@directus/api 20.0.0-rc.0 → 20.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (291) hide show
  1. package/dist/app.js +9 -4
  2. package/dist/auth/drivers/ldap.js +4 -4
  3. package/dist/auth/drivers/local.js +4 -4
  4. package/dist/auth/drivers/oauth2.js +4 -4
  5. package/dist/auth/drivers/openid.js +4 -2
  6. package/dist/cache.js +0 -3
  7. package/dist/cli/commands/bootstrap/index.js +2 -8
  8. package/dist/cli/commands/init/index.js +10 -9
  9. package/dist/cli/utils/defaults.d.ts +11 -4
  10. package/dist/cli/utils/defaults.js +1 -7
  11. package/dist/constants.d.ts +9 -1
  12. package/dist/constants.js +10 -0
  13. package/dist/controllers/auth.js +16 -5
  14. package/dist/controllers/permissions.js +2 -14
  15. package/dist/controllers/roles.js +1 -22
  16. package/dist/controllers/{access.d.ts → tus.d.ts} +1 -0
  17. package/dist/controllers/tus.js +72 -0
  18. package/dist/controllers/users.js +55 -0
  19. package/dist/database/helpers/fn/types.d.ts +1 -2
  20. package/dist/database/helpers/fn/types.js +1 -1
  21. package/dist/database/helpers/geometry/dialects/mssql.d.ts +1 -1
  22. package/dist/database/helpers/geometry/dialects/mssql.js +2 -4
  23. package/dist/database/helpers/geometry/dialects/mysql.js +1 -1
  24. package/dist/database/helpers/geometry/dialects/oracle.d.ts +1 -1
  25. package/dist/database/helpers/geometry/dialects/oracle.js +3 -5
  26. package/dist/database/helpers/geometry/types.d.ts +1 -1
  27. package/dist/database/helpers/geometry/types.js +2 -4
  28. package/dist/database/index.js +1 -2
  29. package/dist/database/migrations/20240701A-add-tus-data.js +12 -0
  30. package/dist/database/{run-ast/types.d.ts → run-ast.d.ts} +9 -3
  31. package/dist/database/run-ast.js +450 -0
  32. package/dist/flows.js +4 -3
  33. package/dist/middleware/authenticate.js +7 -2
  34. package/dist/middleware/cache.js +1 -1
  35. package/dist/middleware/check-ip.d.ts +2 -0
  36. package/dist/middleware/check-ip.js +37 -0
  37. package/dist/middleware/get-permissions.d.ts +3 -0
  38. package/dist/middleware/get-permissions.js +10 -0
  39. package/dist/middleware/respond.js +1 -1
  40. package/dist/services/activity.js +10 -22
  41. package/dist/services/assets.d.ts +3 -2
  42. package/dist/services/assets.js +5 -10
  43. package/dist/services/authentication.js +26 -32
  44. package/dist/services/authorization.d.ts +17 -0
  45. package/dist/services/authorization.js +456 -0
  46. package/dist/services/collections.js +17 -18
  47. package/dist/services/fields.d.ts +1 -0
  48. package/dist/services/fields.js +24 -53
  49. package/dist/services/files/lib/extract-metadata.d.ts +3 -0
  50. package/dist/services/files/lib/extract-metadata.js +32 -0
  51. package/dist/services/files/utils/get-metadata.d.ts +5 -0
  52. package/dist/services/files/utils/get-metadata.js +107 -0
  53. package/dist/services/files.d.ts +4 -6
  54. package/dist/services/files.js +24 -140
  55. package/dist/services/graphql/index.d.ts +3 -3
  56. package/dist/services/graphql/index.js +22 -126
  57. package/dist/services/graphql/subscription.js +4 -2
  58. package/dist/services/import-export.js +4 -18
  59. package/dist/services/index.d.ts +2 -3
  60. package/dist/services/index.js +2 -3
  61. package/dist/services/items.js +44 -115
  62. package/dist/services/meta.js +23 -60
  63. package/dist/services/payload.d.ts +10 -9
  64. package/dist/services/payload.js +3 -18
  65. package/dist/services/{permissions.d.ts → permissions/index.d.ts} +7 -5
  66. package/dist/services/{permissions.js → permissions/index.js} +54 -30
  67. package/dist/{permissions → services/permissions}/lib/with-app-minimal-permissions.d.ts +1 -1
  68. package/dist/services/permissions/lib/with-app-minimal-permissions.js +13 -0
  69. package/dist/services/relations.d.ts +6 -0
  70. package/dist/services/relations.js +29 -26
  71. package/dist/services/roles.d.ts +12 -4
  72. package/dist/services/roles.js +424 -57
  73. package/dist/services/server.js +6 -0
  74. package/dist/services/shares.d.ts +2 -0
  75. package/dist/services/shares.js +8 -12
  76. package/dist/services/specifications.d.ts +2 -2
  77. package/dist/services/specifications.js +27 -39
  78. package/dist/services/tus/data-store.d.ts +36 -0
  79. package/dist/services/tus/data-store.js +214 -0
  80. package/dist/services/tus/index.d.ts +2 -0
  81. package/dist/services/tus/index.js +2 -0
  82. package/dist/services/tus/lockers.d.ts +36 -0
  83. package/dist/services/tus/lockers.js +83 -0
  84. package/dist/services/tus/server.d.ts +8 -0
  85. package/dist/services/tus/server.js +80 -0
  86. package/dist/services/tus/utils/wait-timeout.d.ts +1 -0
  87. package/dist/services/tus/utils/wait-timeout.js +13 -0
  88. package/dist/services/users.d.ts +5 -1
  89. package/dist/services/users.js +161 -78
  90. package/dist/services/utils.js +7 -11
  91. package/dist/services/versions.d.ts +2 -0
  92. package/dist/services/versions.js +10 -34
  93. package/dist/storage/register-locations.js +5 -1
  94. package/dist/telemetry/lib/get-report.js +2 -2
  95. package/dist/telemetry/utils/check-increased-user-limits.d.ts +7 -0
  96. package/dist/telemetry/utils/check-increased-user-limits.js +25 -0
  97. package/dist/telemetry/utils/get-role-counts-by-roles.d.ts +6 -0
  98. package/dist/telemetry/utils/get-role-counts-by-roles.js +27 -0
  99. package/dist/telemetry/utils/get-role-counts-by-users.d.ts +11 -0
  100. package/dist/telemetry/utils/get-role-counts-by-users.js +34 -0
  101. package/dist/telemetry/utils/get-user-count.d.ts +8 -0
  102. package/dist/telemetry/utils/get-user-count.js +33 -0
  103. package/dist/telemetry/utils/get-user-counts-by-roles.d.ts +7 -0
  104. package/dist/telemetry/utils/get-user-counts-by-roles.js +35 -0
  105. package/dist/types/ast.d.ts +1 -43
  106. package/dist/types/items.d.ts +0 -11
  107. package/dist/utils/apply-query.d.ts +3 -4
  108. package/dist/utils/apply-query.js +8 -37
  109. package/dist/utils/get-accountability-for-role.js +25 -16
  110. package/dist/utils/get-accountability-for-token.js +16 -17
  111. package/dist/utils/get-ast-from-query.d.ts +13 -0
  112. package/dist/utils/get-ast-from-query.js +297 -0
  113. package/dist/utils/get-cache-key.d.ts +1 -1
  114. package/dist/utils/get-cache-key.js +1 -12
  115. package/dist/utils/get-column.d.ts +1 -2
  116. package/dist/utils/get-column.js +0 -1
  117. package/dist/utils/get-permissions.d.ts +2 -0
  118. package/dist/utils/get-permissions.js +150 -0
  119. package/dist/utils/get-service.js +1 -5
  120. package/dist/utils/merge-permissions-for-share.d.ts +4 -0
  121. package/dist/utils/merge-permissions-for-share.js +109 -0
  122. package/dist/utils/merge-permissions.d.ts +3 -0
  123. package/dist/utils/merge-permissions.js +95 -0
  124. package/dist/utils/reduce-schema.d.ts +6 -4
  125. package/dist/utils/reduce-schema.js +34 -14
  126. package/dist/utils/verify-session-jwt.js +2 -1
  127. package/dist/websocket/authenticate.d.ts +2 -0
  128. package/dist/websocket/authenticate.js +12 -0
  129. package/dist/websocket/controllers/graphql.js +4 -1
  130. package/dist/websocket/controllers/hooks.js +0 -4
  131. package/dist/websocket/controllers/rest.js +2 -0
  132. package/dist/websocket/handlers/subscribe.js +2 -0
  133. package/dist/websocket/utils/items.d.ts +1 -1
  134. package/package.json +35 -33
  135. package/dist/controllers/access.js +0 -148
  136. package/dist/controllers/policies.d.ts +0 -2
  137. package/dist/controllers/policies.js +0 -169
  138. package/dist/database/get-ast-from-query/get-ast-from-query.d.ts +0 -16
  139. package/dist/database/get-ast-from-query/get-ast-from-query.js +0 -82
  140. package/dist/database/get-ast-from-query/lib/convert-wildcards.d.ts +0 -13
  141. package/dist/database/get-ast-from-query/lib/convert-wildcards.js +0 -69
  142. package/dist/database/get-ast-from-query/lib/parse-fields.d.ts +0 -15
  143. package/dist/database/get-ast-from-query/lib/parse-fields.js +0 -190
  144. package/dist/database/get-ast-from-query/utils/get-deep-query.d.ts +0 -14
  145. package/dist/database/get-ast-from-query/utils/get-deep-query.js +0 -17
  146. package/dist/database/get-ast-from-query/utils/get-related-collection.d.ts +0 -2
  147. package/dist/database/get-ast-from-query/utils/get-related-collection.js +0 -13
  148. package/dist/database/get-ast-from-query/utils/get-relation.d.ts +0 -2
  149. package/dist/database/get-ast-from-query/utils/get-relation.js +0 -7
  150. package/dist/database/migrations/20240619A-permissions-policies.js +0 -163
  151. package/dist/database/run-ast/lib/get-db-query.d.ts +0 -4
  152. package/dist/database/run-ast/lib/get-db-query.js +0 -194
  153. package/dist/database/run-ast/lib/parse-current-level.d.ts +0 -7
  154. package/dist/database/run-ast/lib/parse-current-level.js +0 -41
  155. package/dist/database/run-ast/run-ast.d.ts +0 -7
  156. package/dist/database/run-ast/run-ast.js +0 -107
  157. package/dist/database/run-ast/types.js +0 -1
  158. package/dist/database/run-ast/utils/apply-case-when.d.ts +0 -16
  159. package/dist/database/run-ast/utils/apply-case-when.js +0 -26
  160. package/dist/database/run-ast/utils/apply-parent-filters.d.ts +0 -3
  161. package/dist/database/run-ast/utils/apply-parent-filters.js +0 -55
  162. package/dist/database/run-ast/utils/get-column-pre-processor.d.ts +0 -10
  163. package/dist/database/run-ast/utils/get-column-pre-processor.js +0 -57
  164. package/dist/database/run-ast/utils/get-field-alias.d.ts +0 -2
  165. package/dist/database/run-ast/utils/get-field-alias.js +0 -4
  166. package/dist/database/run-ast/utils/get-inner-query-column-pre-processor.d.ts +0 -5
  167. package/dist/database/run-ast/utils/get-inner-query-column-pre-processor.js +0 -23
  168. package/dist/database/run-ast/utils/merge-with-parent-items.d.ts +0 -3
  169. package/dist/database/run-ast/utils/merge-with-parent-items.js +0 -87
  170. package/dist/database/run-ast/utils/remove-temporary-fields.d.ts +0 -3
  171. package/dist/database/run-ast/utils/remove-temporary-fields.js +0 -73
  172. package/dist/permissions/cache.d.ts +0 -2
  173. package/dist/permissions/cache.js +0 -23
  174. package/dist/permissions/lib/fetch-permissions.d.ts +0 -10
  175. package/dist/permissions/lib/fetch-permissions.js +0 -55
  176. package/dist/permissions/lib/fetch-policies.d.ts +0 -7
  177. package/dist/permissions/lib/fetch-policies.js +0 -28
  178. package/dist/permissions/lib/fetch-roles-tree.d.ts +0 -3
  179. package/dist/permissions/lib/fetch-roles-tree.js +0 -28
  180. package/dist/permissions/lib/with-app-minimal-permissions.js +0 -10
  181. package/dist/permissions/modules/fetch-accountability-collection-access/fetch-accountability-collection-access.d.ts +0 -7
  182. package/dist/permissions/modules/fetch-accountability-collection-access/fetch-accountability-collection-access.js +0 -56
  183. package/dist/permissions/modules/fetch-accountability-policy-globals/fetch-accountability-policy-globals.d.ts +0 -3
  184. package/dist/permissions/modules/fetch-accountability-policy-globals/fetch-accountability-policy-globals.js +0 -16
  185. package/dist/permissions/modules/fetch-allowed-collections/fetch-allowed-collections.d.ts +0 -8
  186. package/dist/permissions/modules/fetch-allowed-collections/fetch-allowed-collections.js +0 -24
  187. package/dist/permissions/modules/fetch-allowed-field-map/fetch-allowed-field-map.d.ts +0 -9
  188. package/dist/permissions/modules/fetch-allowed-field-map/fetch-allowed-field-map.js +0 -31
  189. package/dist/permissions/modules/fetch-allowed-fields/fetch-allowed-fields.d.ts +0 -16
  190. package/dist/permissions/modules/fetch-allowed-fields/fetch-allowed-fields.js +0 -27
  191. package/dist/permissions/modules/fetch-global-access/fetch-global-access.d.ts +0 -10
  192. package/dist/permissions/modules/fetch-global-access/fetch-global-access.js +0 -23
  193. package/dist/permissions/modules/fetch-global-access/lib/fetch-global-access-for-roles.d.ts +0 -5
  194. package/dist/permissions/modules/fetch-global-access/lib/fetch-global-access-for-roles.js +0 -7
  195. package/dist/permissions/modules/fetch-global-access/lib/fetch-global-access-for-user.d.ts +0 -5
  196. package/dist/permissions/modules/fetch-global-access/lib/fetch-global-access-for-user.js +0 -10
  197. package/dist/permissions/modules/fetch-global-access/types.d.ts +0 -4
  198. package/dist/permissions/modules/fetch-global-access/types.js +0 -1
  199. package/dist/permissions/modules/fetch-global-access/utils/fetch-global-access-for-query.d.ts +0 -4
  200. package/dist/permissions/modules/fetch-global-access/utils/fetch-global-access-for-query.js +0 -27
  201. package/dist/permissions/modules/fetch-inconsistent-field-map/fetch-inconsistent-field-map.d.ts +0 -12
  202. package/dist/permissions/modules/fetch-inconsistent-field-map/fetch-inconsistent-field-map.js +0 -32
  203. package/dist/permissions/modules/fetch-policies-ip-access/fetch-policies-ip-access.d.ts +0 -4
  204. package/dist/permissions/modules/fetch-policies-ip-access/fetch-policies-ip-access.js +0 -29
  205. package/dist/permissions/modules/process-ast/lib/extract-fields-from-children.d.ts +0 -4
  206. package/dist/permissions/modules/process-ast/lib/extract-fields-from-children.js +0 -49
  207. package/dist/permissions/modules/process-ast/lib/extract-fields-from-query.d.ts +0 -3
  208. package/dist/permissions/modules/process-ast/lib/extract-fields-from-query.js +0 -56
  209. package/dist/permissions/modules/process-ast/lib/field-map-from-ast.d.ts +0 -4
  210. package/dist/permissions/modules/process-ast/lib/field-map-from-ast.js +0 -8
  211. package/dist/permissions/modules/process-ast/lib/inject-cases.d.ts +0 -9
  212. package/dist/permissions/modules/process-ast/lib/inject-cases.js +0 -93
  213. package/dist/permissions/modules/process-ast/process-ast.d.ts +0 -9
  214. package/dist/permissions/modules/process-ast/process-ast.js +0 -39
  215. package/dist/permissions/modules/process-ast/types.d.ts +0 -24
  216. package/dist/permissions/modules/process-ast/types.js +0 -1
  217. package/dist/permissions/modules/process-ast/utils/collections-in-field-map.d.ts +0 -2
  218. package/dist/permissions/modules/process-ast/utils/collections-in-field-map.js +0 -7
  219. package/dist/permissions/modules/process-ast/utils/dedupe-access.d.ts +0 -12
  220. package/dist/permissions/modules/process-ast/utils/dedupe-access.js +0 -30
  221. package/dist/permissions/modules/process-ast/utils/extract-paths-from-query.d.ts +0 -15
  222. package/dist/permissions/modules/process-ast/utils/extract-paths-from-query.js +0 -50
  223. package/dist/permissions/modules/process-ast/utils/find-related-collection.d.ts +0 -3
  224. package/dist/permissions/modules/process-ast/utils/find-related-collection.js +0 -9
  225. package/dist/permissions/modules/process-ast/utils/flatten-filter.d.ts +0 -3
  226. package/dist/permissions/modules/process-ast/utils/flatten-filter.js +0 -24
  227. package/dist/permissions/modules/process-ast/utils/format-a2o-key.d.ts +0 -1
  228. package/dist/permissions/modules/process-ast/utils/format-a2o-key.js +0 -3
  229. package/dist/permissions/modules/process-ast/utils/get-info-for-path.d.ts +0 -5
  230. package/dist/permissions/modules/process-ast/utils/get-info-for-path.js +0 -7
  231. package/dist/permissions/modules/process-ast/utils/has-item-permissions.d.ts +0 -2
  232. package/dist/permissions/modules/process-ast/utils/has-item-permissions.js +0 -3
  233. package/dist/permissions/modules/process-ast/utils/stringify-query-path.d.ts +0 -2
  234. package/dist/permissions/modules/process-ast/utils/stringify-query-path.js +0 -3
  235. package/dist/permissions/modules/process-ast/utils/validate-path/create-error.d.ts +0 -3
  236. package/dist/permissions/modules/process-ast/utils/validate-path/create-error.js +0 -16
  237. package/dist/permissions/modules/process-ast/utils/validate-path/validate-path-existence.d.ts +0 -2
  238. package/dist/permissions/modules/process-ast/utils/validate-path/validate-path-existence.js +0 -12
  239. package/dist/permissions/modules/process-ast/utils/validate-path/validate-path-permissions.d.ts +0 -2
  240. package/dist/permissions/modules/process-ast/utils/validate-path/validate-path-permissions.js +0 -28
  241. package/dist/permissions/modules/process-payload/lib/is-field-nullable.d.ts +0 -5
  242. package/dist/permissions/modules/process-payload/lib/is-field-nullable.js +0 -12
  243. package/dist/permissions/modules/process-payload/process-payload.d.ts +0 -13
  244. package/dist/permissions/modules/process-payload/process-payload.js +0 -77
  245. package/dist/permissions/modules/validate-access/lib/validate-collection-access.d.ts +0 -12
  246. package/dist/permissions/modules/validate-access/lib/validate-collection-access.js +0 -11
  247. package/dist/permissions/modules/validate-access/lib/validate-item-access.d.ts +0 -9
  248. package/dist/permissions/modules/validate-access/lib/validate-item-access.js +0 -33
  249. package/dist/permissions/modules/validate-access/validate-access.d.ts +0 -14
  250. package/dist/permissions/modules/validate-access/validate-access.js +0 -28
  251. package/dist/permissions/modules/validate-remaining-admin/validate-remaining-admin-count.d.ts +0 -1
  252. package/dist/permissions/modules/validate-remaining-admin/validate-remaining-admin-count.js +0 -8
  253. package/dist/permissions/modules/validate-remaining-admin/validate-remaining-admin-users.d.ts +0 -5
  254. package/dist/permissions/modules/validate-remaining-admin/validate-remaining-admin-users.js +0 -10
  255. package/dist/permissions/types.d.ts +0 -6
  256. package/dist/permissions/types.js +0 -1
  257. package/dist/permissions/utils/create-default-accountability.d.ts +0 -2
  258. package/dist/permissions/utils/create-default-accountability.js +0 -11
  259. package/dist/permissions/utils/extract-required-dynamic-variable-context.d.ts +0 -8
  260. package/dist/permissions/utils/extract-required-dynamic-variable-context.js +0 -27
  261. package/dist/permissions/utils/fetch-dynamic-variable-context.d.ts +0 -9
  262. package/dist/permissions/utils/fetch-dynamic-variable-context.js +0 -43
  263. package/dist/permissions/utils/filter-policies-by-ip.d.ts +0 -2
  264. package/dist/permissions/utils/filter-policies-by-ip.js +0 -15
  265. package/dist/permissions/utils/get-unaliased-field-key.d.ts +0 -5
  266. package/dist/permissions/utils/get-unaliased-field-key.js +0 -17
  267. package/dist/permissions/utils/process-permissions.d.ts +0 -7
  268. package/dist/permissions/utils/process-permissions.js +0 -9
  269. package/dist/permissions/utils/with-cache.d.ts +0 -10
  270. package/dist/permissions/utils/with-cache.js +0 -25
  271. package/dist/services/access.d.ts +0 -10
  272. package/dist/services/access.js +0 -43
  273. package/dist/services/policies.d.ts +0 -12
  274. package/dist/services/policies.js +0 -87
  275. package/dist/telemetry/utils/check-user-limits.d.ts +0 -5
  276. package/dist/telemetry/utils/check-user-limits.js +0 -19
  277. package/dist/utils/fetch-user-count/fetch-access-lookup.d.ts +0 -17
  278. package/dist/utils/fetch-user-count/fetch-access-lookup.js +0 -22
  279. package/dist/utils/fetch-user-count/fetch-access-roles.d.ts +0 -16
  280. package/dist/utils/fetch-user-count/fetch-access-roles.js +0 -37
  281. package/dist/utils/fetch-user-count/fetch-active-users.d.ts +0 -6
  282. package/dist/utils/fetch-user-count/fetch-active-users.js +0 -3
  283. package/dist/utils/fetch-user-count/fetch-user-count.d.ts +0 -12
  284. package/dist/utils/fetch-user-count/fetch-user-count.js +0 -57
  285. package/dist/utils/fetch-user-count/get-user-count-query.d.ts +0 -20
  286. package/dist/utils/fetch-user-count/get-user-count-query.js +0 -17
  287. package/dist/utils/validate-user-count-integrity.d.ts +0 -13
  288. package/dist/utils/validate-user-count-integrity.js +0 -29
  289. /package/dist/database/migrations/{20240619A-permissions-policies.d.ts → 20240701A-add-tus-data.d.ts} +0 -0
  290. /package/dist/{utils → services/files/utils}/parse-image-metadata.d.ts +0 -0
  291. /package/dist/{utils → services/files/utils}/parse-image-metadata.js +0 -0
