@directus/api 26.0.0 → 26.0.1
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.
|
@@ -4,9 +4,10 @@ import { FailedValidationError, joiValidationErrorItemToErrorExtensions } from '
|
|
|
4
4
|
import { assign, difference, uniq } from 'lodash-es';
|
|
5
5
|
import { fetchPermissions } from '../../lib/fetch-permissions.js';
|
|
6
6
|
import { fetchPolicies } from '../../lib/fetch-policies.js';
|
|
7
|
-
import { isFieldNullable } from './lib/is-field-nullable.js';
|
|
8
|
-
import { fetchDynamicVariableData } from '../../utils/fetch-dynamic-variable-data.js';
|
|
9
7
|
import { extractRequiredDynamicVariableContext } from '../../utils/extract-required-dynamic-variable-context.js';
|
|
8
|
+
import { fetchDynamicVariableData } from '../../utils/fetch-dynamic-variable-data.js';
|
|
9
|
+
import { contextHasDynamicVariables } from '../process-ast/utils/context-has-dynamic-variables.js';
|
|
10
|
+
import { isFieldNullable } from './lib/is-field-nullable.js';
|
|
10
11
|
/**
|
|
11
12
|
* @note this only validates the top-level fields. The expectation is that this function is called
|
|
12
13
|
* for each level of nested insert separately
|
|
@@ -14,8 +15,9 @@ import { extractRequiredDynamicVariableContext } from '../../utils/extract-requi
|
|
|
14
15
|
export async function processPayload(options, context) {
|
|
15
16
|
let permissions;
|
|
16
17
|
let permissionValidationRules = [];
|
|
17
|
-
|
|
18
|
+
let policies = [];
|
|
18
19
|
if (!options.accountability.admin) {
|
|
20
|
+
policies = await fetchPolicies(options.accountability, context);
|
|
19
21
|
permissions = await fetchPermissions({ action: options.action, policies, collections: [options.collection], accountability: options.accountability }, context);
|
|
20
22
|
if (permissions.length === 0) {
|
|
21
23
|
throw new ForbiddenError({
|
|
@@ -55,14 +57,18 @@ export async function processPayload(options, context) {
|
|
|
55
57
|
},
|
|
56
58
|
});
|
|
57
59
|
}
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
60
|
+
if (field.validation) {
|
|
61
|
+
const permissionContext = extractRequiredDynamicVariableContext(field.validation);
|
|
62
|
+
const filterContext = contextHasDynamicVariables(permissionContext)
|
|
63
|
+
? await fetchDynamicVariableData({
|
|
64
|
+
accountability: options.accountability,
|
|
65
|
+
policies,
|
|
66
|
+
dynamicVariableContext: permissionContext,
|
|
67
|
+
}, context)
|
|
68
|
+
: undefined;
|
|
69
|
+
const validationFilter = parseFilter(field.validation, options.accountability, filterContext);
|
|
70
|
+
fieldValidationRules.push(validationFilter);
|
|
71
|
+
}
|
|
66
72
|
}
|
|
67
73
|
const presets = (permissions ?? []).map((permission) => permission.presets);
|
|
68
74
|
const payloadWithPresets = assign({}, ...presets, options.payload);
|
|
@@ -23,7 +23,9 @@ export async function fetchDynamicVariableData(options, context) {
|
|
|
23
23
|
});
|
|
24
24
|
});
|
|
25
25
|
}
|
|
26
|
-
if (options.accountability.roles
|
|
26
|
+
if (options.accountability.roles &&
|
|
27
|
+
options.accountability.roles.length > 0 &&
|
|
28
|
+
(options.dynamicVariableContext.$CURRENT_ROLES?.size ?? 0) > 0) {
|
|
27
29
|
contextData['$CURRENT_ROLES'] = await fetchContextData('$CURRENT_ROLES', options.dynamicVariableContext, { roles: options.accountability.roles }, async (fields) => {
|
|
28
30
|
const rolesService = new RolesService(context);
|
|
29
31
|
return await rolesService.readMany(options.accountability.roles, {
|
|
@@ -360,29 +360,26 @@ export function applyFilter(knex, schema, rootQuery, rootFilter, collection, ali
|
|
|
360
360
|
pkField = knex.raw(getHelpers(knex).schema.castA2oPrimaryKey(), [pkField]);
|
|
361
361
|
}
|
|
362
362
|
const childKey = Object.keys(value)?.[0];
|
|
363
|
-
|
|
364
|
-
const
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
// Add implicit _some behavior when no operator is provided
|
|
384
|
-
dbQuery[logical].whereIn(pkField, subQueryBuilder(value, subCases));
|
|
385
|
-
continue;
|
|
363
|
+
if (childKey === '_none' || childKey === '_some') {
|
|
364
|
+
const subQueryBuilder = (filter, cases) => (subQueryKnex) => {
|
|
365
|
+
const field = relation.field;
|
|
366
|
+
const collection = relation.collection;
|
|
367
|
+
const column = `${collection}.${field}`;
|
|
368
|
+
subQueryKnex
|
|
369
|
+
.select({ [field]: column })
|
|
370
|
+
.from(collection)
|
|
371
|
+
.whereNotNull(column);
|
|
372
|
+
applyQuery(knex, relation.collection, subQueryKnex, { filter }, schema, cases, permissions);
|
|
373
|
+
};
|
|
374
|
+
const { cases: subCases } = getCases(relation.collection, permissions, []);
|
|
375
|
+
if (childKey === '_none') {
|
|
376
|
+
dbQuery[logical].whereNotIn(pkField, subQueryBuilder(Object.values(value)[0], subCases));
|
|
377
|
+
continue;
|
|
378
|
+
}
|
|
379
|
+
else if (childKey === '_some') {
|
|
380
|
+
dbQuery[logical].whereIn(pkField, subQueryBuilder(Object.values(value)[0], subCases));
|
|
381
|
+
continue;
|
|
382
|
+
}
|
|
386
383
|
}
|
|
387
384
|
}
|
|
388
385
|
if (filterPath.includes('_none') || filterPath.includes('_some')) {
|
|
@@ -631,7 +628,8 @@ export function applySearch(knex, schema, dbQuery, searchQuery, collection, alia
|
|
|
631
628
|
dbQuery.andWhere(function (queryBuilder) {
|
|
632
629
|
let needsFallbackCondition = true;
|
|
633
630
|
fields.forEach(([name, field]) => {
|
|
634
|
-
|
|
631
|
+
// only account for when cases when full access is not given
|
|
632
|
+
const whenCases = allowedFields.has('*') ? [] : (caseMap[name] ?? []).map((caseIndex) => cases[caseIndex]);
|
|
635
633
|
const fieldType = getFieldType(field);
|
|
636
634
|
if (fieldType !== null) {
|
|
637
635
|
needsFallbackCondition = false;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@directus/api",
|
|
3
|
-
"version": "26.0.
|
|
3
|
+
"version": "26.0.1",
|
|
4
4
|
"description": "Directus is a real-time API and App dashboard for managing SQL database content",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"directus",
|
|
@@ -150,29 +150,29 @@
|
|
|
150
150
|
"ws": "8.18.1",
|
|
151
151
|
"zod": "3.24.2",
|
|
152
152
|
"zod-validation-error": "3.4.0",
|
|
153
|
-
"@directus/app": "13.8.
|
|
154
|
-
"@directus/constants": "13.0.1",
|
|
153
|
+
"@directus/app": "13.8.1",
|
|
155
154
|
"@directus/errors": "2.0.1",
|
|
155
|
+
"@directus/constants": "13.0.1",
|
|
156
156
|
"@directus/env": "5.0.3",
|
|
157
157
|
"@directus/extensions": "3.0.4",
|
|
158
|
+
"@directus/extensions-registry": "3.0.4",
|
|
159
|
+
"@directus/memory": "3.0.3",
|
|
158
160
|
"@directus/extensions-sdk": "13.0.4",
|
|
159
161
|
"@directus/format-title": "12.0.1",
|
|
160
|
-
"@directus/memory": "3.0.3",
|
|
161
|
-
"@directus/pressure": "3.0.3",
|
|
162
|
-
"@directus/extensions-registry": "3.0.4",
|
|
163
|
-
"@directus/storage": "12.0.0",
|
|
164
|
-
"@directus/storage-driver-azure": "12.0.3",
|
|
165
162
|
"@directus/schema": "13.0.1",
|
|
166
163
|
"@directus/specs": "11.1.0",
|
|
164
|
+
"@directus/pressure": "3.0.3",
|
|
165
|
+
"@directus/storage": "12.0.0",
|
|
167
166
|
"@directus/storage-driver-cloudinary": "12.0.3",
|
|
167
|
+
"@directus/storage-driver-azure": "12.0.3",
|
|
168
|
+
"@directus/storage-driver-gcs": "12.0.3",
|
|
168
169
|
"@directus/storage-driver-local": "12.0.0",
|
|
169
170
|
"@directus/storage-driver-s3": "12.0.3",
|
|
170
|
-
"@directus/
|
|
171
|
+
"@directus/system-data": "3.1.0",
|
|
171
172
|
"@directus/storage-driver-supabase": "3.0.3",
|
|
172
173
|
"@directus/utils": "13.0.3",
|
|
173
|
-
"@directus/system-data": "3.1.0",
|
|
174
174
|
"@directus/validation": "2.0.3",
|
|
175
|
-
"directus": "11.6.
|
|
175
|
+
"directus": "11.6.1"
|
|
176
176
|
},
|
|
177
177
|
"devDependencies": {
|
|
178
178
|
"@directus/tsconfig": "3.0.0",
|