@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.
- package/dist/app.js +9 -4
- package/dist/auth/drivers/ldap.js +4 -4
- package/dist/auth/drivers/local.js +4 -4
- package/dist/auth/drivers/oauth2.js +4 -4
- package/dist/auth/drivers/openid.js +4 -2
- package/dist/cache.js +0 -3
- package/dist/cli/commands/bootstrap/index.js +2 -8
- package/dist/cli/commands/init/index.js +10 -9
- package/dist/cli/utils/defaults.d.ts +11 -4
- package/dist/cli/utils/defaults.js +1 -7
- package/dist/constants.d.ts +9 -1
- package/dist/constants.js +10 -0
- package/dist/controllers/auth.js +16 -5
- package/dist/controllers/permissions.js +2 -14
- package/dist/controllers/roles.js +1 -22
- package/dist/controllers/{access.d.ts → tus.d.ts} +1 -0
- package/dist/controllers/tus.js +72 -0
- package/dist/controllers/users.js +55 -0
- package/dist/database/helpers/fn/types.d.ts +1 -2
- package/dist/database/helpers/fn/types.js +1 -1
- package/dist/database/helpers/geometry/dialects/mssql.d.ts +1 -1
- package/dist/database/helpers/geometry/dialects/mssql.js +2 -4
- package/dist/database/helpers/geometry/dialects/mysql.js +1 -1
- package/dist/database/helpers/geometry/dialects/oracle.d.ts +1 -1
- package/dist/database/helpers/geometry/dialects/oracle.js +3 -5
- package/dist/database/helpers/geometry/types.d.ts +1 -1
- package/dist/database/helpers/geometry/types.js +2 -4
- package/dist/database/index.js +1 -2
- package/dist/database/migrations/20240701A-add-tus-data.js +12 -0
- package/dist/database/{run-ast/types.d.ts → run-ast.d.ts} +9 -3
- package/dist/database/run-ast.js +450 -0
- package/dist/flows.js +4 -3
- package/dist/middleware/authenticate.js +7 -2
- package/dist/middleware/cache.js +1 -1
- package/dist/middleware/check-ip.d.ts +2 -0
- package/dist/middleware/check-ip.js +37 -0
- package/dist/middleware/get-permissions.d.ts +3 -0
- package/dist/middleware/get-permissions.js +10 -0
- package/dist/middleware/respond.js +1 -1
- package/dist/services/activity.js +10 -22
- package/dist/services/assets.d.ts +3 -2
- package/dist/services/assets.js +5 -10
- package/dist/services/authentication.js +26 -32
- package/dist/services/authorization.d.ts +17 -0
- package/dist/services/authorization.js +456 -0
- package/dist/services/collections.js +17 -18
- package/dist/services/fields.d.ts +1 -0
- package/dist/services/fields.js +24 -53
- package/dist/services/files/lib/extract-metadata.d.ts +3 -0
- package/dist/services/files/lib/extract-metadata.js +32 -0
- package/dist/services/files/utils/get-metadata.d.ts +5 -0
- package/dist/services/files/utils/get-metadata.js +107 -0
- package/dist/services/files.d.ts +4 -6
- package/dist/services/files.js +24 -140
- package/dist/services/graphql/index.d.ts +3 -3
- package/dist/services/graphql/index.js +22 -126
- package/dist/services/graphql/subscription.js +4 -2
- package/dist/services/import-export.js +4 -18
- package/dist/services/index.d.ts +2 -3
- package/dist/services/index.js +2 -3
- package/dist/services/items.js +44 -115
- package/dist/services/meta.js +23 -60
- package/dist/services/payload.d.ts +10 -9
- package/dist/services/payload.js +3 -18
- package/dist/services/{permissions.d.ts → permissions/index.d.ts} +7 -5
- package/dist/services/{permissions.js → permissions/index.js} +54 -30
- package/dist/{permissions → services/permissions}/lib/with-app-minimal-permissions.d.ts +1 -1
- package/dist/services/permissions/lib/with-app-minimal-permissions.js +13 -0
- package/dist/services/relations.d.ts +6 -0
- package/dist/services/relations.js +29 -26
- package/dist/services/roles.d.ts +12 -4
- package/dist/services/roles.js +424 -57
- package/dist/services/server.js +6 -0
- package/dist/services/shares.d.ts +2 -0
- package/dist/services/shares.js +8 -12
- package/dist/services/specifications.d.ts +2 -2
- package/dist/services/specifications.js +27 -39
- package/dist/services/tus/data-store.d.ts +36 -0
- package/dist/services/tus/data-store.js +214 -0
- package/dist/services/tus/index.d.ts +2 -0
- package/dist/services/tus/index.js +2 -0
- package/dist/services/tus/lockers.d.ts +36 -0
- package/dist/services/tus/lockers.js +83 -0
- package/dist/services/tus/server.d.ts +8 -0
- package/dist/services/tus/server.js +80 -0
- package/dist/services/tus/utils/wait-timeout.d.ts +1 -0
- package/dist/services/tus/utils/wait-timeout.js +13 -0
- package/dist/services/users.d.ts +5 -1
- package/dist/services/users.js +161 -78
- package/dist/services/utils.js +7 -11
- package/dist/services/versions.d.ts +2 -0
- package/dist/services/versions.js +10 -34
- package/dist/storage/register-locations.js +5 -1
- package/dist/telemetry/lib/get-report.js +2 -2
- package/dist/telemetry/utils/check-increased-user-limits.d.ts +7 -0
- package/dist/telemetry/utils/check-increased-user-limits.js +25 -0
- package/dist/telemetry/utils/get-role-counts-by-roles.d.ts +6 -0
- package/dist/telemetry/utils/get-role-counts-by-roles.js +27 -0
- package/dist/telemetry/utils/get-role-counts-by-users.d.ts +11 -0
- package/dist/telemetry/utils/get-role-counts-by-users.js +34 -0
- package/dist/telemetry/utils/get-user-count.d.ts +8 -0
- package/dist/telemetry/utils/get-user-count.js +33 -0
- package/dist/telemetry/utils/get-user-counts-by-roles.d.ts +7 -0
- package/dist/telemetry/utils/get-user-counts-by-roles.js +35 -0
- package/dist/types/ast.d.ts +1 -43
- package/dist/types/items.d.ts +0 -11
- package/dist/utils/apply-query.d.ts +3 -4
- package/dist/utils/apply-query.js +8 -37
- package/dist/utils/get-accountability-for-role.js +25 -16
- package/dist/utils/get-accountability-for-token.js +16 -17
- package/dist/utils/get-ast-from-query.d.ts +13 -0
- package/dist/utils/get-ast-from-query.js +297 -0
- package/dist/utils/get-cache-key.d.ts +1 -1
- package/dist/utils/get-cache-key.js +1 -12
- package/dist/utils/get-column.d.ts +1 -2
- package/dist/utils/get-column.js +0 -1
- package/dist/utils/get-permissions.d.ts +2 -0
- package/dist/utils/get-permissions.js +150 -0
- package/dist/utils/get-service.js +1 -5
- package/dist/utils/merge-permissions-for-share.d.ts +4 -0
- package/dist/utils/merge-permissions-for-share.js +109 -0
- package/dist/utils/merge-permissions.d.ts +3 -0
- package/dist/utils/merge-permissions.js +95 -0
- package/dist/utils/reduce-schema.d.ts +6 -4
- package/dist/utils/reduce-schema.js +34 -14
- package/dist/utils/verify-session-jwt.js +2 -1
- package/dist/websocket/authenticate.d.ts +2 -0
- package/dist/websocket/authenticate.js +12 -0
- package/dist/websocket/controllers/graphql.js +4 -1
- package/dist/websocket/controllers/hooks.js +0 -4
- package/dist/websocket/controllers/rest.js +2 -0
- package/dist/websocket/handlers/subscribe.js +2 -0
- package/dist/websocket/utils/items.d.ts +1 -1
- package/package.json +35 -33
- package/dist/controllers/access.js +0 -148
- package/dist/controllers/policies.d.ts +0 -2
- package/dist/controllers/policies.js +0 -169
- package/dist/database/get-ast-from-query/get-ast-from-query.d.ts +0 -16
- package/dist/database/get-ast-from-query/get-ast-from-query.js +0 -82
- package/dist/database/get-ast-from-query/lib/convert-wildcards.d.ts +0 -13
- package/dist/database/get-ast-from-query/lib/convert-wildcards.js +0 -69
- package/dist/database/get-ast-from-query/lib/parse-fields.d.ts +0 -15
- package/dist/database/get-ast-from-query/lib/parse-fields.js +0 -190
- package/dist/database/get-ast-from-query/utils/get-deep-query.d.ts +0 -14
- package/dist/database/get-ast-from-query/utils/get-deep-query.js +0 -17
- package/dist/database/get-ast-from-query/utils/get-related-collection.d.ts +0 -2
- package/dist/database/get-ast-from-query/utils/get-related-collection.js +0 -13
- package/dist/database/get-ast-from-query/utils/get-relation.d.ts +0 -2
- package/dist/database/get-ast-from-query/utils/get-relation.js +0 -7
- package/dist/database/migrations/20240619A-permissions-policies.js +0 -163
- package/dist/database/run-ast/lib/get-db-query.d.ts +0 -4
- package/dist/database/run-ast/lib/get-db-query.js +0 -194
- package/dist/database/run-ast/lib/parse-current-level.d.ts +0 -7
- package/dist/database/run-ast/lib/parse-current-level.js +0 -41
- package/dist/database/run-ast/run-ast.d.ts +0 -7
- package/dist/database/run-ast/run-ast.js +0 -107
- package/dist/database/run-ast/types.js +0 -1
- package/dist/database/run-ast/utils/apply-case-when.d.ts +0 -16
- package/dist/database/run-ast/utils/apply-case-when.js +0 -26
- package/dist/database/run-ast/utils/apply-parent-filters.d.ts +0 -3
- package/dist/database/run-ast/utils/apply-parent-filters.js +0 -55
- package/dist/database/run-ast/utils/get-column-pre-processor.d.ts +0 -10
- package/dist/database/run-ast/utils/get-column-pre-processor.js +0 -57
- package/dist/database/run-ast/utils/get-field-alias.d.ts +0 -2
- package/dist/database/run-ast/utils/get-field-alias.js +0 -4
- package/dist/database/run-ast/utils/get-inner-query-column-pre-processor.d.ts +0 -5
- package/dist/database/run-ast/utils/get-inner-query-column-pre-processor.js +0 -23
- package/dist/database/run-ast/utils/merge-with-parent-items.d.ts +0 -3
- package/dist/database/run-ast/utils/merge-with-parent-items.js +0 -87
- package/dist/database/run-ast/utils/remove-temporary-fields.d.ts +0 -3
- package/dist/database/run-ast/utils/remove-temporary-fields.js +0 -73
- package/dist/permissions/cache.d.ts +0 -2
- package/dist/permissions/cache.js +0 -23
- package/dist/permissions/lib/fetch-permissions.d.ts +0 -10
- package/dist/permissions/lib/fetch-permissions.js +0 -55
- package/dist/permissions/lib/fetch-policies.d.ts +0 -7
- package/dist/permissions/lib/fetch-policies.js +0 -28
- package/dist/permissions/lib/fetch-roles-tree.d.ts +0 -3
- package/dist/permissions/lib/fetch-roles-tree.js +0 -28
- package/dist/permissions/lib/with-app-minimal-permissions.js +0 -10
- package/dist/permissions/modules/fetch-accountability-collection-access/fetch-accountability-collection-access.d.ts +0 -7
- package/dist/permissions/modules/fetch-accountability-collection-access/fetch-accountability-collection-access.js +0 -56
- package/dist/permissions/modules/fetch-accountability-policy-globals/fetch-accountability-policy-globals.d.ts +0 -3
- package/dist/permissions/modules/fetch-accountability-policy-globals/fetch-accountability-policy-globals.js +0 -16
- package/dist/permissions/modules/fetch-allowed-collections/fetch-allowed-collections.d.ts +0 -8
- package/dist/permissions/modules/fetch-allowed-collections/fetch-allowed-collections.js +0 -24
- package/dist/permissions/modules/fetch-allowed-field-map/fetch-allowed-field-map.d.ts +0 -9
- package/dist/permissions/modules/fetch-allowed-field-map/fetch-allowed-field-map.js +0 -31
- package/dist/permissions/modules/fetch-allowed-fields/fetch-allowed-fields.d.ts +0 -16
- package/dist/permissions/modules/fetch-allowed-fields/fetch-allowed-fields.js +0 -27
- package/dist/permissions/modules/fetch-global-access/fetch-global-access.d.ts +0 -10
- package/dist/permissions/modules/fetch-global-access/fetch-global-access.js +0 -23
- package/dist/permissions/modules/fetch-global-access/lib/fetch-global-access-for-roles.d.ts +0 -5
- package/dist/permissions/modules/fetch-global-access/lib/fetch-global-access-for-roles.js +0 -7
- package/dist/permissions/modules/fetch-global-access/lib/fetch-global-access-for-user.d.ts +0 -5
- package/dist/permissions/modules/fetch-global-access/lib/fetch-global-access-for-user.js +0 -10
- package/dist/permissions/modules/fetch-global-access/types.d.ts +0 -4
- package/dist/permissions/modules/fetch-global-access/types.js +0 -1
- package/dist/permissions/modules/fetch-global-access/utils/fetch-global-access-for-query.d.ts +0 -4
- package/dist/permissions/modules/fetch-global-access/utils/fetch-global-access-for-query.js +0 -27
- package/dist/permissions/modules/fetch-inconsistent-field-map/fetch-inconsistent-field-map.d.ts +0 -12
- package/dist/permissions/modules/fetch-inconsistent-field-map/fetch-inconsistent-field-map.js +0 -32
- package/dist/permissions/modules/fetch-policies-ip-access/fetch-policies-ip-access.d.ts +0 -4
- package/dist/permissions/modules/fetch-policies-ip-access/fetch-policies-ip-access.js +0 -29
- package/dist/permissions/modules/process-ast/lib/extract-fields-from-children.d.ts +0 -4
- package/dist/permissions/modules/process-ast/lib/extract-fields-from-children.js +0 -49
- package/dist/permissions/modules/process-ast/lib/extract-fields-from-query.d.ts +0 -3
- package/dist/permissions/modules/process-ast/lib/extract-fields-from-query.js +0 -56
- package/dist/permissions/modules/process-ast/lib/field-map-from-ast.d.ts +0 -4
- package/dist/permissions/modules/process-ast/lib/field-map-from-ast.js +0 -8
- package/dist/permissions/modules/process-ast/lib/inject-cases.d.ts +0 -9
- package/dist/permissions/modules/process-ast/lib/inject-cases.js +0 -93
- package/dist/permissions/modules/process-ast/process-ast.d.ts +0 -9
- package/dist/permissions/modules/process-ast/process-ast.js +0 -39
- package/dist/permissions/modules/process-ast/types.d.ts +0 -24
- package/dist/permissions/modules/process-ast/types.js +0 -1
- package/dist/permissions/modules/process-ast/utils/collections-in-field-map.d.ts +0 -2
- package/dist/permissions/modules/process-ast/utils/collections-in-field-map.js +0 -7
- package/dist/permissions/modules/process-ast/utils/dedupe-access.d.ts +0 -12
- package/dist/permissions/modules/process-ast/utils/dedupe-access.js +0 -30
- package/dist/permissions/modules/process-ast/utils/extract-paths-from-query.d.ts +0 -15
- package/dist/permissions/modules/process-ast/utils/extract-paths-from-query.js +0 -50
- package/dist/permissions/modules/process-ast/utils/find-related-collection.d.ts +0 -3
- package/dist/permissions/modules/process-ast/utils/find-related-collection.js +0 -9
- package/dist/permissions/modules/process-ast/utils/flatten-filter.d.ts +0 -3
- package/dist/permissions/modules/process-ast/utils/flatten-filter.js +0 -24
- package/dist/permissions/modules/process-ast/utils/format-a2o-key.d.ts +0 -1
- package/dist/permissions/modules/process-ast/utils/format-a2o-key.js +0 -3
- package/dist/permissions/modules/process-ast/utils/get-info-for-path.d.ts +0 -5
- package/dist/permissions/modules/process-ast/utils/get-info-for-path.js +0 -7
- package/dist/permissions/modules/process-ast/utils/has-item-permissions.d.ts +0 -2
- package/dist/permissions/modules/process-ast/utils/has-item-permissions.js +0 -3
- package/dist/permissions/modules/process-ast/utils/stringify-query-path.d.ts +0 -2
- package/dist/permissions/modules/process-ast/utils/stringify-query-path.js +0 -3
- package/dist/permissions/modules/process-ast/utils/validate-path/create-error.d.ts +0 -3
- package/dist/permissions/modules/process-ast/utils/validate-path/create-error.js +0 -16
- package/dist/permissions/modules/process-ast/utils/validate-path/validate-path-existence.d.ts +0 -2
- package/dist/permissions/modules/process-ast/utils/validate-path/validate-path-existence.js +0 -12
- package/dist/permissions/modules/process-ast/utils/validate-path/validate-path-permissions.d.ts +0 -2
- package/dist/permissions/modules/process-ast/utils/validate-path/validate-path-permissions.js +0 -28
- package/dist/permissions/modules/process-payload/lib/is-field-nullable.d.ts +0 -5
- package/dist/permissions/modules/process-payload/lib/is-field-nullable.js +0 -12
- package/dist/permissions/modules/process-payload/process-payload.d.ts +0 -13
- package/dist/permissions/modules/process-payload/process-payload.js +0 -77
- package/dist/permissions/modules/validate-access/lib/validate-collection-access.d.ts +0 -12
- package/dist/permissions/modules/validate-access/lib/validate-collection-access.js +0 -11
- package/dist/permissions/modules/validate-access/lib/validate-item-access.d.ts +0 -9
- package/dist/permissions/modules/validate-access/lib/validate-item-access.js +0 -33
- package/dist/permissions/modules/validate-access/validate-access.d.ts +0 -14
- package/dist/permissions/modules/validate-access/validate-access.js +0 -28
- package/dist/permissions/modules/validate-remaining-admin/validate-remaining-admin-count.d.ts +0 -1
- package/dist/permissions/modules/validate-remaining-admin/validate-remaining-admin-count.js +0 -8
- package/dist/permissions/modules/validate-remaining-admin/validate-remaining-admin-users.d.ts +0 -5
- package/dist/permissions/modules/validate-remaining-admin/validate-remaining-admin-users.js +0 -10
- package/dist/permissions/types.d.ts +0 -6
- package/dist/permissions/types.js +0 -1
- package/dist/permissions/utils/create-default-accountability.d.ts +0 -2
- package/dist/permissions/utils/create-default-accountability.js +0 -11
- package/dist/permissions/utils/extract-required-dynamic-variable-context.d.ts +0 -8
- package/dist/permissions/utils/extract-required-dynamic-variable-context.js +0 -27
- package/dist/permissions/utils/fetch-dynamic-variable-context.d.ts +0 -9
- package/dist/permissions/utils/fetch-dynamic-variable-context.js +0 -43
- package/dist/permissions/utils/filter-policies-by-ip.d.ts +0 -2
- package/dist/permissions/utils/filter-policies-by-ip.js +0 -15
- package/dist/permissions/utils/get-unaliased-field-key.d.ts +0 -5
- package/dist/permissions/utils/get-unaliased-field-key.js +0 -17
- package/dist/permissions/utils/process-permissions.d.ts +0 -7
- package/dist/permissions/utils/process-permissions.js +0 -9
- package/dist/permissions/utils/with-cache.d.ts +0 -10
- package/dist/permissions/utils/with-cache.js +0 -25
- package/dist/services/access.d.ts +0 -10
- package/dist/services/access.js +0 -43
- package/dist/services/policies.d.ts +0 -12
- package/dist/services/policies.js +0 -87
- package/dist/telemetry/utils/check-user-limits.d.ts +0 -5
- package/dist/telemetry/utils/check-user-limits.js +0 -19
- package/dist/utils/fetch-user-count/fetch-access-lookup.d.ts +0 -17
- package/dist/utils/fetch-user-count/fetch-access-lookup.js +0 -22
- package/dist/utils/fetch-user-count/fetch-access-roles.d.ts +0 -16
- package/dist/utils/fetch-user-count/fetch-access-roles.js +0 -37
- package/dist/utils/fetch-user-count/fetch-active-users.d.ts +0 -6
- package/dist/utils/fetch-user-count/fetch-active-users.js +0 -3
- package/dist/utils/fetch-user-count/fetch-user-count.d.ts +0 -12
- package/dist/utils/fetch-user-count/fetch-user-count.js +0 -57
- package/dist/utils/fetch-user-count/get-user-count-query.d.ts +0 -20
- package/dist/utils/fetch-user-count/get-user-count-query.js +0 -17
- package/dist/utils/validate-user-count-integrity.d.ts +0 -13
- package/dist/utils/validate-user-count-integrity.js +0 -29
- /package/dist/database/migrations/{20240619A-permissions-policies.d.ts → 20240701A-add-tus-data.d.ts} +0 -0
- /package/dist/{utils → services/files/utils}/parse-image-metadata.d.ts +0 -0
- /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,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 =
|
|
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 {
|
|
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
|
|
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
|
-
|
|
44
|
-
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
12
|
+
authorizationService: AuthorizationService;
|
|
12
13
|
filesService: FilesService;
|
|
13
14
|
constructor(options: AbstractServiceOptions);
|
|
14
15
|
getAsset(id: string, transformation?: TransformationSet, range?: Range): Promise<{
|
package/dist/services/assets.js
CHANGED
|
@@ -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
|
-
|
|
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
|
|
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,
|
|
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
|
-
.
|
|
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
|
|
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:
|
|
148
|
-
admin_access:
|
|
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
|
-
|
|
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.
|
|
274
|
-
app_access:
|
|
275
|
-
admin_access:
|
|
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.
|
|
284
|
-
app_access:
|
|
285
|
-
admin_access:
|
|
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(
|
|
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
|
+
}
|