@directus/api 19.3.1 → 20.0.0-rc.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (285) hide show
  1. package/dist/app.js +4 -4
  2. package/dist/auth/drivers/ldap.js +4 -4
  3. package/dist/auth/drivers/local.js +4 -4
  4. package/dist/auth/drivers/oauth2.js +4 -4
  5. package/dist/auth/drivers/openid.js +2 -4
  6. package/dist/cache.js +3 -0
  7. package/dist/cli/commands/bootstrap/index.js +8 -2
  8. package/dist/cli/commands/init/index.js +9 -10
  9. package/dist/cli/utils/defaults.d.ts +4 -11
  10. package/dist/cli/utils/defaults.js +7 -1
  11. package/dist/constants.d.ts +1 -1
  12. package/dist/controllers/access.d.ts +2 -0
  13. package/dist/controllers/access.js +148 -0
  14. package/dist/controllers/auth.js +5 -16
  15. package/dist/controllers/permissions.js +14 -2
  16. package/dist/controllers/policies.d.ts +2 -0
  17. package/dist/controllers/policies.js +169 -0
  18. package/dist/controllers/roles.js +22 -1
  19. package/dist/controllers/users.js +0 -55
  20. package/dist/database/errors/dialects/mysql.js +23 -23
  21. package/dist/database/get-ast-from-query/get-ast-from-query.d.ts +16 -0
  22. package/dist/database/get-ast-from-query/get-ast-from-query.js +82 -0
  23. package/dist/database/get-ast-from-query/lib/convert-wildcards.d.ts +13 -0
  24. package/dist/database/get-ast-from-query/lib/convert-wildcards.js +69 -0
  25. package/dist/database/get-ast-from-query/lib/parse-fields.d.ts +15 -0
  26. package/dist/database/get-ast-from-query/lib/parse-fields.js +190 -0
  27. package/dist/database/get-ast-from-query/utils/get-deep-query.d.ts +14 -0
  28. package/dist/database/get-ast-from-query/utils/get-deep-query.js +17 -0
  29. package/dist/database/get-ast-from-query/utils/get-related-collection.d.ts +2 -0
  30. package/dist/database/get-ast-from-query/utils/get-related-collection.js +13 -0
  31. package/dist/database/get-ast-from-query/utils/get-relation.d.ts +2 -0
  32. package/dist/database/get-ast-from-query/utils/get-relation.js +7 -0
  33. package/dist/database/helpers/fn/types.d.ts +2 -1
  34. package/dist/database/helpers/fn/types.js +1 -1
  35. package/dist/database/helpers/geometry/dialects/mssql.d.ts +1 -1
  36. package/dist/database/helpers/geometry/dialects/mssql.js +4 -2
  37. package/dist/database/helpers/geometry/dialects/mysql.js +1 -1
  38. package/dist/database/helpers/geometry/dialects/oracle.d.ts +1 -1
  39. package/dist/database/helpers/geometry/dialects/oracle.js +5 -3
  40. package/dist/database/helpers/geometry/types.d.ts +1 -1
  41. package/dist/database/helpers/geometry/types.js +4 -2
  42. package/dist/database/index.js +2 -1
  43. package/dist/database/migrations/20240619A-permissions-policies.d.ts +3 -0
  44. package/dist/database/migrations/20240619A-permissions-policies.js +163 -0
  45. package/dist/database/run-ast/lib/get-db-query.d.ts +4 -0
  46. package/dist/database/run-ast/lib/get-db-query.js +194 -0
  47. package/dist/database/run-ast/lib/parse-current-level.d.ts +7 -0
  48. package/dist/database/run-ast/lib/parse-current-level.js +41 -0
  49. package/dist/database/run-ast/run-ast.d.ts +7 -0
  50. package/dist/database/run-ast/run-ast.js +107 -0
  51. package/dist/database/{run-ast.d.ts → run-ast/types.d.ts} +3 -9
  52. package/dist/database/run-ast/types.js +1 -0
  53. package/dist/database/run-ast/utils/apply-case-when.d.ts +16 -0
  54. package/dist/database/run-ast/utils/apply-case-when.js +26 -0
  55. package/dist/database/run-ast/utils/apply-parent-filters.d.ts +3 -0
  56. package/dist/database/run-ast/utils/apply-parent-filters.js +55 -0
  57. package/dist/database/run-ast/utils/get-column-pre-processor.d.ts +10 -0
  58. package/dist/database/run-ast/utils/get-column-pre-processor.js +57 -0
  59. package/dist/database/run-ast/utils/get-field-alias.d.ts +2 -0
  60. package/dist/database/run-ast/utils/get-field-alias.js +4 -0
  61. package/dist/database/run-ast/utils/get-inner-query-column-pre-processor.d.ts +5 -0
  62. package/dist/database/run-ast/utils/get-inner-query-column-pre-processor.js +23 -0
  63. package/dist/database/run-ast/utils/merge-with-parent-items.d.ts +3 -0
  64. package/dist/database/run-ast/utils/merge-with-parent-items.js +87 -0
  65. package/dist/database/run-ast/utils/remove-temporary-fields.d.ts +3 -0
  66. package/dist/database/run-ast/utils/remove-temporary-fields.js +73 -0
  67. package/dist/extensions/lib/sandbox/generate-api-extensions-sandbox-entrypoint.d.ts +1 -1
  68. package/dist/flows.js +3 -4
  69. package/dist/middleware/authenticate.js +2 -7
  70. package/dist/middleware/cache.js +1 -1
  71. package/dist/middleware/cors.js +4 -4
  72. package/dist/middleware/respond.js +1 -1
  73. package/dist/permissions/cache.d.ts +2 -0
  74. package/dist/permissions/cache.js +23 -0
  75. package/dist/permissions/lib/fetch-permissions.d.ts +10 -0
  76. package/dist/permissions/lib/fetch-permissions.js +55 -0
  77. package/dist/permissions/lib/fetch-policies.d.ts +7 -0
  78. package/dist/permissions/lib/fetch-policies.js +28 -0
  79. package/dist/permissions/lib/fetch-roles-tree.d.ts +3 -0
  80. package/dist/permissions/lib/fetch-roles-tree.js +28 -0
  81. package/dist/{services/permissions → permissions}/lib/with-app-minimal-permissions.d.ts +1 -1
  82. package/dist/permissions/lib/with-app-minimal-permissions.js +10 -0
  83. package/dist/permissions/modules/fetch-accountability-collection-access/fetch-accountability-collection-access.d.ts +7 -0
  84. package/dist/permissions/modules/fetch-accountability-collection-access/fetch-accountability-collection-access.js +56 -0
  85. package/dist/permissions/modules/fetch-accountability-policy-globals/fetch-accountability-policy-globals.d.ts +3 -0
  86. package/dist/permissions/modules/fetch-accountability-policy-globals/fetch-accountability-policy-globals.js +16 -0
  87. package/dist/permissions/modules/fetch-allowed-collections/fetch-allowed-collections.d.ts +8 -0
  88. package/dist/permissions/modules/fetch-allowed-collections/fetch-allowed-collections.js +24 -0
  89. package/dist/permissions/modules/fetch-allowed-field-map/fetch-allowed-field-map.d.ts +9 -0
  90. package/dist/permissions/modules/fetch-allowed-field-map/fetch-allowed-field-map.js +31 -0
  91. package/dist/permissions/modules/fetch-allowed-fields/fetch-allowed-fields.d.ts +16 -0
  92. package/dist/permissions/modules/fetch-allowed-fields/fetch-allowed-fields.js +27 -0
  93. package/dist/permissions/modules/fetch-global-access/fetch-global-access.d.ts +10 -0
  94. package/dist/permissions/modules/fetch-global-access/fetch-global-access.js +23 -0
  95. package/dist/permissions/modules/fetch-global-access/lib/fetch-global-access-for-roles.d.ts +5 -0
  96. package/dist/permissions/modules/fetch-global-access/lib/fetch-global-access-for-roles.js +7 -0
  97. package/dist/permissions/modules/fetch-global-access/lib/fetch-global-access-for-user.d.ts +5 -0
  98. package/dist/permissions/modules/fetch-global-access/lib/fetch-global-access-for-user.js +10 -0
  99. package/dist/permissions/modules/fetch-global-access/types.d.ts +4 -0
  100. package/dist/permissions/modules/fetch-global-access/types.js +1 -0
  101. package/dist/permissions/modules/fetch-global-access/utils/fetch-global-access-for-query.d.ts +4 -0
  102. package/dist/permissions/modules/fetch-global-access/utils/fetch-global-access-for-query.js +27 -0
  103. package/dist/permissions/modules/fetch-inconsistent-field-map/fetch-inconsistent-field-map.d.ts +12 -0
  104. package/dist/permissions/modules/fetch-inconsistent-field-map/fetch-inconsistent-field-map.js +32 -0
  105. package/dist/permissions/modules/fetch-policies-ip-access/fetch-policies-ip-access.d.ts +4 -0
  106. package/dist/permissions/modules/fetch-policies-ip-access/fetch-policies-ip-access.js +29 -0
  107. package/dist/permissions/modules/process-ast/lib/extract-fields-from-children.d.ts +4 -0
  108. package/dist/permissions/modules/process-ast/lib/extract-fields-from-children.js +49 -0
  109. package/dist/permissions/modules/process-ast/lib/extract-fields-from-query.d.ts +3 -0
  110. package/dist/permissions/modules/process-ast/lib/extract-fields-from-query.js +56 -0
  111. package/dist/permissions/modules/process-ast/lib/field-map-from-ast.d.ts +4 -0
  112. package/dist/permissions/modules/process-ast/lib/field-map-from-ast.js +8 -0
  113. package/dist/permissions/modules/process-ast/lib/inject-cases.d.ts +9 -0
  114. package/dist/permissions/modules/process-ast/lib/inject-cases.js +93 -0
  115. package/dist/permissions/modules/process-ast/process-ast.d.ts +9 -0
  116. package/dist/permissions/modules/process-ast/process-ast.js +39 -0
  117. package/dist/permissions/modules/process-ast/types.d.ts +24 -0
  118. package/dist/permissions/modules/process-ast/types.js +1 -0
  119. package/dist/permissions/modules/process-ast/utils/collections-in-field-map.d.ts +2 -0
  120. package/dist/permissions/modules/process-ast/utils/collections-in-field-map.js +7 -0
  121. package/dist/permissions/modules/process-ast/utils/dedupe-access.d.ts +12 -0
  122. package/dist/permissions/modules/process-ast/utils/dedupe-access.js +30 -0
  123. package/dist/permissions/modules/process-ast/utils/extract-paths-from-query.d.ts +15 -0
  124. package/dist/permissions/modules/process-ast/utils/extract-paths-from-query.js +50 -0
  125. package/dist/permissions/modules/process-ast/utils/find-related-collection.d.ts +3 -0
  126. package/dist/permissions/modules/process-ast/utils/find-related-collection.js +9 -0
  127. package/dist/permissions/modules/process-ast/utils/flatten-filter.d.ts +3 -0
  128. package/dist/permissions/modules/process-ast/utils/flatten-filter.js +24 -0
  129. package/dist/permissions/modules/process-ast/utils/format-a2o-key.d.ts +1 -0
  130. package/dist/permissions/modules/process-ast/utils/format-a2o-key.js +3 -0
  131. package/dist/permissions/modules/process-ast/utils/get-info-for-path.d.ts +5 -0
  132. package/dist/permissions/modules/process-ast/utils/get-info-for-path.js +7 -0
  133. package/dist/permissions/modules/process-ast/utils/has-item-permissions.d.ts +2 -0
  134. package/dist/permissions/modules/process-ast/utils/has-item-permissions.js +3 -0
  135. package/dist/permissions/modules/process-ast/utils/stringify-query-path.d.ts +2 -0
  136. package/dist/permissions/modules/process-ast/utils/stringify-query-path.js +3 -0
  137. package/dist/permissions/modules/process-ast/utils/validate-path/create-error.d.ts +3 -0
  138. package/dist/permissions/modules/process-ast/utils/validate-path/create-error.js +16 -0
  139. package/dist/permissions/modules/process-ast/utils/validate-path/validate-path-existence.d.ts +2 -0
  140. package/dist/permissions/modules/process-ast/utils/validate-path/validate-path-existence.js +12 -0
  141. package/dist/permissions/modules/process-ast/utils/validate-path/validate-path-permissions.d.ts +2 -0
  142. package/dist/permissions/modules/process-ast/utils/validate-path/validate-path-permissions.js +28 -0
  143. package/dist/permissions/modules/process-payload/lib/is-field-nullable.d.ts +5 -0
  144. package/dist/permissions/modules/process-payload/lib/is-field-nullable.js +12 -0
  145. package/dist/permissions/modules/process-payload/process-payload.d.ts +13 -0
  146. package/dist/permissions/modules/process-payload/process-payload.js +77 -0
  147. package/dist/permissions/modules/validate-access/lib/validate-collection-access.d.ts +12 -0
  148. package/dist/permissions/modules/validate-access/lib/validate-collection-access.js +11 -0
  149. package/dist/permissions/modules/validate-access/lib/validate-item-access.d.ts +9 -0
  150. package/dist/permissions/modules/validate-access/lib/validate-item-access.js +33 -0
  151. package/dist/permissions/modules/validate-access/validate-access.d.ts +14 -0
  152. package/dist/permissions/modules/validate-access/validate-access.js +28 -0
  153. package/dist/permissions/modules/validate-remaining-admin/validate-remaining-admin-count.d.ts +1 -0
  154. package/dist/permissions/modules/validate-remaining-admin/validate-remaining-admin-count.js +8 -0
  155. package/dist/permissions/modules/validate-remaining-admin/validate-remaining-admin-users.d.ts +5 -0
  156. package/dist/permissions/modules/validate-remaining-admin/validate-remaining-admin-users.js +10 -0
  157. package/dist/permissions/types.d.ts +6 -0
  158. package/dist/permissions/types.js +1 -0
  159. package/dist/permissions/utils/create-default-accountability.d.ts +2 -0
  160. package/dist/permissions/utils/create-default-accountability.js +11 -0
  161. package/dist/permissions/utils/extract-required-dynamic-variable-context.d.ts +8 -0
  162. package/dist/permissions/utils/extract-required-dynamic-variable-context.js +27 -0
  163. package/dist/permissions/utils/fetch-dynamic-variable-context.d.ts +9 -0
  164. package/dist/permissions/utils/fetch-dynamic-variable-context.js +43 -0
  165. package/dist/permissions/utils/filter-policies-by-ip.d.ts +2 -0
  166. package/dist/permissions/utils/filter-policies-by-ip.js +15 -0
  167. package/dist/permissions/utils/get-unaliased-field-key.d.ts +5 -0
  168. package/dist/permissions/utils/get-unaliased-field-key.js +17 -0
  169. package/dist/permissions/utils/process-permissions.d.ts +7 -0
  170. package/dist/permissions/utils/process-permissions.js +9 -0
  171. package/dist/permissions/utils/with-cache.d.ts +10 -0
  172. package/dist/permissions/utils/with-cache.js +25 -0
  173. package/dist/services/access.d.ts +10 -0
  174. package/dist/services/access.js +43 -0
  175. package/dist/services/activity.js +22 -10
  176. package/dist/services/assets.d.ts +2 -3
  177. package/dist/services/assets.js +10 -5
  178. package/dist/services/authentication.js +18 -18
  179. package/dist/services/collections.js +18 -17
  180. package/dist/services/fields.d.ts +0 -1
  181. package/dist/services/fields.js +53 -24
  182. package/dist/services/files.d.ts +0 -4
  183. package/dist/services/files.js +10 -10
  184. package/dist/services/flows.d.ts +0 -2
  185. package/dist/services/flows.js +2 -14
  186. package/dist/services/graphql/index.d.ts +3 -3
  187. package/dist/services/graphql/index.js +126 -22
  188. package/dist/services/graphql/subscription.js +2 -4
  189. package/dist/services/import-export.js +23 -9
  190. package/dist/services/index.d.ts +3 -2
  191. package/dist/services/index.js +3 -2
  192. package/dist/services/items.d.ts +40 -14
  193. package/dist/services/items.js +182 -79
  194. package/dist/services/meta.js +60 -23
  195. package/dist/services/notifications.d.ts +0 -1
  196. package/dist/services/notifications.js +0 -7
  197. package/dist/services/operations.d.ts +0 -2
  198. package/dist/services/operations.js +2 -14
  199. package/dist/services/payload.d.ts +9 -10
  200. package/dist/services/payload.js +35 -19
  201. package/dist/services/{permissions/index.d.ts → permissions.d.ts} +5 -7
  202. package/dist/services/{permissions/index.js → permissions.js} +30 -54
  203. package/dist/services/policies.d.ts +12 -0
  204. package/dist/services/policies.js +87 -0
  205. package/dist/services/relations.d.ts +0 -6
  206. package/dist/services/relations.js +26 -29
  207. package/dist/services/roles.d.ts +4 -14
  208. package/dist/services/roles.js +56 -430
  209. package/dist/services/shares.d.ts +0 -2
  210. package/dist/services/shares.js +12 -8
  211. package/dist/services/specifications.d.ts +2 -2
  212. package/dist/services/specifications.js +39 -27
  213. package/dist/services/users.d.ts +2 -20
  214. package/dist/services/users.js +87 -192
  215. package/dist/services/utils.js +11 -7
  216. package/dist/services/versions.d.ts +0 -2
  217. package/dist/services/versions.js +34 -10
  218. package/dist/telemetry/lib/get-report.js +6 -3
  219. package/dist/telemetry/types/report.d.ts +4 -0
  220. package/dist/telemetry/utils/check-user-limits.d.ts +5 -0
  221. package/dist/telemetry/utils/check-user-limits.js +19 -0
  222. package/dist/telemetry/utils/get-filesize-sum.d.ts +5 -0
  223. package/dist/telemetry/utils/get-filesize-sum.js +7 -0
  224. package/dist/types/ast.d.ts +43 -1
  225. package/dist/types/items.d.ts +11 -0
  226. package/dist/utils/apply-query.d.ts +4 -3
  227. package/dist/utils/apply-query.js +37 -8
  228. package/dist/utils/fetch-user-count/fetch-access-lookup.d.ts +17 -0
  229. package/dist/utils/fetch-user-count/fetch-access-lookup.js +22 -0
  230. package/dist/utils/fetch-user-count/fetch-access-roles.d.ts +16 -0
  231. package/dist/utils/fetch-user-count/fetch-access-roles.js +37 -0
  232. package/dist/utils/fetch-user-count/fetch-active-users.d.ts +6 -0
  233. package/dist/utils/fetch-user-count/fetch-active-users.js +3 -0
  234. package/dist/utils/fetch-user-count/fetch-user-count.d.ts +12 -0
  235. package/dist/utils/fetch-user-count/fetch-user-count.js +57 -0
  236. package/dist/utils/fetch-user-count/get-user-count-query.d.ts +20 -0
  237. package/dist/utils/fetch-user-count/get-user-count-query.js +17 -0
  238. package/dist/utils/get-accountability-for-role.js +16 -25
  239. package/dist/utils/get-accountability-for-token.js +17 -16
  240. package/dist/utils/get-cache-key.d.ts +1 -1
  241. package/dist/utils/get-cache-key.js +12 -1
  242. package/dist/utils/get-column.d.ts +2 -1
  243. package/dist/utils/get-column.js +1 -0
  244. package/dist/utils/get-graphql-type.js +1 -0
  245. package/dist/utils/get-service.d.ts +1 -1
  246. package/dist/utils/get-service.js +14 -10
  247. package/dist/utils/reduce-schema.d.ts +4 -6
  248. package/dist/utils/reduce-schema.js +14 -34
  249. package/dist/utils/validate-user-count-integrity.d.ts +13 -0
  250. package/dist/utils/validate-user-count-integrity.js +29 -0
  251. package/dist/websocket/authenticate.d.ts +0 -2
  252. package/dist/websocket/authenticate.js +0 -12
  253. package/dist/websocket/controllers/graphql.js +1 -4
  254. package/dist/websocket/controllers/hooks.js +4 -0
  255. package/dist/websocket/controllers/rest.js +0 -2
  256. package/dist/websocket/handlers/subscribe.js +0 -2
  257. package/dist/websocket/utils/items.d.ts +1 -1
  258. package/dist/websocket/utils/items.js +4 -1
  259. package/package.json +31 -30
  260. package/dist/database/run-ast.js +0 -450
  261. package/dist/middleware/check-ip.d.ts +0 -2
  262. package/dist/middleware/check-ip.js +0 -37
  263. package/dist/middleware/get-permissions.d.ts +0 -3
  264. package/dist/middleware/get-permissions.js +0 -10
  265. package/dist/services/authorization.d.ts +0 -17
  266. package/dist/services/authorization.js +0 -456
  267. package/dist/services/permissions/lib/with-app-minimal-permissions.js +0 -13
  268. package/dist/telemetry/utils/check-increased-user-limits.d.ts +0 -7
  269. package/dist/telemetry/utils/check-increased-user-limits.js +0 -22
  270. package/dist/telemetry/utils/get-role-counts-by-roles.d.ts +0 -6
  271. package/dist/telemetry/utils/get-role-counts-by-roles.js +0 -27
  272. package/dist/telemetry/utils/get-role-counts-by-users.d.ts +0 -11
  273. package/dist/telemetry/utils/get-role-counts-by-users.js +0 -34
  274. package/dist/telemetry/utils/get-user-count.d.ts +0 -8
  275. package/dist/telemetry/utils/get-user-count.js +0 -33
  276. package/dist/telemetry/utils/get-user-counts-by-roles.d.ts +0 -7
  277. package/dist/telemetry/utils/get-user-counts-by-roles.js +0 -35
  278. package/dist/utils/get-ast-from-query.d.ts +0 -13
  279. package/dist/utils/get-ast-from-query.js +0 -297
  280. package/dist/utils/get-permissions.d.ts +0 -2
  281. package/dist/utils/get-permissions.js +0 -150
  282. package/dist/utils/merge-permissions-for-share.d.ts +0 -4
  283. package/dist/utils/merge-permissions-for-share.js +0 -109
  284. package/dist/utils/merge-permissions.d.ts +0 -3
  285. package/dist/utils/merge-permissions.js +0 -95