@@ -0,0 +1,37 @@
1
+ import { InvalidIpError } from '@directus/errors';
2
+ import getDatabase from '../database/index.js';
3
+ import { useLogger } from '../logger.js';
4
+ import asyncHandler from '../utils/async-handler.js';
5
+ import { ipInNetworks } from '../utils/ip-in-networks.js';
6
+ export const checkIP = asyncHandler(async (req, _res, next) => {
7
+ const database = getDatabase();
8
+ const logger = useLogger();
9
+ const { role: roleId, ip } = req.accountability;
10
+ const query = database.select('ip_access').from('directus_roles');
11
+ if (roleId) {
12
+ query.where({ id: roleId });
13
+ }
14
+ else {
15
+ query.whereNull('id');
16
+ }
17
+ const role = await query.first();
18
+ if (!role?.ip_access)
19
+ return next();
20
+ const ipAllowList = role.ip_access.split(',').filter((ip) => ip);
21
+ if (ipAllowList.length > 0) {
22
+ if (!ip)
23
+ throw new InvalidIpError();
24
+ let allowed;
25
+ try {
26
+ allowed = ipInNetworks(ip, ipAllowList);
27
+ }
28
+ catch (error) {
29
+ logger.warn(`Invalid IP access configuration for role "${roleId}"`);
30
+ logger.warn(error);
31
+ throw new InvalidIpError();
32
+ }
33
+ if (!allowed)
34
+ throw new InvalidIpError();
35
+ }
36
+ return next();
37
+ });
@@ -0,0 +1,3 @@
1
+ import type { RequestHandler } from 'express';
2
+ declare const getPermissions: RequestHandler;
3
+ export default getPermissions;
@@ -0,0 +1,10 @@
1
+ import asyncHandler from '../utils/async-handler.js';
2
+ import { getPermissions as getPermissionsUtil } from '../utils/get-permissions.js';
3
+ const getPermissions = asyncHandler(async (req, _res, next) => {
4
+ if (!req.accountability) {
5
+ throw new Error('getPermissions middleware needs to be called after authenticate');
6
+ }
7
+ req.accountability.permissions = await getPermissionsUtil(req.accountability, req.schema);
8
+ return next();
9
+ });
10
+ export default getPermissions;
@@ -25,7 +25,7 @@ export const respond = asyncHandler(async (req, res) => {
25
25
  !req.sanitizedQuery.export &&
26
26
  res.locals['cache'] !== false &&
27
27
  exceedsMaxSize === false) {
28
- const key = await getCacheKey(req);
28
+ const key = getCacheKey(req);
29
29
  try {
30
30
  await setCacheValue(cache, key, res.locals['payload'], getMilliseconds(env['CACHE_TTL']));
31
31
  await setCacheValue(cache, `${key}__expires_at`, { exp: Date.now() + getMilliseconds(env['CACHE_TTL'], 0) });
@@ -3,13 +3,11 @@ import { useEnv } from '@directus/env';
3
3
  import { ErrorCode, isDirectusError } from '@directus/errors';
4
4
  import { uniq } from 'lodash-es';
5
5
  import { useLogger } from '../logger.js';
6
- import { fetchRolesTree } from '../permissions/lib/fetch-roles-tree.js';
7
- import { fetchGlobalAccess } from '../permissions/modules/fetch-global-access/fetch-global-access.js';
8
- import { validateAccess } from '../permissions/modules/validate-access/validate-access.js';
9
- import { createDefaultAccountability } from '../permissions/utils/create-default-accountability.js';
6
+ import { getPermissions } from '../utils/get-permissions.js';
10
7
  import { isValidUuid } from '../utils/is-valid-uuid.js';
11
8
  import { Url } from '../utils/url.js';
12
9
  import { userName } from '../utils/user-name.js';
10
+ import { AuthorizationService } from './authorization.js';
13
11
  import { ItemsService } from './items.js';
14
12
  import { NotificationsService } from './notifications.js';
15
13
  import { UsersService } from './users.js';
@@ -33,29 +31,19 @@ export class ActivityService extends ItemsService {
33
31
  for (const mention of mentions) {
34
32
  const userID = mention.substring(1);
35
33
  const user = await this.usersService.readOne(userID, {
36
- fields: ['id', 'first_name', 'last_name', 'email', 'role'],
34
+ fields: ['id', 'first_name', 'last_name', 'email', 'role.id', 'role.admin_access', 'role.app_access'],
37
35
  });
38
- const roles = await fetchRolesTree(user['role'], this.knex);
39
- const globalAccess = await fetchGlobalAccess({ user: user['id'], roles, ip: null }, this.knex);
40
- const accountability = createDefaultAccountability({
36
+ const accountability = {
41
37
  user: userID,
42
38
  role: user['role']?.id ?? null,
43
- roles,
44
- ...globalAccess,
45
- });
39
+ admin: user['role']?.admin_access ?? null,
40
+ app: user['role']?.app_access ?? null,
41
+ };
42
+ accountability.permissions = await getPermissions(accountability, this.schema);
43
+ const authorizationService = new AuthorizationService({ schema: this.schema, accountability });
46
44
  const usersService = new UsersService({ schema: this.schema, accountability });
47
45
  try {
48
- if (this.accountability) {
49
- await validateAccess({
50
- accountability: this.accountability,
51
- action: 'read',
52
- collection: data['collection'],
53
- primaryKeys: [data['item']],
54
- }, {
55
- knex: this.knex,
56
- schema: this.schema,
57
- });
58
- }
46
+ await authorizationService.checkAccess('read', data['collection'], data['item']);
59
47
  const templateData = await usersService.readByQuery({
60
48
  fields: ['id', 'first_name', 'last_name', 'email'],
61
49
  filter: { id: { _in: mentions.map((mention) => mention.substring(1)) } },
@@ -1,14 +1,15 @@
1
1
  /// <reference types="node" resolution-mode="require"/>
2
2
  import type { Range, Stat } from '@directus/storage';
3
- import type { Accountability, SchemaOverview } from '@directus/types';
3
+ import type { Accountability } from '@directus/types';
4
4
  import type { Knex } from 'knex';
5
5
  import type { Readable } from 'node:stream';
6
6
  import type { AbstractServiceOptions, TransformationSet } from '../types/index.js';
7
+ import { AuthorizationService } from './authorization.js';
7
8
  import { FilesService } from './files.js';
8
9
  export declare class AssetsService {
9
10
  knex: Knex;
10
11
  accountability: Accountability | null;
11
- schema: SchemaOverview;
12
+ authorizationService: AuthorizationService;
12
13
  filesService: FilesService;
13
14
  constructor(options: AbstractServiceOptions);
14
15
  getAsset(id: string, transformation?: TransformationSet, range?: Range): Promise<{
@@ -8,24 +8,24 @@ import sharp from 'sharp';
8
8
  import { SUPPORTED_IMAGE_TRANSFORM_FORMATS } from '../constants.js';
9
9
  import getDatabase from '../database/index.js';
10
10
  import { useLogger } from '../logger.js';
11
- import { validateAccess } from '../permissions/modules/validate-access/validate-access.js';
12
11
  import { getStorage } from '../storage/index.js';
13
12
  import { getMilliseconds } from '../utils/get-milliseconds.js';
14
13
  import { isValidUuid } from '../utils/is-valid-uuid.js';
15
14
  import * as TransformationUtils from '../utils/transformations.js';
15
+ import { AuthorizationService } from './authorization.js';
16
16
  import { FilesService } from './files.js';
17
17
  const env = useEnv();
18
18
  const logger = useLogger();
19
19
  export class AssetsService {
20
20
  knex;
21
21
  accountability;
22
- schema;
22
+ authorizationService;
23
23
  filesService;
24
24
  constructor(options) {
25
25
  this.knex = options.knex || getDatabase();
26
26
  this.accountability = options.accountability || null;
27
- this.schema = options.schema;
28
27
  this.filesService = new FilesService({ ...options, accountability: null });
28
+ this.authorizationService = new AuthorizationService(options);
29
29
  }
30
30
  async getAsset(id, transformation, range) {
31
31
  const storage = await getStorage();
@@ -41,13 +41,8 @@ export class AssetsService {
41
41
  */
42
42
  if (!isValidUuid(id))
43
43
  throw new ForbiddenError();
44
- if (systemPublicKeys.includes(id) === false && this.accountability) {
45
- await validateAccess({
46
- accountability: this.accountability,
47
- action: 'read',
48
- collection: 'directus_files',
49
- primaryKeys: [id],
50
- }, { knex: this.knex, schema: this.schema });
44
+ if (systemPublicKeys.includes(id) === false && this.accountability?.admin !== true) {
45
+ await this.authorizationService.checkAccess('read', 'directus_files', id);
51
46
  }
52
47
  const file = (await this.filesService.readOne(id, { limit: 1 }));
53
48
  const exists = await storage.location(file.storage).exists(file.filename_disk);
@@ -1,8 +1,6 @@
1
- import { fetchRolesTree } from '../permissions/lib/fetch-roles-tree.js';
2
- import { fetchGlobalAccess } from '../permissions/modules/fetch-global-access/fetch-global-access.js';
3
1
  import { Action } from '@directus/constants';
4
2
  import { useEnv } from '@directus/env';
5
- import { InvalidCredentialsError, InvalidOtpError, InvalidProviderError, ServiceUnavailableError, UserSuspendedError, } from '@directus/errors';
3
+ import { InvalidCredentialsError, InvalidOtpError, ServiceUnavailableError, UserSuspendedError, } from '@directus/errors';
6
4
  import jwt from 'jsonwebtoken';
7
5
  import { clone, cloneDeep } from 'lodash-es';
8
6
  import { performance } from 'perf_hooks';
@@ -50,9 +48,10 @@ export class AuthenticationService {
50
48
  throw err;
51
49
  }
52
50
  const user = await this.knex
53
- .select('id', 'first_name', 'last_name', 'email', 'password', 'status', 'role', 'tfa_secret', 'provider', 'external_identifier', 'auth_data')
54
- .from('directus_users')
55
- .where('id', userId)
51
+ .select('u.id', 'u.first_name', 'u.last_name', 'u.email', 'u.password', 'u.status', 'u.role', 'r.admin_access', 'r.app_access', 'u.tfa_secret', 'u.provider', 'u.external_identifier', 'u.auth_data')
52
+ .from('directus_users as u')
53
+ .leftJoin('directus_roles as r', 'u.role', 'r.id')
54
+ .where('u.id', userId)
56
55
  .first();
57
56
  const updatedPayload = await emitter.emitFilter('auth.login', payload, {
58
57
  status: 'pending',
@@ -75,20 +74,10 @@ export class AuthenticationService {
75
74
  accountability: this.accountability,
76
75
  });
77
76
  };
78
- if (user?.status !== 'active') {
77
+ if (user?.status !== 'active' || user?.provider !== providerName) {
79
78
  emitStatus('fail');
80
- if (user?.status === 'suspended') {
81
- await stall(STALL_TIME, timeStart);
82
- throw new UserSuspendedError();
83
- }
84
- else {
85
- await stall(STALL_TIME, timeStart);
86
- throw new InvalidCredentialsError();
87
- }
88
- }
89
- else if (user.provider !== providerName) {
90
79
  await stall(STALL_TIME, timeStart);
91
- throw new InvalidProviderError();
80
+ throw new InvalidCredentialsError();
92
81
  }
93
82
  const settingsService = new SettingsService({
94
83
  knex: this.knex,
@@ -139,13 +128,11 @@ export class AuthenticationService {
139
128
  throw new InvalidOtpError();
140
129
  }
141
130
  }
142
- const roles = await fetchRolesTree(user.role, this.knex);
143
- const globalAccess = await fetchGlobalAccess({ roles, user: user.id, ip: this.accountability?.ip ?? null }, this.knex);
144
131
  const tokenPayload = {
145
132
  id: user.id,
146
133
  role: user.role,
147
- app_access: globalAccess.app,
148
- admin_access: globalAccess.admin,
134
+ app_access: user.app_access,
135
+ admin_access: user.admin_access,
149
136
  };
150
137
  const refreshToken = nanoid(64);
151
138
  const refreshTokenExpiration = new Date(Date.now() + getMilliseconds(env['REFRESH_TOKEN_TTL'], 0));
@@ -220,7 +207,9 @@ export class AuthenticationService {
220
207
  user_provider: 'u.provider',
221
208
  user_external_identifier: 'u.external_identifier',
222
209
  user_auth_data: 'u.auth_data',
223
- user_role: 'u.role',
210
+ role_id: 'r.id',
211
+ role_admin_access: 'r.admin_access',
212
+ role_app_access: 'r.app_access',
224
213
  share_id: 'd.id',
225
214
  share_item: 'd.item',
226
215
  share_role: 'd.role',
@@ -233,6 +222,9 @@ export class AuthenticationService {
233
222
  .from('directus_sessions AS s')
234
223
  .leftJoin('directus_users AS u', 's.user', 'u.id')
235
224
  .leftJoin('directus_shares AS d', 's.share', 'd.id')
225
+ .leftJoin('directus_roles AS r', (join) => {
226
+ join.onIn('r.id', [this.knex.ref('u.role'), this.knex.ref('d.role')]);
227
+ })
236
228
  .where('s.token', refreshToken)
237
229
  .andWhere('s.expires', '>=', new Date())
238
230
  .andWhere((subQuery) => {
@@ -256,8 +248,6 @@ export class AuthenticationService {
256
248
  throw new InvalidCredentialsError();
257
249
  }
258
250
  }
259
- const roles = await fetchRolesTree(record.user_role, this.knex);
260
- const globalAccess = await fetchGlobalAccess({ user: record.user_id, roles, ip: this.accountability?.ip ?? null }, this.knex);
261
251
  if (record.user_id) {
262
252
  const provider = getAuthProvider(record.user_provider);
263
253
  await provider.refresh({
@@ -270,9 +260,9 @@ export class AuthenticationService {
270
260
  provider: record.user_provider,
271
261
  external_identifier: record.user_external_identifier,
272
262
  auth_data: record.user_auth_data,
273
- role: record.user_role,
274
- app_access: globalAccess.app,
275
- admin_access: globalAccess.admin,
263
+ role: record.role_id,
264
+ app_access: record.role_app_access,
265
+ admin_access: record.role_admin_access,
276
266
  });
277
267
  }
278
268
  let newRefreshToken = record.session_next_token ?? nanoid(64);
@@ -280,9 +270,9 @@ export class AuthenticationService {
280
270
  const refreshTokenExpiration = new Date(Date.now() + getMilliseconds(sessionDuration, 0));
281
271
  const tokenPayload = {
282
272
  id: record.user_id,
283
- role: record.user_role,
284
- app_access: globalAccess.app,
285
- admin_access: globalAccess.admin,
273
+ role: record.role_id,
274
+ app_access: record.role_app_access,
275
+ admin_access: record.role_admin_access,
286
276
  };
287
277
  if (options?.session) {
288
278
  newRefreshToken = await this.updateStatefulSession(record, refreshToken, newRefreshToken, refreshTokenExpiration);
@@ -329,7 +319,10 @@ export class AuthenticationService {
329
319
  // Clear expired sessions for the current user
330
320
  await this.knex('directus_sessions')
331
321
  .delete()
332
- .where('user', '=', record.user_id)
322
+ .where({
323
+ user: record.user_id,
324
+ share: record.share_id,
325
+ })
333
326
  .andWhere('expires', '<', new Date());
334
327
  return {
335
328
  accessToken,
@@ -372,6 +365,7 @@ export class AuthenticationService {
372
365
  await this.knex('directus_sessions').insert({
373
366
  token: newSessionToken,
374
367
  user: sessionRecord['user_id'],
368
+ share: sessionRecord['share_id'],
375
369
  expires: sessionExpiration,
376
370
  ip: this.accountability?.ip,
377
371
  user_agent: this.accountability?.userAgent,
@@ -0,0 +1,17 @@
1
+ import type { Accountability, Item, PermissionsAction, PrimaryKey, SchemaOverview } from '@directus/types';
2
+ import type { Knex } from 'knex';
3
+ import type { AST, AbstractServiceOptions } from '../types/index.js';
4
+ import { PayloadService } from './payload.js';
5
+ export declare class AuthorizationService {
6
+ knex: Knex;
7
+ accountability: Accountability | null;
8
+ payloadService: PayloadService;
9
+ schema: SchemaOverview;
10
+ constructor(options: AbstractServiceOptions);
11
+ processAST(ast: AST, action?: PermissionsAction): Promise<AST>;
12
+ /**
13
+ * Checks if the provided payload matches the configured permissions, and adds the presets to the payload.
14
+ */
15
+ validatePayload(action: PermissionsAction, collection: string, data: Partial<Item>): Partial<Item>;
16
+ checkAccess(action: PermissionsAction, collection: string, pk?: PrimaryKey | PrimaryKey[]): Promise<void>;
17
+ }