directus 9.9.0 → 9.11.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/README.md +1 -1
- package/dist/app.js +3 -0
- package/dist/auth/drivers/oauth2.d.ts +1 -1
- package/dist/auth/drivers/oauth2.js +14 -11
- package/dist/auth/drivers/openid.d.ts +1 -1
- package/dist/auth/drivers/openid.js +14 -11
- package/dist/cli/commands/schema/apply.js +4 -3
- package/dist/controllers/assets.js +8 -9
- package/dist/controllers/files.js +3 -0
- package/dist/database/helpers/date/dialects/sqlite.js +6 -2
- package/dist/database/helpers/fn/dialects/postgres.js +5 -1
- package/dist/database/migrations/20210225A-add-relations-sort-field.js +2 -1
- package/dist/database/migrations/20210506A-rename-interfaces.js +2 -1
- package/dist/database/migrations/20210802A-replace-groups.js +2 -1
- package/dist/database/migrations/20210805A-update-groups.js +2 -1
- package/dist/database/migrations/20210805B-change-image-metadata-structure.js +3 -2
- package/dist/database/migrations/20211007A-update-presets.js +5 -4
- package/dist/database/run-ast.js +11 -15
- package/dist/database/system-data/fields/collections.yaml +1 -1
- package/dist/env.js +8 -3
- package/dist/exceptions/index.d.ts +1 -0
- package/dist/exceptions/index.js +1 -0
- package/dist/exceptions/invalid-provider.d.ts +4 -0
- package/dist/exceptions/invalid-provider.js +10 -0
- package/dist/exceptions/range-not-satisfiable.d.ts +2 -2
- package/dist/exceptions/range-not-satisfiable.js +5 -1
- package/dist/middleware/graphql.js +2 -1
- package/dist/services/assets.js +27 -1
- package/dist/services/authentication.js +4 -1
- package/dist/services/collections.js +2 -0
- package/dist/services/fields.js +17 -8
- package/dist/services/graphql.js +75 -34
- package/dist/services/import-export.d.ts +1 -1
- package/dist/services/import-export.js +14 -11
- package/dist/services/items.d.ts +3 -3
- package/dist/services/items.js +20 -6
- package/dist/services/payload.d.ts +3 -3
- package/dist/services/payload.js +11 -8
- package/dist/services/specifications.js +1 -3
- package/dist/services/users.d.ts +4 -0
- package/dist/services/users.js +24 -1
- package/dist/utils/{apply-query.d.ts → apply-query/index.d.ts} +2 -1
- package/dist/utils/apply-query/index.js +394 -0
- package/dist/utils/apply-query/operators/between.operator.d.ts +2 -0
- package/dist/utils/apply-query/operators/between.operator.js +16 -0
- package/dist/utils/apply-query/operators/contains.operator.d.ts +2 -0
- package/dist/utils/apply-query/operators/contains.operator.js +9 -0
- package/dist/utils/apply-query/operators/ends-with.operator.d.ts +2 -0
- package/dist/utils/apply-query/operators/ends-with.operator.js +9 -0
- package/dist/utils/apply-query/operators/equals.operator.d.ts +2 -0
- package/dist/utils/apply-query/operators/equals.operator.js +9 -0
- package/dist/utils/apply-query/operators/greather-than-equals.operator.d.ts +2 -0
- package/dist/utils/apply-query/operators/greather-than-equals.operator.js +9 -0
- package/dist/utils/apply-query/operators/greather-than.operator.d.ts +2 -0
- package/dist/utils/apply-query/operators/greather-than.operator.js +9 -0
- package/dist/utils/apply-query/operators/in.operator.d.ts +2 -0
- package/dist/utils/apply-query/operators/in.operator.js +14 -0
- package/dist/utils/apply-query/operators/index.d.ts +3 -0
- package/dist/utils/apply-query/operators/index.js +72 -0
- package/dist/utils/apply-query/operators/insensitive-contains.operator.d.ts +2 -0
- package/dist/utils/apply-query/operators/insensitive-contains.operator.js +9 -0
- package/dist/utils/apply-query/operators/insensitive-ends-with.operator.d.ts +2 -0
- package/dist/utils/apply-query/operators/insensitive-ends-with.operator.js +9 -0
- package/dist/utils/apply-query/operators/insensitive-equals.operator.d.ts +2 -0
- package/dist/utils/apply-query/operators/insensitive-equals.operator.js +9 -0
- package/dist/utils/apply-query/operators/insensitive-not-contains.operator.d.ts +2 -0
- package/dist/utils/apply-query/operators/insensitive-not-contains.operator.js +9 -0
- package/dist/utils/apply-query/operators/insensitive-not-ends-with.operator.d.ts +2 -0
- package/dist/utils/apply-query/operators/insensitive-not-ends-with.operator.js +9 -0
- package/dist/utils/apply-query/operators/insensitive-not-equals.operator.d.ts +2 -0
- package/dist/utils/apply-query/operators/insensitive-not-equals.operator.js +9 -0
- package/dist/utils/apply-query/operators/insensitive-not-starts-with.operator.d.ts +2 -0
- package/dist/utils/apply-query/operators/insensitive-not-starts-with.operator.js +9 -0
- package/dist/utils/apply-query/operators/insensitive-starts-with.operator.d.ts +2 -0
- package/dist/utils/apply-query/operators/insensitive-starts-with.operator.js +9 -0
- package/dist/utils/apply-query/operators/intersects-bbox.operator.d.ts +2 -0
- package/dist/utils/apply-query/operators/intersects-bbox.operator.js +9 -0
- package/dist/utils/apply-query/operators/intersects.operator.d.ts +2 -0
- package/dist/utils/apply-query/operators/intersects.operator.js +9 -0
- package/dist/utils/apply-query/operators/is-empty.operator.d.ts +2 -0
- package/dist/utils/apply-query/operators/is-empty.operator.js +14 -0
- package/dist/utils/apply-query/operators/is-not-empty.operator.d.ts +2 -0
- package/dist/utils/apply-query/operators/is-not-empty.operator.js +14 -0
- package/dist/utils/apply-query/operators/is-not-null.operator.d.ts +2 -0
- package/dist/utils/apply-query/operators/is-not-null.operator.js +14 -0
- package/dist/utils/apply-query/operators/is-null.operator.d.ts +2 -0
- package/dist/utils/apply-query/operators/is-null.operator.js +14 -0
- package/dist/utils/apply-query/operators/less-than-equals.operator.d.ts +2 -0
- package/dist/utils/apply-query/operators/less-than-equals.operator.js +9 -0
- package/dist/utils/apply-query/operators/less-than.operator.d.ts +2 -0
- package/dist/utils/apply-query/operators/less-than.operator.js +9 -0
- package/dist/utils/apply-query/operators/not-between.operator.d.ts +2 -0
- package/dist/utils/apply-query/operators/not-between.operator.js +16 -0
- package/dist/utils/apply-query/operators/not-contains.operator.d.ts +2 -0
- package/dist/utils/apply-query/operators/not-contains.operator.js +9 -0
- package/dist/utils/apply-query/operators/not-ends-with.operator.d.ts +2 -0
- package/dist/utils/apply-query/operators/not-ends-with.operator.js +9 -0
- package/dist/utils/apply-query/operators/not-equals.operator.d.ts +2 -0
- package/dist/utils/apply-query/operators/not-equals.operator.js +9 -0
- package/dist/utils/apply-query/operators/not-in.operator.d.ts +2 -0
- package/dist/utils/apply-query/operators/not-in.operator.js +14 -0
- package/dist/utils/apply-query/operators/not-intersects-bbox.operator.d.ts +2 -0
- package/dist/utils/apply-query/operators/not-intersects-bbox.operator.js +9 -0
- package/dist/utils/apply-query/operators/not-intersects.operator.d.ts +2 -0
- package/dist/utils/apply-query/operators/not-intersects.operator.js +9 -0
- package/dist/utils/apply-query/operators/not-starts-with.operator.d.ts +2 -0
- package/dist/utils/apply-query/operators/not-starts-with.operator.js +9 -0
- package/dist/utils/apply-query/operators/operator-register.d.ts +13 -0
- package/dist/utils/apply-query/operators/operator-register.js +7 -0
- package/dist/utils/apply-query/operators/starts-with.operator.d.ts +2 -0
- package/dist/utils/apply-query/operators/starts-with.operator.js +9 -0
- package/dist/utils/apply-snapshot.d.ts +3 -3
- package/dist/utils/apply-snapshot.js +64 -49
- package/dist/utils/get-ast-from-query.js +10 -4
- package/dist/utils/get-column-path.d.ts +16 -0
- package/dist/utils/get-column-path.js +46 -0
- package/dist/utils/get-default-value.js +4 -3
- package/dist/utils/get-permissions.d.ts +1 -1
- package/dist/utils/get-permissions.js +9 -8
- package/dist/utils/get-relation-info.d.ts +7 -0
- package/dist/utils/get-relation-info.js +45 -0
- package/dist/utils/get-relation-type.d.ts +1 -1
- package/dist/utils/get-schema.js +5 -1
- package/dist/utils/get-snapshot.js +22 -4
- package/dist/utils/merge-permissions-for-share.js +1 -1
- package/dist/utils/parse-json.d.ts +5 -0
- package/dist/utils/parse-json.js +19 -0
- package/dist/utils/reduce-schema.js +18 -11
- package/dist/utils/sanitize-query.d.ts +1 -2
- package/dist/utils/sanitize-query.js +6 -5
- package/package.json +16 -18
- package/dist/utils/apply-query.js +0 -498
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getColumnPath = void 0;
|
|
4
|
+
const get_relation_info_1 = require("./get-relation-info");
|
|
5
|
+
const exceptions_1 = require("../exceptions");
|
|
6
|
+
const lodash_1 = require("lodash");
|
|
7
|
+
/**
|
|
8
|
+
* Converts a Directus field list path to the correct SQL names based on the constructed alias map.
|
|
9
|
+
* For example: ['author', 'role', 'name'] -> 'ljnsv.name'
|
|
10
|
+
*/
|
|
11
|
+
function getColumnPath({ path, collection, aliasMap, relations }) {
|
|
12
|
+
return followRelation(path);
|
|
13
|
+
function followRelation(pathParts, parentCollection = collection, parentAlias) {
|
|
14
|
+
/**
|
|
15
|
+
* For A2M fields, the path can contain an optional collection scope <field>:<scope>
|
|
16
|
+
*/
|
|
17
|
+
const pathRoot = pathParts[0].split(':')[0];
|
|
18
|
+
const { relation, relationType } = (0, get_relation_info_1.getRelationInfo)(relations, parentCollection, pathRoot);
|
|
19
|
+
if (!relation) {
|
|
20
|
+
throw new exceptions_1.InvalidQueryException(`"${parentCollection}.${pathRoot}" is not a relational field`);
|
|
21
|
+
}
|
|
22
|
+
const alias = (0, lodash_1.get)(aliasMap, parentAlias ? [parentAlias, ...pathParts] : pathParts);
|
|
23
|
+
const remainingParts = pathParts.slice(1);
|
|
24
|
+
let parent;
|
|
25
|
+
if (relationType === 'a2o') {
|
|
26
|
+
const pathScope = pathParts[0].split(':')[1];
|
|
27
|
+
if (!pathScope) {
|
|
28
|
+
throw new exceptions_1.InvalidQueryException(`You have to provide a collection scope when sorting on a many-to-any item`);
|
|
29
|
+
}
|
|
30
|
+
parent = pathScope;
|
|
31
|
+
}
|
|
32
|
+
else if (relationType === 'm2o') {
|
|
33
|
+
parent = relation.related_collection;
|
|
34
|
+
}
|
|
35
|
+
else {
|
|
36
|
+
parent = relation.collection;
|
|
37
|
+
}
|
|
38
|
+
if (remainingParts.length === 1) {
|
|
39
|
+
return `${alias || parent}.${remainingParts[0]}`;
|
|
40
|
+
}
|
|
41
|
+
if (remainingParts.length) {
|
|
42
|
+
return followRelation(remainingParts, parent, alias);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
exports.getColumnPath = getColumnPath;
|
|
@@ -3,9 +3,10 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
const get_local_type_1 = __importDefault(require("./get-local-type"));
|
|
7
|
-
const logger_1 = __importDefault(require("../logger"));
|
|
8
6
|
const env_1 = __importDefault(require("../env"));
|
|
7
|
+
const logger_1 = __importDefault(require("../logger"));
|
|
8
|
+
const get_local_type_1 = __importDefault(require("./get-local-type"));
|
|
9
|
+
const parse_json_1 = require("./parse-json");
|
|
9
10
|
function getDefaultValue(column) {
|
|
10
11
|
var _a;
|
|
11
12
|
const type = (0, get_local_type_1.default)(column);
|
|
@@ -59,7 +60,7 @@ function castToObject(value) {
|
|
|
59
60
|
return value;
|
|
60
61
|
if (typeof value === 'string') {
|
|
61
62
|
try {
|
|
62
|
-
return
|
|
63
|
+
return (0, parse_json_1.parseJSON)(value);
|
|
63
64
|
}
|
|
64
65
|
catch (err) {
|
|
65
66
|
if (env_1.default.NODE_ENV === 'development') {
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Accountability, Permission, SchemaOverview } from '@directus/shared/types';
|
|
2
2
|
export declare function getPermissions(accountability: Accountability, schema: SchemaOverview): Promise<Permission[]>;
|
|
@@ -6,15 +6,16 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
6
6
|
exports.getPermissions = void 0;
|
|
7
7
|
const utils_1 = require("@directus/shared/utils");
|
|
8
8
|
const lodash_1 = require("lodash");
|
|
9
|
+
const object_hash_1 = __importDefault(require("object-hash"));
|
|
10
|
+
const cache_1 = require("../cache");
|
|
9
11
|
const database_1 = __importDefault(require("../database"));
|
|
10
12
|
const app_access_permissions_1 = require("../database/system-data/app-access-permissions");
|
|
13
|
+
const env_1 = __importDefault(require("../env"));
|
|
14
|
+
const roles_1 = require("../services/roles");
|
|
15
|
+
const users_1 = require("../services/users");
|
|
11
16
|
const merge_permissions_1 = require("../utils/merge-permissions");
|
|
12
17
|
const merge_permissions_for_share_1 = require("./merge-permissions-for-share");
|
|
13
|
-
const
|
|
14
|
-
const roles_1 = require("../services/roles");
|
|
15
|
-
const cache_1 = require("../cache");
|
|
16
|
-
const object_hash_1 = __importDefault(require("object-hash"));
|
|
17
|
-
const env_1 = __importDefault(require("../env"));
|
|
18
|
+
const parse_json_1 = require("./parse-json");
|
|
18
19
|
async function getPermissions(accountability, schema) {
|
|
19
20
|
const database = (0, database_1.default)();
|
|
20
21
|
const { systemCache, cache } = (0, cache_1.getCache)();
|
|
@@ -84,19 +85,19 @@ function parsePermissions(permissions) {
|
|
|
84
85
|
permissions = permissions.map((permissionRaw) => {
|
|
85
86
|
const permission = (0, lodash_1.cloneDeep)(permissionRaw);
|
|
86
87
|
if (permission.permissions && typeof permission.permissions === 'string') {
|
|
87
|
-
permission.permissions =
|
|
88
|
+
permission.permissions = (0, parse_json_1.parseJSON)(permission.permissions);
|
|
88
89
|
}
|
|
89
90
|
else if (permission.permissions === null) {
|
|
90
91
|
permission.permissions = {};
|
|
91
92
|
}
|
|
92
93
|
if (permission.validation && typeof permission.validation === 'string') {
|
|
93
|
-
permission.validation =
|
|
94
|
+
permission.validation = (0, parse_json_1.parseJSON)(permission.validation);
|
|
94
95
|
}
|
|
95
96
|
else if (permission.validation === null) {
|
|
96
97
|
permission.validation = {};
|
|
97
98
|
}
|
|
98
99
|
if (permission.presets && typeof permission.presets === 'string') {
|
|
99
|
-
permission.presets =
|
|
100
|
+
permission.presets = (0, parse_json_1.parseJSON)(permission.presets);
|
|
100
101
|
}
|
|
101
102
|
else if (permission.presets === null) {
|
|
102
103
|
permission.presets = {};
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { Relation } from '@directus/shared/types';
|
|
2
|
+
declare type RelationInfo = {
|
|
3
|
+
relation: Relation | null;
|
|
4
|
+
relationType: string | null;
|
|
5
|
+
};
|
|
6
|
+
export declare function getRelationInfo(relations: Relation[], collection: string, field: string): RelationInfo;
|
|
7
|
+
export {};
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getRelationInfo = void 0;
|
|
4
|
+
const get_relation_type_1 = require("./get-relation-type");
|
|
5
|
+
function getRelationInfo(relations, collection, field) {
|
|
6
|
+
var _a, _b;
|
|
7
|
+
if (field.startsWith('$FOLLOW') && field.length > 500) {
|
|
8
|
+
throw new Error(`Implicit $FOLLOW statement is too big to parse. Got: "${field.substring(500)}..."`);
|
|
9
|
+
}
|
|
10
|
+
const implicitRelation = (_a = field.match(/^\$FOLLOW\((.*?),(.*?)(?:,(.*?))?\)$/)) === null || _a === void 0 ? void 0 : _a.slice(1);
|
|
11
|
+
if (implicitRelation) {
|
|
12
|
+
if (implicitRelation[2] === undefined) {
|
|
13
|
+
const [m2oCollection, m2oField] = implicitRelation;
|
|
14
|
+
const relation = {
|
|
15
|
+
collection: m2oCollection.trim(),
|
|
16
|
+
field: m2oField.trim(),
|
|
17
|
+
related_collection: collection,
|
|
18
|
+
schema: null,
|
|
19
|
+
meta: null,
|
|
20
|
+
};
|
|
21
|
+
return { relation, relationType: 'o2m' };
|
|
22
|
+
}
|
|
23
|
+
else {
|
|
24
|
+
const [a2oCollection, a2oItemField, a2oCollectionField] = implicitRelation;
|
|
25
|
+
const relation = {
|
|
26
|
+
collection: a2oCollection.trim(),
|
|
27
|
+
field: a2oItemField.trim(),
|
|
28
|
+
related_collection: collection,
|
|
29
|
+
schema: null,
|
|
30
|
+
meta: {
|
|
31
|
+
one_collection_field: a2oCollectionField.trim(),
|
|
32
|
+
},
|
|
33
|
+
};
|
|
34
|
+
return { relation, relationType: 'o2a' };
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
const relation = (_b = relations.find((relation) => {
|
|
38
|
+
var _a;
|
|
39
|
+
return ((relation.collection === collection && relation.field === field) ||
|
|
40
|
+
(relation.related_collection === collection && ((_a = relation.meta) === null || _a === void 0 ? void 0 : _a.one_field) === field));
|
|
41
|
+
})) !== null && _b !== void 0 ? _b : null;
|
|
42
|
+
const relationType = relation ? (0, get_relation_type_1.getRelationType)({ relation, collection, field }) : null;
|
|
43
|
+
return { relation, relationType };
|
|
44
|
+
}
|
|
45
|
+
exports.getRelationInfo = getRelationInfo;
|
package/dist/utils/get-schema.js
CHANGED
|
@@ -8,6 +8,7 @@ const schema_1 = __importDefault(require("@directus/schema"));
|
|
|
8
8
|
const utils_1 = require("@directus/shared/utils");
|
|
9
9
|
const lodash_1 = require("lodash");
|
|
10
10
|
const cache_1 = require("../cache");
|
|
11
|
+
const constants_1 = require("../constants");
|
|
11
12
|
const database_1 = __importDefault(require("../database"));
|
|
12
13
|
const collections_1 = require("../database/system-data/collections");
|
|
13
14
|
const fields_1 = require("../database/system-data/fields");
|
|
@@ -16,6 +17,7 @@ const logger_1 = __importDefault(require("../logger"));
|
|
|
16
17
|
const services_1 = require("../services");
|
|
17
18
|
const get_default_value_1 = __importDefault(require("./get-default-value"));
|
|
18
19
|
const get_local_type_1 = __importDefault(require("./get-local-type"));
|
|
20
|
+
const parse_json_1 = require("./parse-json");
|
|
19
21
|
async function getSchema(options) {
|
|
20
22
|
const database = (options === null || options === void 0 ? void 0 : options.database) || (0, database_1.default)();
|
|
21
23
|
const schemaInspector = (0, schema_1.default)(database);
|
|
@@ -113,10 +115,12 @@ async function getDatabaseSchema(database, schemaInspector) {
|
|
|
113
115
|
const existing = result.collections[field.collection].fields[field.field];
|
|
114
116
|
const column = schemaOverview[field.collection].columns[field.field];
|
|
115
117
|
const special = field.special ? (0, utils_1.toArray)(field.special) : [];
|
|
118
|
+
if (constants_1.ALIAS_TYPES.some((type) => special.includes(type)) === false && !existing)
|
|
119
|
+
continue;
|
|
116
120
|
const type = (existing && (0, get_local_type_1.default)(column, { special })) || 'alias';
|
|
117
121
|
let validation = (_a = field.validation) !== null && _a !== void 0 ? _a : null;
|
|
118
122
|
if (validation && typeof validation === 'string')
|
|
119
|
-
validation =
|
|
123
|
+
validation = (0, parse_json_1.parseJSON)(validation);
|
|
120
124
|
result.collections[field.collection].fields[field.field] = {
|
|
121
125
|
field: field.field,
|
|
122
126
|
defaultValue: (_b = existing === null || existing === void 0 ? void 0 : existing.defaultValue) !== null && _b !== void 0 ? _b : null,
|
|
@@ -16,17 +16,23 @@ async function getSnapshot(options) {
|
|
|
16
16
|
const collectionsService = new services_1.CollectionsService({ knex: database, schema });
|
|
17
17
|
const fieldsService = new services_1.FieldsService({ knex: database, schema });
|
|
18
18
|
const relationsService = new services_1.RelationsService({ knex: database, schema });
|
|
19
|
-
const [
|
|
19
|
+
const [collectionsRaw, fieldsRaw, relationsRaw] = await Promise.all([
|
|
20
20
|
collectionsService.readByQuery(),
|
|
21
21
|
fieldsService.readAll(),
|
|
22
22
|
relationsService.readAll(),
|
|
23
23
|
]);
|
|
24
|
+
const collectionsFiltered = collectionsRaw.filter((item) => excludeSystem(item));
|
|
25
|
+
const fieldsFiltered = fieldsRaw.filter((item) => excludeSystem(item)).map(omitID);
|
|
26
|
+
const relationsFiltered = relationsRaw.filter((item) => excludeSystem(item)).map(omitID);
|
|
27
|
+
const collectionsSorted = (0, lodash_1.sortBy)((0, lodash_1.mapValues)(collectionsFiltered, sortDeep), ['collection']);
|
|
28
|
+
const fieldsSorted = (0, lodash_1.sortBy)((0, lodash_1.mapValues)(fieldsFiltered, sortDeep), ['collection', 'field']);
|
|
29
|
+
const relationsSorted = (0, lodash_1.sortBy)((0, lodash_1.mapValues)(relationsFiltered, sortDeep), ['collection', 'field']);
|
|
24
30
|
return {
|
|
25
31
|
version: 1,
|
|
26
32
|
directus: package_json_1.version,
|
|
27
|
-
collections:
|
|
28
|
-
fields:
|
|
29
|
-
relations:
|
|
33
|
+
collections: collectionsSorted,
|
|
34
|
+
fields: fieldsSorted,
|
|
35
|
+
relations: relationsSorted,
|
|
30
36
|
};
|
|
31
37
|
}
|
|
32
38
|
exports.getSnapshot = getSnapshot;
|
|
@@ -39,3 +45,15 @@ function excludeSystem(item) {
|
|
|
39
45
|
function omitID(item) {
|
|
40
46
|
return (0, lodash_1.omit)(item, 'meta.id');
|
|
41
47
|
}
|
|
48
|
+
function sortDeep(raw) {
|
|
49
|
+
if ((0, lodash_1.isPlainObject)(raw)) {
|
|
50
|
+
const mapped = (0, lodash_1.mapValues)(raw, sortDeep);
|
|
51
|
+
const pairs = (0, lodash_1.toPairs)(mapped);
|
|
52
|
+
const sorted = (0, lodash_1.sortBy)(pairs);
|
|
53
|
+
return (0, lodash_1.fromPairs)(sorted);
|
|
54
|
+
}
|
|
55
|
+
if ((0, lodash_1.isArray)(raw)) {
|
|
56
|
+
return (0, lodash_1.sortBy)(raw);
|
|
57
|
+
}
|
|
58
|
+
return raw;
|
|
59
|
+
}
|
|
@@ -48,7 +48,7 @@ function mergePermissionsForShare(currentPermissions, accountability, schema) {
|
|
|
48
48
|
}
|
|
49
49
|
}
|
|
50
50
|
// Explicitly filter out permissions to collections unrelated to the root parent item.
|
|
51
|
-
const limitedPermissions = currentPermissions.filter(({ collection }) => allowedCollections.includes(collection));
|
|
51
|
+
const limitedPermissions = currentPermissions.filter(({ action, collection }) => allowedCollections.includes(collection) && action === 'read');
|
|
52
52
|
return (0, merge_permissions_1.mergePermissions)('and', limitedPermissions, generatedPermissions);
|
|
53
53
|
}
|
|
54
54
|
exports.mergePermissionsForShare = mergePermissionsForShare;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.noproto = exports.parseJSON = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* Run JSON.parse, but ignore `__proto__` properties. This prevents prototype pollution attacks
|
|
6
|
+
*/
|
|
7
|
+
function parseJSON(input) {
|
|
8
|
+
if (String(input).includes('__proto__')) {
|
|
9
|
+
return JSON.parse(input, noproto);
|
|
10
|
+
}
|
|
11
|
+
return JSON.parse(input);
|
|
12
|
+
}
|
|
13
|
+
exports.parseJSON = parseJSON;
|
|
14
|
+
function noproto(key, value) {
|
|
15
|
+
if (key !== '__proto__') {
|
|
16
|
+
return value;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
exports.noproto = noproto;
|
|
@@ -25,19 +25,26 @@ function reduceSchema(schema, permissions, actions = ['create', 'read', 'update'
|
|
|
25
25
|
return acc;
|
|
26
26
|
}, {})) !== null && _a !== void 0 ? _a : {};
|
|
27
27
|
for (const [collectionName, collection] of Object.entries(schema.collections)) {
|
|
28
|
-
if (permissions === null || permissions === void 0 ? void 0 : permissions.some((permission) => permission.collection === collectionName && actions.includes(permission.action))) {
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
28
|
+
if (!(permissions === null || permissions === void 0 ? void 0 : permissions.some((permission) => permission.collection === collectionName && actions.includes(permission.action)))) {
|
|
29
|
+
continue;
|
|
30
|
+
}
|
|
31
|
+
const fields = {};
|
|
32
|
+
for (const [fieldName, field] of Object.entries(schema.collections[collectionName].fields)) {
|
|
33
|
+
if (!((_b = allowedFieldsInCollection[collectionName]) === null || _b === void 0 ? void 0 : _b.includes('*')) &&
|
|
34
|
+
!((_c = allowedFieldsInCollection[collectionName]) === null || _c === void 0 ? void 0 : _c.includes(fieldName))) {
|
|
35
|
+
continue;
|
|
36
|
+
}
|
|
37
|
+
const o2mRelation = schema.relations.find((relation) => { var _a; return relation.related_collection === collectionName && ((_a = relation.meta) === null || _a === void 0 ? void 0 : _a.one_field) === fieldName; });
|
|
38
|
+
if (o2mRelation &&
|
|
39
|
+
!(permissions === null || permissions === void 0 ? void 0 : permissions.some((permission) => permission.collection === o2mRelation.collection && actions.includes(permission.action)))) {
|
|
40
|
+
continue;
|
|
35
41
|
}
|
|
36
|
-
|
|
37
|
-
...collection,
|
|
38
|
-
fields,
|
|
39
|
-
};
|
|
42
|
+
fields[fieldName] = field;
|
|
40
43
|
}
|
|
44
|
+
reduced.collections[collectionName] = {
|
|
45
|
+
...collection,
|
|
46
|
+
fields,
|
|
47
|
+
};
|
|
41
48
|
}
|
|
42
49
|
reduced.relations = schema.relations.filter((relation) => {
|
|
43
50
|
var _a, _b, _c;
|
|
@@ -1,3 +1,2 @@
|
|
|
1
|
-
import { Query } from '@directus/shared/types';
|
|
2
|
-
import { Accountability } from '@directus/shared/types';
|
|
1
|
+
import { Accountability, Query } from '@directus/shared/types';
|
|
3
2
|
export declare function sanitizeQuery(rawQuery: Record<string, any>, accountability?: Accountability | null): Query;
|
|
@@ -4,10 +4,11 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.sanitizeQuery = void 0;
|
|
7
|
+
const utils_1 = require("@directus/shared/utils");
|
|
7
8
|
const lodash_1 = require("lodash");
|
|
8
9
|
const logger_1 = __importDefault(require("../logger"));
|
|
9
10
|
const types_1 = require("../types");
|
|
10
|
-
const
|
|
11
|
+
const parse_json_1 = require("./parse-json");
|
|
11
12
|
function sanitizeQuery(rawQuery, accountability) {
|
|
12
13
|
const query = {};
|
|
13
14
|
if (rawQuery.limit !== undefined) {
|
|
@@ -82,7 +83,7 @@ function sanitizeAggregate(rawAggregate) {
|
|
|
82
83
|
let aggregate = rawAggregate;
|
|
83
84
|
if (typeof rawAggregate === 'string') {
|
|
84
85
|
try {
|
|
85
|
-
aggregate =
|
|
86
|
+
aggregate = (0, parse_json_1.parseJSON)(rawAggregate);
|
|
86
87
|
}
|
|
87
88
|
catch {
|
|
88
89
|
logger_1.default.warn('Invalid value passed for filter query parameter.');
|
|
@@ -100,7 +101,7 @@ function sanitizeFilter(rawFilter, accountability) {
|
|
|
100
101
|
let filters = rawFilter;
|
|
101
102
|
if (typeof rawFilter === 'string') {
|
|
102
103
|
try {
|
|
103
|
-
filters =
|
|
104
|
+
filters = (0, parse_json_1.parseJSON)(rawFilter);
|
|
104
105
|
}
|
|
105
106
|
catch {
|
|
106
107
|
logger_1.default.warn('Invalid value passed for filter query parameter.');
|
|
@@ -135,7 +136,7 @@ function sanitizeDeep(deep, accountability) {
|
|
|
135
136
|
const result = {};
|
|
136
137
|
if (typeof deep === 'string') {
|
|
137
138
|
try {
|
|
138
|
-
deep =
|
|
139
|
+
deep = (0, parse_json_1.parseJSON)(deep);
|
|
139
140
|
}
|
|
140
141
|
catch {
|
|
141
142
|
logger_1.default.warn('Invalid value passed for deep query parameter.');
|
|
@@ -169,7 +170,7 @@ function sanitizeAlias(rawAlias) {
|
|
|
169
170
|
let alias = rawAlias;
|
|
170
171
|
if (typeof rawAlias === 'string') {
|
|
171
172
|
try {
|
|
172
|
-
alias =
|
|
173
|
+
alias = (0, parse_json_1.parseJSON)(rawAlias);
|
|
173
174
|
}
|
|
174
175
|
catch (err) {
|
|
175
176
|
logger_1.default.warn('Invalid value passed for alias query parameter.');
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "directus",
|
|
3
|
-
"version": "9.
|
|
3
|
+
"version": "9.11.0",
|
|
4
4
|
"license": "GPL-3.0-only",
|
|
5
5
|
"homepage": "https://github.com/directus/directus#readme",
|
|
6
6
|
"description": "Directus is a real-time API and App dashboard for managing SQL database content.",
|
|
@@ -78,16 +78,16 @@
|
|
|
78
78
|
],
|
|
79
79
|
"dependencies": {
|
|
80
80
|
"@aws-sdk/client-ses": "^3.40.0",
|
|
81
|
-
"@directus/app": "9.
|
|
82
|
-
"@directus/drive": "9.
|
|
83
|
-
"@directus/drive-azure": "9.
|
|
84
|
-
"@directus/drive-gcs": "9.
|
|
85
|
-
"@directus/drive-s3": "9.
|
|
86
|
-
"@directus/extensions-sdk": "9.
|
|
87
|
-
"@directus/format-title": "9.
|
|
88
|
-
"@directus/schema": "9.
|
|
89
|
-
"@directus/shared": "9.
|
|
90
|
-
"@directus/specs": "9.
|
|
81
|
+
"@directus/app": "9.11.0",
|
|
82
|
+
"@directus/drive": "9.11.0",
|
|
83
|
+
"@directus/drive-azure": "9.11.0",
|
|
84
|
+
"@directus/drive-gcs": "9.11.0",
|
|
85
|
+
"@directus/drive-s3": "9.11.0",
|
|
86
|
+
"@directus/extensions-sdk": "9.11.0",
|
|
87
|
+
"@directus/format-title": "9.11.0",
|
|
88
|
+
"@directus/schema": "9.11.0",
|
|
89
|
+
"@directus/shared": "9.11.0",
|
|
90
|
+
"@directus/specs": "9.11.0",
|
|
91
91
|
"@godaddy/terminus": "^4.9.0",
|
|
92
92
|
"@rollup/plugin-alias": "^3.1.9",
|
|
93
93
|
"@rollup/plugin-virtual": "^2.0.3",
|
|
@@ -124,7 +124,7 @@
|
|
|
124
124
|
"json2csv": "^5.0.3",
|
|
125
125
|
"jsonwebtoken": "^8.5.1",
|
|
126
126
|
"keyv": "^4.0.3",
|
|
127
|
-
"knex": "^0.
|
|
127
|
+
"knex": "^2.0.0",
|
|
128
128
|
"knex-schema-inspector": "1.7.3",
|
|
129
129
|
"ldapjs": "^2.3.1",
|
|
130
130
|
"liquidjs": "^9.25.0",
|
|
@@ -152,6 +152,7 @@
|
|
|
152
152
|
"sanitize-html": "^2.6.0",
|
|
153
153
|
"sharp": "^0.30.3",
|
|
154
154
|
"stream-json": "^1.7.1",
|
|
155
|
+
"strip-bom-stream": "^4.0.0",
|
|
155
156
|
"supertest": "^6.1.6",
|
|
156
157
|
"tmp-promise": "^3.0.3",
|
|
157
158
|
"update-check": "^1.5.4",
|
|
@@ -161,19 +162,16 @@
|
|
|
161
162
|
},
|
|
162
163
|
"optionalDependencies": {
|
|
163
164
|
"@keyv/redis": "^2.1.2",
|
|
164
|
-
"connect-memcached": "^1.0.0",
|
|
165
|
-
"connect-redis": "^6.0.0",
|
|
166
|
-
"connect-session-knex": "^2.1.0",
|
|
167
165
|
"ioredis": "^4.27.6",
|
|
168
166
|
"keyv-memcache": "^1.2.5",
|
|
169
167
|
"memcached": "^2.2.2",
|
|
170
168
|
"mysql": "^2.18.1",
|
|
171
169
|
"nodemailer-mailgun-transport": "^2.1.3",
|
|
172
170
|
"pg": "^8.6.0",
|
|
173
|
-
"sqlite3": "^5.0.
|
|
171
|
+
"sqlite3": "^5.0.6",
|
|
174
172
|
"tedious": "^13.0.0"
|
|
175
173
|
},
|
|
176
|
-
"gitHead": "
|
|
174
|
+
"gitHead": "f52da51925296b6e615ae2f048727a391d3a2122",
|
|
177
175
|
"devDependencies": {
|
|
178
176
|
"@types/async": "3.2.10",
|
|
179
177
|
"@types/body-parser": "1.19.2",
|
|
@@ -216,7 +214,7 @@
|
|
|
216
214
|
"cross-env": "7.0.3",
|
|
217
215
|
"form-data": "^4.0.0",
|
|
218
216
|
"jest": "27.5.1",
|
|
219
|
-
"knex-mock-client": "1.
|
|
217
|
+
"knex-mock-client": "1.7.0",
|
|
220
218
|
"ts-jest": "27.1.3",
|
|
221
219
|
"ts-node-dev": "1.1.8",
|
|
222
220
|
"typescript": "4.5.2"
|