@@ -5,32 +5,20 @@ export class OperationsService extends ItemsService {
5
5
  super('directus_operations', options);
6
6
  }
7
7
  async createOne(data, opts) {
8
- const flowManager = getFlowManager();
9
8
  const result = await super.createOne(data, opts);
10
- await flowManager.reload();
11
- return result;
12
- }
13
- async createMany(data, opts) {
14
- const flowManager = getFlowManager();
15
- const result = await super.createMany(data, opts);
16
- await flowManager.reload();
17
- return result;
18
- }
19
- async updateBatch(data, opts) {
20
9
  const flowManager = getFlowManager();
21
- const result = await super.updateBatch(data, opts);
22
10
  await flowManager.reload();
23
11
  return result;
24
12
  }
25
13
  async updateMany(keys, data, opts) {
26
- const flowManager = getFlowManager();
27
14
  const result = await super.updateMany(keys, data, opts);
15
+ const flowManager = getFlowManager();
28
16
  await flowManager.reload();
29
17
  return result;
30
18
  }
31
19
  async deleteMany(keys, opts) {
32
- const flowManager = getFlowManager();
33
20
  const result = await super.deleteMany(keys, opts);
21
+ const flowManager = getFlowManager();
34
22
  await flowManager.reload();
35
23
  return result;
36
24
  }
