directus 9.9.0 → 9.9.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.
- package/dist/controllers/files.js +3 -0
- package/dist/database/helpers/fn/dialects/postgres.js +5 -1
- package/dist/database/run-ast.js +3 -3
- package/dist/database/system-data/fields/collections.yaml +1 -1
- package/dist/env.js +2 -2
- package/dist/services/collections.js +2 -0
- package/dist/services/fields.js +2 -0
- package/dist/services/graphql.js +14 -1
- package/dist/services/items.js +5 -3
- package/dist/services/payload.d.ts +1 -1
- package/dist/services/payload.js +2 -0
- package/dist/services/specifications.js +1 -3
- package/dist/services/users.js +4 -1
- package/dist/utils/apply-query.js +1 -1
- package/dist/utils/get-ast-from-query.js +15 -3
- package/dist/utils/get-schema.js +3 -0
- package/dist/utils/reduce-schema.js +20 -12
- package/package.json +12 -12
|
@@ -58,6 +58,9 @@ const multipartHandler = (req, res, next) => {
|
|
|
58
58
|
payload[fieldname] = fieldValue;
|
|
59
59
|
});
|
|
60
60
|
busboy.on('file', async (fieldname, fileStream, filename, encoding, mimetype) => {
|
|
61
|
+
if (!filename) {
|
|
62
|
+
return busboy.emit('error', new exceptions_1.InvalidPayloadException(`File is missing filename`));
|
|
63
|
+
}
|
|
61
64
|
fileCount++;
|
|
62
65
|
if (!payload.title) {
|
|
63
66
|
payload.title = (0, format_title_1.default)(path_1.default.parse(filename).name);
|
|
@@ -31,7 +31,11 @@ class FnHelperPostgres extends types_1.FnHelper {
|
|
|
31
31
|
var _a, _b, _c, _d, _e;
|
|
32
32
|
const type = (_e = (_d = (_c = (_b = (_a = this.schema.collections) === null || _a === void 0 ? void 0 : _a[table]) === null || _b === void 0 ? void 0 : _b.fields) === null || _c === void 0 ? void 0 : _c[column]) === null || _d === void 0 ? void 0 : _d.type) !== null && _e !== void 0 ? _e : 'unknown';
|
|
33
33
|
if (type === 'json') {
|
|
34
|
-
|
|
34
|
+
const { dbType } = this.schema.collections[table].fields[column];
|
|
35
|
+
return this.knex.raw(dbType === 'jsonb' ? 'jsonb_array_length(??.??)' : 'json_array_length(??.??)', [
|
|
36
|
+
table,
|
|
37
|
+
column,
|
|
38
|
+
]);
|
|
35
39
|
}
|
|
36
40
|
if (type === 'alias') {
|
|
37
41
|
return this._relationalCount(table, column);
|
package/dist/database/run-ast.js
CHANGED
|
@@ -107,7 +107,7 @@ async function parseCurrentLevel(schema, collection, children, query) {
|
|
|
107
107
|
if (!child.relation)
|
|
108
108
|
continue;
|
|
109
109
|
if (child.type === 'm2o') {
|
|
110
|
-
columnsToSelectInternal.push(child.
|
|
110
|
+
columnsToSelectInternal.push(child.relation.field);
|
|
111
111
|
}
|
|
112
112
|
if (child.type === 'a2o') {
|
|
113
113
|
columnsToSelectInternal.push(child.relation.field);
|
|
@@ -126,7 +126,7 @@ async function parseCurrentLevel(schema, collection, children, query) {
|
|
|
126
126
|
const columnsToSelect = [...new Set(columnsToSelectInternal)];
|
|
127
127
|
const fieldNodes = columnsToSelect.map((column) => {
|
|
128
128
|
var _a;
|
|
129
|
-
return (_a = children.find((childNode) => childNode.type === 'field' && childNode.fieldKey === column)) !== null && _a !== void 0 ? _a : {
|
|
129
|
+
return (_a = children.find((childNode) => childNode.type === 'field' && (childNode.fieldKey === column || childNode.name === column))) !== null && _a !== void 0 ? _a : {
|
|
130
130
|
type: 'field',
|
|
131
131
|
name: column,
|
|
132
132
|
fieldKey: column,
|
|
@@ -221,7 +221,7 @@ function mergeWithParentItems(schema, nestedItem, parentItem, nestedNode) {
|
|
|
221
221
|
for (const parentItem of parentItems) {
|
|
222
222
|
const itemChild = nestedItems.find((nestedItem) => {
|
|
223
223
|
return (nestedItem[schema.collections[nestedNode.relation.related_collection].primary] ==
|
|
224
|
-
parentItem[nestedNode.
|
|
224
|
+
parentItem[nestedNode.relation.field]);
|
|
225
225
|
});
|
|
226
226
|
parentItem[nestedNode.fieldKey] = itemChild || null;
|
|
227
227
|
}
|
package/dist/env.js
CHANGED
|
@@ -87,8 +87,8 @@ const typeMap = {
|
|
|
87
87
|
};
|
|
88
88
|
let env = {
|
|
89
89
|
...defaults,
|
|
90
|
-
...getEnv(),
|
|
91
90
|
...process.env,
|
|
91
|
+
...getEnv(),
|
|
92
92
|
};
|
|
93
93
|
process.env = env;
|
|
94
94
|
env = processValues(env);
|
|
@@ -100,8 +100,8 @@ exports.default = env;
|
|
|
100
100
|
function refreshEnv() {
|
|
101
101
|
env = {
|
|
102
102
|
...defaults,
|
|
103
|
-
...getEnv(),
|
|
104
103
|
...process.env,
|
|
104
|
+
...getEnv(),
|
|
105
105
|
};
|
|
106
106
|
process.env = env;
|
|
107
107
|
env = processValues(env);
|
package/dist/services/fields.js
CHANGED
package/dist/services/graphql.js
CHANGED
|
@@ -1175,6 +1175,7 @@ class GraphQLService {
|
|
|
1175
1175
|
continue;
|
|
1176
1176
|
selection = selection;
|
|
1177
1177
|
let current;
|
|
1178
|
+
let currentAlias = null;
|
|
1178
1179
|
// Union type (Many-to-Any)
|
|
1179
1180
|
if (selection.kind === 'InlineFragment') {
|
|
1180
1181
|
if (selection.typeCondition.name.value.startsWith('__'))
|
|
@@ -1187,8 +1188,20 @@ class GraphQLService {
|
|
|
1187
1188
|
if (selection.name.value.startsWith('__'))
|
|
1188
1189
|
continue;
|
|
1189
1190
|
current = selection.name.value;
|
|
1191
|
+
if (selection.alias) {
|
|
1192
|
+
currentAlias = selection.alias.value;
|
|
1193
|
+
}
|
|
1190
1194
|
if (parent) {
|
|
1191
1195
|
current = `${parent}.${current}`;
|
|
1196
|
+
if (currentAlias) {
|
|
1197
|
+
currentAlias = `${parent}.${currentAlias}`;
|
|
1198
|
+
// add nested aliases into deep query
|
|
1199
|
+
if (selection.selectionSet) {
|
|
1200
|
+
if (!query.deep)
|
|
1201
|
+
query.deep = {};
|
|
1202
|
+
(0, lodash_1.set)(query.deep, parent, (0, lodash_1.merge)((0, lodash_1.get)(query.deep, parent), { _alias: { [selection.alias.value]: selection.name.value } }));
|
|
1203
|
+
}
|
|
1204
|
+
}
|
|
1192
1205
|
}
|
|
1193
1206
|
}
|
|
1194
1207
|
if (selection.selectionSet) {
|
|
@@ -1203,7 +1216,7 @@ class GraphQLService {
|
|
|
1203
1216
|
}
|
|
1204
1217
|
}
|
|
1205
1218
|
else {
|
|
1206
|
-
children = parseFields(selection.selectionSet.selections, current);
|
|
1219
|
+
children = parseFields(selection.selectionSet.selections, currentAlias !== null && currentAlias !== void 0 ? currentAlias : current);
|
|
1207
1220
|
}
|
|
1208
1221
|
fields.push(...children);
|
|
1209
1222
|
}
|
package/dist/services/items.js
CHANGED
|
@@ -354,13 +354,14 @@ class ItemsService {
|
|
|
354
354
|
knex: trx,
|
|
355
355
|
schema: this.schema,
|
|
356
356
|
});
|
|
357
|
-
const
|
|
357
|
+
const revisions = (await Promise.all(activity.map(async (activity, index) => ({
|
|
358
358
|
activity: activity,
|
|
359
359
|
collection: this.collection,
|
|
360
360
|
item: keys[index],
|
|
361
361
|
data: snapshots && Array.isArray(snapshots) ? JSON.stringify(snapshots[index]) : JSON.stringify(snapshots),
|
|
362
362
|
delta: await payloadService.prepareDelta(payloadWithTypeCasting),
|
|
363
|
-
}))));
|
|
363
|
+
})))).filter((revision) => revision.delta);
|
|
364
|
+
const revisionIDs = await revisionsService.createMany(revisions);
|
|
364
365
|
for (let i = 0; i < revisionIDs.length; i++) {
|
|
365
366
|
const revisionID = revisionIDs[i];
|
|
366
367
|
if (opts === null || opts === void 0 ? void 0 : opts.onRevisionCreate) {
|
|
@@ -529,7 +530,8 @@ class ItemsService {
|
|
|
529
530
|
defaults[name] = null;
|
|
530
531
|
continue;
|
|
531
532
|
}
|
|
532
|
-
|
|
533
|
+
if (field.defaultValue)
|
|
534
|
+
defaults[name] = field.defaultValue;
|
|
533
535
|
}
|
|
534
536
|
return defaults;
|
|
535
537
|
}
|
|
@@ -65,6 +65,6 @@ export declare class PayloadService {
|
|
|
65
65
|
* Transforms the input partial payload to match the output structure, to have consistency
|
|
66
66
|
* between delta and data
|
|
67
67
|
*/
|
|
68
|
-
prepareDelta(data: Partial<Item>): Promise<string>;
|
|
68
|
+
prepareDelta(data: Partial<Item>): Promise<string | null>;
|
|
69
69
|
}
|
|
70
70
|
export {};
|
package/dist/services/payload.js
CHANGED
package/dist/services/users.js
CHANGED
|
@@ -140,8 +140,11 @@ class UsersService extends items_1.ItemsService {
|
|
|
140
140
|
* Update many users by primary key
|
|
141
141
|
*/
|
|
142
142
|
async updateMany(keys, data, opts) {
|
|
143
|
+
var _a, _b;
|
|
143
144
|
if (data.role) {
|
|
144
|
-
|
|
145
|
+
// data.role will be an object with id with GraphQL mutations
|
|
146
|
+
const roleId = (_b = (_a = data.role) === null || _a === void 0 ? void 0 : _a.id) !== null && _b !== void 0 ? _b : data.role;
|
|
147
|
+
const newRole = await this.knex.select('admin_access').from('directus_roles').where('id', roleId).first();
|
|
145
148
|
if (!(newRole === null || newRole === void 0 ? void 0 : newRole.admin_access)) {
|
|
146
149
|
await this.checkRemainingAdminExistence(keys);
|
|
147
150
|
}
|
|
@@ -228,7 +228,7 @@ function applyFilter(knex, schema, rootQuery, rootFilter, collection, subQuery =
|
|
|
228
228
|
subQueryKnex
|
|
229
229
|
.select({ [field]: column })
|
|
230
230
|
.from(collection)
|
|
231
|
-
.whereNotNull(
|
|
231
|
+
.whereNotNull(column);
|
|
232
232
|
applyQuery(knex, relation.collection, subQueryKnex, { filter }, schema, true);
|
|
233
233
|
};
|
|
234
234
|
if (((_a = Object.keys(value)) === null || _a === void 0 ? void 0 : _a[0]) === '_none') {
|
|
@@ -75,9 +75,17 @@ async function getASTFromQuery(collection, query, schema, options) {
|
|
|
75
75
|
const relationalStructure = {};
|
|
76
76
|
for (const fieldKey of fields) {
|
|
77
77
|
let name = fieldKey;
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
name
|
|
78
|
+
if (query.alias) {
|
|
79
|
+
// check for field alias (is is one of the key)
|
|
80
|
+
if (name in query.alias) {
|
|
81
|
+
name = query.alias[fieldKey];
|
|
82
|
+
}
|
|
83
|
+
// check for junction alias (it is one of the value instead of the key)
|
|
84
|
+
if (Object.values(query.alias).includes(name)) {
|
|
85
|
+
const aliasKey = Object.keys(query.alias).find((key) => { var _a; return ((_a = query.alias) === null || _a === void 0 ? void 0 : _a[key]) === name; });
|
|
86
|
+
if (aliasKey && fieldKey !== aliasKey)
|
|
87
|
+
name = aliasKey;
|
|
88
|
+
}
|
|
81
89
|
}
|
|
82
90
|
const isRelational = name.includes('.') ||
|
|
83
91
|
// We'll always treat top level o2m fields as a related item. This is an alias field, otherwise it won't return
|
|
@@ -162,6 +170,10 @@ async function getASTFromQuery(collection, query, schema, options) {
|
|
|
162
170
|
if (permissions && permissions.some((permission) => permission.collection === relatedCollection) === false) {
|
|
163
171
|
continue;
|
|
164
172
|
}
|
|
173
|
+
// update query alias for children parseFields
|
|
174
|
+
const deepAlias = (_a = getDeepQuery((deep === null || deep === void 0 ? void 0 : deep[fieldKey]) || {})) === null || _a === void 0 ? void 0 : _a.alias;
|
|
175
|
+
if (!(0, lodash_1.isEmpty)(deepAlias))
|
|
176
|
+
query.alias = deepAlias;
|
|
165
177
|
child = {
|
|
166
178
|
type: relationType,
|
|
167
179
|
name: relatedCollection,
|
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");
|
|
@@ -113,6 +114,8 @@ async function getDatabaseSchema(database, schemaInspector) {
|
|
|
113
114
|
const existing = result.collections[field.collection].fields[field.field];
|
|
114
115
|
const column = schemaOverview[field.collection].columns[field.field];
|
|
115
116
|
const special = field.special ? (0, utils_1.toArray)(field.special) : [];
|
|
117
|
+
if (constants_1.ALIAS_TYPES.some((type) => special.includes(type)) === false && !existing)
|
|
118
|
+
continue;
|
|
116
119
|
const type = (existing && (0, get_local_type_1.default)(column, { special })) || 'alias';
|
|
117
120
|
let validation = (_a = field.validation) !== null && _a !== void 0 ? _a : null;
|
|
118
121
|
if (validation && typeof validation === 'string')
|
|
@@ -10,7 +10,7 @@ const lodash_1 = require("lodash");
|
|
|
10
10
|
* @returns Reduced schema
|
|
11
11
|
*/
|
|
12
12
|
function reduceSchema(schema, permissions, actions = ['create', 'read', 'update', 'delete']) {
|
|
13
|
-
var _a, _b, _c;
|
|
13
|
+
var _a, _b, _c, _d, _e;
|
|
14
14
|
const reduced = {
|
|
15
15
|
collections: {},
|
|
16
16
|
relations: [],
|
|
@@ -25,19 +25,27 @@ 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 relatedCollection = ((_d = schema.relations.find((relation) => relation.collection === collectionName && relation.field === fieldName)) === null || _d === void 0 ? void 0 : _d.related_collection) ||
|
|
38
|
+
((_e = schema.relations.find((relation) => { var _a; return relation.related_collection === collectionName && ((_a = relation.meta) === null || _a === void 0 ? void 0 : _a.one_field) === fieldName; })) === null || _e === void 0 ? void 0 : _e.collection);
|
|
39
|
+
if (relatedCollection &&
|
|
40
|
+
!(permissions === null || permissions === void 0 ? void 0 : permissions.some((permission) => permission.collection === relatedCollection && actions.includes(permission.action)))) {
|
|
41
|
+
continue;
|
|
35
42
|
}
|
|
36
|
-
|
|
37
|
-
...collection,
|
|
38
|
-
fields,
|
|
39
|
-
};
|
|
43
|
+
fields[fieldName] = field;
|
|
40
44
|
}
|
|
45
|
+
reduced.collections[collectionName] = {
|
|
46
|
+
...collection,
|
|
47
|
+
fields,
|
|
48
|
+
};
|
|
41
49
|
}
|
|
42
50
|
reduced.relations = schema.relations.filter((relation) => {
|
|
43
51
|
var _a, _b, _c;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "directus",
|
|
3
|
-
"version": "9.9.
|
|
3
|
+
"version": "9.9.1",
|
|
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.9.
|
|
82
|
-
"@directus/drive": "9.9.
|
|
83
|
-
"@directus/drive-azure": "9.9.
|
|
84
|
-
"@directus/drive-gcs": "9.9.
|
|
85
|
-
"@directus/drive-s3": "9.9.
|
|
86
|
-
"@directus/extensions-sdk": "9.9.
|
|
87
|
-
"@directus/format-title": "9.9.
|
|
88
|
-
"@directus/schema": "9.9.
|
|
89
|
-
"@directus/shared": "9.9.
|
|
90
|
-
"@directus/specs": "9.9.
|
|
81
|
+
"@directus/app": "9.9.1",
|
|
82
|
+
"@directus/drive": "9.9.1",
|
|
83
|
+
"@directus/drive-azure": "9.9.1",
|
|
84
|
+
"@directus/drive-gcs": "9.9.1",
|
|
85
|
+
"@directus/drive-s3": "9.9.1",
|
|
86
|
+
"@directus/extensions-sdk": "9.9.1",
|
|
87
|
+
"@directus/format-title": "9.9.1",
|
|
88
|
+
"@directus/schema": "9.9.1",
|
|
89
|
+
"@directus/shared": "9.9.1",
|
|
90
|
+
"@directus/specs": "9.9.1",
|
|
91
91
|
"@godaddy/terminus": "^4.9.0",
|
|
92
92
|
"@rollup/plugin-alias": "^3.1.9",
|
|
93
93
|
"@rollup/plugin-virtual": "^2.0.3",
|
|
@@ -173,7 +173,7 @@
|
|
|
173
173
|
"sqlite3": "^5.0.2",
|
|
174
174
|
"tedious": "^13.0.0"
|
|
175
175
|
},
|
|
176
|
-
"gitHead": "
|
|
176
|
+
"gitHead": "ed780aceba707c714e0b0aa01a953d141a5c800e",
|
|
177
177
|
"devDependencies": {
|
|
178
178
|
"@types/async": "3.2.10",
|
|
179
179
|
"@types/body-parser": "1.19.2",
|