@@ -2,6 +2,7 @@ import type { Accountability, Item, PrimaryKey, SchemaOverview } from '@directus
2
2
  import type { Knex } from 'knex';
3
3
  import type { Helpers } from '../database/helpers/index.js';
4
4
  import type { AbstractServiceOptions, ActionEventParams, MutationOptions } from '../types/index.js';
5
+ import { UserIntegrityCheckFlag } from '../utils/validate-user-count-integrity.js';
5
6
  type Action = 'create' | 'read' | 'update';
6
7
  type Transformers = {
7
8
  [type: string]: (context: {
@@ -13,6 +14,11 @@ type Transformers = {
13
14
  helpers: Helpers;
14
15
  }) => Promise<any>;
15
16
  };
17
+ type PayloadServiceProcessRelationResult = {
18
+ revisions: PrimaryKey[];
19
+ nestedActionEvents: ActionEventParams[];
20
+ userIntegrityCheckFlags: UserIntegrityCheckFlag;
21
+ };
16
22
  /**
17
23
  * Process a given payload for a collection to ensure the special fields (hash, uuid, date etc) are
18
24
  * handled correctly.
@@ -46,26 +52,19 @@ export declare class PayloadService {
46
52
  /**
47
53
  * Recursively save/update all nested related Any-to-One items
48
54
  */
49
- processA2O(data: Partial<Item>, opts?: MutationOptions): Promise<{
55
+ processA2O(data: Partial<Item>, opts?: MutationOptions): Promise<PayloadServiceProcessRelationResult & {
50
56
  payload: Partial<Item>;
51
- revisions: PrimaryKey[];
52
- nestedActionEvents: ActionEventParams[];
53
57
  }>;
54
58
  /**
55
59
  * Save/update all nested related m2o items inside the payload
56
60
  */
57
- processM2O(data: Partial<Item>, opts?: MutationOptions): Promise<{
61
+ processM2O(data: Partial<Item>, opts?: MutationOptions): Promise<PayloadServiceProcessRelationResult & {
58
62
  payload: Partial<Item>;
59
- revisions: PrimaryKey[];
60
- nestedActionEvents: ActionEventParams[];
61
63
  }>;
62
64
  /**
63
65
  * Recursively save/update all nested related o2m items
64
66
  */
65
- processO2M(data: Partial<Item>, parent: PrimaryKey, opts?: MutationOptions): Promise<{
66
- revisions: PrimaryKey[];
67
- nestedActionEvents: ActionEventParams[];
68
- }>;
67
+ processO2M(data: Partial<Item>, parent: PrimaryKey, opts?: MutationOptions): Promise<PayloadServiceProcessRelationResult>;
69
68
  /**
70
69
  * Transforms the input partial payload to match the output structure, to have consistency
71
70
  * between delta and data
@@ -9,7 +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 { ItemsService } from './items.js';
12
+ import { UserIntegrityCheckFlag } from '../utils/validate-user-count-integrity.js';
13
13
  /**
14
14
  * Process a given payload for a collection to ensure the special fields (hash, uuid, date etc) are
15
15
  * handled correctly.
@@ -318,6 +318,7 @@ export class PayloadService {
318
318
  return relation.collection === this.collection;
319
319
  });
320
320
  const revisions = [];
321
+ let userIntegrityCheckFlags = UserIntegrityCheckFlag.None;
321
322
  const nestedActionEvents = [];
322
323
  const payload = cloneDeep(data);
323
324
  // Only process related records that are actually in the payload
@@ -340,7 +341,8 @@ export class PayloadService {
340
341
  reason: `"${relation.collection}.${relation.field}" can't be linked to collection "${relatedCollection}"`,
341
342
  });
342
343
  }
343
- const itemsService = new ItemsService(relatedCollection, {
344
+ const { getService } = await import('../utils/get-service.js');
345
+ const service = getService(relatedCollection, {
344
346
  accountability: this.accountability,
345
347
  knex: this.knex,
346
348
  schema: this.schema,
@@ -360,8 +362,9 @@ export class PayloadService {
360
362
  if (exists) {
361
363
  const fieldsToUpdate = omit(relatedRecord, relatedPrimary);
362
364
  if (Object.keys(fieldsToUpdate).length > 0) {
363
- await itemsService.updateOne(relatedPrimaryKey, relatedRecord, {
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,
@@ -369,8 +372,9 @@ export class PayloadService {
369
372
  }
370
373
  }
371
374
  else {
372
- relatedPrimaryKey = await itemsService.createOne(relatedRecord, {
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) => {
@@ -402,8 +407,8 @@ export class PayloadService {
402
407
  if (!relation.related_collection)
403
408
  continue;
404
409
  const relatedPrimaryKeyField = this.schema.collections[relation.related_collection].primary;
405
- // Items service to the related collection
406
- const itemsService = new ItemsService(relation.related_collection, {
410
+ const { getService } = await import('../utils/get-service.js');
411
+ const service = getService(relation.related_collection, {
407
412
  accountability: this.accountability,
408
413
  knex: this.knex,
409
414
  schema: this.schema,
@@ -422,8 +427,9 @@ export class PayloadService {
422
427
  if (exists) {
423
428
  const fieldsToUpdate = omit(relatedRecord, relatedPrimaryKeyField);
424
429
  if (Object.keys(fieldsToUpdate).length > 0) {
425
- await itemsService.updateOne(relatedPrimaryKey, relatedRecord, {
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,
@@ -431,8 +437,9 @@ export class PayloadService {
431
437
  }
432
438
  }
433
439
  else {
434
- relatedPrimaryKey = await itemsService.createOne(relatedRecord, {
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;
@@ -469,7 +477,8 @@ export class PayloadService {
469
477
  continue;
470
478
  const currentPrimaryKeyField = this.schema.collections[relation.related_collection].primary;
471
479
  const relatedPrimaryKeyField = this.schema.collections[relation.collection].primary;
472
- const itemsService = new ItemsService(relation.collection, {
480
+ const { getService } = await import('../utils/get-service.js');
481
+ const service = getService(relation.collection, {
473
482
  accountability: this.accountability,
474
483
  knex: this.knex,
475
484
  schema: this.schema,
@@ -513,8 +522,9 @@ export class PayloadService {
513
522
  [relation.field]: parent || payload[currentPrimaryKeyField],
514
523
  });
515
524
  }
516
- savedPrimaryKeys.push(...(await itemsService.upsertMany(recordsToUpsert, {
525
+ savedPrimaryKeys.push(...(await service.upsertMany(recordsToUpsert, {
517
526
  onRevisionCreate: (pk) => revisions.push(pk),
527
+ onRequireUserIntegrityCheck: (flags) => (userIntegrityCheckFlags |= flags),
518
528
  bypassEmitAction: (params) => opts?.bypassEmitAction ? opts.bypassEmitAction(params) : nestedActionEvents.push(params),
519
529
  emitEvents: opts?.emitEvents,
520
530
  mutationTracker: opts?.mutationTracker,
@@ -538,15 +548,17 @@ export class PayloadService {
538
548
  // Nullify all related items that aren't included in the current payload
539
549
  if (relation.meta.one_deselect_action === 'delete') {
540
550
  // There's no revision for a deletion
541
- await itemsService.deleteByQuery(query, {
551
+ await service.deleteByQuery(query, {
552
+ onRequireUserIntegrityCheck: (flags) => (userIntegrityCheckFlags |= flags),
542
553
  bypassEmitAction: (params) => opts?.bypassEmitAction ? opts.bypassEmitAction(params) : nestedActionEvents.push(params),
543
554
  emitEvents: opts?.emitEvents,
544
555
  mutationTracker: opts?.mutationTracker,
545
556
  });
546
557
  }
547
558
  else {
548
- await itemsService.updateByQuery(query, { [relation.field]: null }, {
559
+ await service.updateByQuery(query, { [relation.field]: null }, {
549
560
  onRevisionCreate: (pk) => revisions.push(pk),
561
+ onRequireUserIntegrityCheck: (flags) => (userIntegrityCheckFlags |= flags),
550
562
  bypassEmitAction: (params) => opts?.bypassEmitAction ? opts.bypassEmitAction(params) : nestedActionEvents.push(params),
551
563
  emitEvents: opts?.emitEvents,
552
564
  mutationTracker: opts?.mutationTracker,
@@ -587,8 +599,9 @@ export class PayloadService {
587
599
  [relation.field]: parent || payload[currentPrimaryKeyField],
588
600
  }));
589
601
  }
590
- await itemsService.createMany(createPayload, {
602
+ await service.createMany(createPayload, {
591
603
  onRevisionCreate: (pk) => revisions.push(pk),
604
+ onRequireUserIntegrityCheck: (flags) => (userIntegrityCheckFlags |= flags),
592
605
  bypassEmitAction: (params) => opts?.bypassEmitAction ? opts.bypassEmitAction(params) : nestedActionEvents.push(params),
593
606
  emitEvents: opts?.emitEvents,
594
607
  mutationTracker: opts?.mutationTracker,
@@ -597,11 +610,12 @@ export class PayloadService {
597
610
  if (alterations.update) {
598
611
  const primaryKeyField = this.schema.collections[relation.collection].primary;
599
612
  for (const item of alterations.update) {
600
- await itemsService.updateOne(item[primaryKeyField], {
613
+ await service.updateOne(item[primaryKeyField], {
601
614
  ...item,
602
615
  [relation.field]: parent || payload[currentPrimaryKeyField],
603
616
  }, {
604
617
  onRevisionCreate: (pk) => revisions.push(pk),
618
+ onRequireUserIntegrityCheck: (flags) => (userIntegrityCheckFlags |= flags),
605
619
  bypassEmitAction: (params) => opts?.bypassEmitAction ? opts.bypassEmitAction(params) : nestedActionEvents.push(params),
606
620
  emitEvents: opts?.emitEvents,
607
621
  mutationTracker: opts?.mutationTracker,
@@ -626,15 +640,17 @@ export class PayloadService {
626
640
  },
627
641
  };
628
642
  if (relation.meta.one_deselect_action === 'delete') {
629
- await itemsService.deleteByQuery(query, {
643
+ await service.deleteByQuery(query, {
644
+ onRequireUserIntegrityCheck: (flags) => (userIntegrityCheckFlags |= flags),
630
645
  bypassEmitAction: (params) => opts?.bypassEmitAction ? opts.bypassEmitAction(params) : nestedActionEvents.push(params),
631
646
  emitEvents: opts?.emitEvents,
632
647
  mutationTracker: opts?.mutationTracker,
633
648
  });
634
649
  }
635
650
  else {
636
- await itemsService.updateByQuery(query, { [relation.field]: null }, {
651
+ await service.updateByQuery(query, { [relation.field]: null }, {
637
652
  onRevisionCreate: (pk) => revisions.push(pk),
653
+ onRequireUserIntegrityCheck: (flags) => (userIntegrityCheckFlags |= flags),
638
654
  bypassEmitAction: (params) => opts?.bypassEmitAction ? opts.bypassEmitAction(params) : nestedActionEvents.push(params),
639
655
  emitEvents: opts?.emitEvents,
640
656
  mutationTracker: opts?.mutationTracker,
@@ -643,7 +659,7 @@ export class PayloadService {
643
659
  }
644
660
  }
645
661
  }
646
- return { revisions, nestedActionEvents };
662
+ return { revisions, nestedActionEvents, userIntegrityCheckFlags };
647
663
  }
648
664
  /**
649
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;
@@ -32,10 +30,6 @@ export declare class RelationsService {
32
30
  * Delete an existing relationship
33
31
  */
34
32
  deleteOne(collection: string, field: string, opts?: MutationOptions): Promise<void>;
35
- /**
36
- * Whether or not the current user has read access to relations
37
- */
38
- private get hasReadAccess();
39
33
  /**
40
34
  * Combine raw schema foreign key information with Directus relations meta rows to form final
41
35
  * Relation objects