directus 9.8.0 → 9.10.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/__mocks__/cache.d.ts +5 -0
- package/dist/__mocks__/cache.js +7 -0
- package/dist/app.js +3 -0
- package/dist/auth/drivers/ldap.js +10 -11
- package/dist/auth/drivers/oauth2.js +11 -6
- package/dist/auth/drivers/openid.js +9 -6
- package/dist/cli/commands/schema/apply.js +9 -3
- package/dist/controllers/assets.js +5 -0
- package/dist/controllers/files.d.ts +2 -0
- package/dist/controllers/files.js +13 -5
- package/dist/database/helpers/date/dialects/mssql.d.ts +4 -0
- package/dist/database/helpers/date/dialects/mssql.js +12 -0
- package/dist/database/helpers/date/dialects/mysql.d.ts +5 -0
- package/dist/database/helpers/date/dialects/mysql.js +16 -0
- package/dist/database/helpers/date/dialects/oracle.d.ts +4 -0
- package/dist/database/helpers/date/dialects/oracle.js +15 -0
- package/dist/database/helpers/date/dialects/sqlite.d.ts +1 -0
- package/dist/database/helpers/date/dialects/sqlite.js +8 -0
- package/dist/database/helpers/date/index.d.ts +3 -3
- package/dist/database/helpers/date/index.js +6 -6
- package/dist/database/helpers/date/types.d.ts +3 -0
- package/dist/database/helpers/date/types.js +10 -0
- package/dist/database/helpers/fn/dialects/postgres.js +5 -1
- package/dist/database/helpers/index.d.ts +1 -1
- package/dist/database/migrations/20220402A-remove-default-value-panel-icon.d.ts +3 -0
- package/dist/database/migrations/20220402A-remove-default-value-panel-icon.js +22 -0
- package/dist/database/run-ast.js +3 -3
- package/dist/database/system-data/fields/collections.yaml +1 -1
- package/dist/database/system-data/fields/settings.yaml +0 -1
- package/dist/database/system-data/fields/users.yaml +3 -0
- package/dist/env.js +9 -3
- package/dist/exceptions/index.d.ts +1 -0
- package/dist/exceptions/index.js +1 -0
- package/dist/exceptions/token-expired.d.ts +4 -0
- package/dist/exceptions/token-expired.js +10 -0
- package/dist/middleware/cache.js +10 -0
- package/dist/services/authorization.js +72 -30
- package/dist/services/collections.d.ts +2 -0
- package/dist/services/collections.js +10 -0
- package/dist/services/fields.js +26 -1
- package/dist/services/files.d.ts +5 -1
- package/dist/services/files.js +59 -40
- package/dist/services/graphql.d.ts +2 -3
- package/dist/services/graphql.js +65 -11
- package/dist/services/import-export.js +2 -0
- package/dist/services/items.js +12 -5
- package/dist/services/payload.d.ts +2 -1
- package/dist/services/payload.js +22 -17
- package/dist/services/specifications.js +1 -3
- package/dist/services/users.js +4 -1
- package/dist/types/files.d.ts +8 -0
- package/dist/utils/apply-query.d.ts +2 -1
- package/dist/utils/apply-query.js +134 -156
- package/dist/utils/apply-snapshot.d.ts +3 -1
- package/dist/utils/apply-snapshot.js +34 -5
- package/dist/utils/get-ast-from-query.js +15 -3
- package/dist/utils/get-column-path.d.ts +16 -0
- package/dist/utils/get-column-path.js +46 -0
- package/dist/utils/get-graphql-type.js +1 -0
- package/dist/utils/get-local-type.js +5 -0
- 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 +3 -0
- package/dist/utils/jwt.js +1 -1
- package/dist/utils/merge-permissions-for-share.js +1 -1
- package/dist/utils/reduce-schema.js +18 -11
- package/dist/utils/validate-query.js +19 -15
- package/example.env +4 -0
- package/package.json +18 -19
package/dist/services/graphql.js
CHANGED
|
@@ -5,20 +5,22 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.GraphQLService = exports.GraphQLDate = exports.GraphQLGeoJSON = void 0;
|
|
7
7
|
const argon2_1 = __importDefault(require("argon2"));
|
|
8
|
-
const validate_query_1 = require("../utils/validate-query");
|
|
9
8
|
const graphql_1 = require("graphql");
|
|
10
9
|
const graphql_compose_1 = require("graphql-compose");
|
|
11
10
|
const lodash_1 = require("lodash");
|
|
12
11
|
const ms_1 = __importDefault(require("ms"));
|
|
13
12
|
const cache_1 = require("../cache");
|
|
13
|
+
const constants_1 = require("../constants");
|
|
14
14
|
const database_1 = __importDefault(require("../database"));
|
|
15
15
|
const env_1 = __importDefault(require("../env"));
|
|
16
16
|
const exceptions_1 = require("../exceptions");
|
|
17
17
|
const extensions_1 = require("../extensions");
|
|
18
18
|
const types_1 = require("../types");
|
|
19
|
+
const generate_hash_1 = require("../utils/generate-hash");
|
|
19
20
|
const get_graphql_type_1 = require("../utils/get-graphql-type");
|
|
20
21
|
const reduce_schema_1 = require("../utils/reduce-schema");
|
|
21
22
|
const sanitize_query_1 = require("../utils/sanitize-query");
|
|
23
|
+
const validate_query_1 = require("../utils/validate-query");
|
|
22
24
|
const activity_1 = require("./activity");
|
|
23
25
|
const authentication_1 = require("./authentication");
|
|
24
26
|
const collections_1 = require("./collections");
|
|
@@ -26,9 +28,9 @@ const fields_1 = require("./fields");
|
|
|
26
28
|
const files_1 = require("./files");
|
|
27
29
|
const folders_1 = require("./folders");
|
|
28
30
|
const items_1 = require("./items");
|
|
31
|
+
const notifications_1 = require("./notifications");
|
|
29
32
|
const permissions_1 = require("./permissions");
|
|
30
33
|
const presets_1 = require("./presets");
|
|
31
|
-
const notifications_1 = require("./notifications");
|
|
32
34
|
const relations_1 = require("./relations");
|
|
33
35
|
const revisions_1 = require("./revisions");
|
|
34
36
|
const roles_1 = require("./roles");
|
|
@@ -40,8 +42,6 @@ const tfa_1 = require("./tfa");
|
|
|
40
42
|
const users_1 = require("./users");
|
|
41
43
|
const utils_1 = require("./utils");
|
|
42
44
|
const webhooks_1 = require("./webhooks");
|
|
43
|
-
const generate_hash_1 = require("../utils/generate-hash");
|
|
44
|
-
const constants_1 = require("../constants");
|
|
45
45
|
const GraphQLVoid = new graphql_1.GraphQLScalarType({
|
|
46
46
|
name: 'Void',
|
|
47
47
|
description: 'Represents NULL values',
|
|
@@ -89,7 +89,16 @@ class GraphQLService {
|
|
|
89
89
|
async execute({ document, variables, operationName, contextValue, }) {
|
|
90
90
|
var _a;
|
|
91
91
|
const schema = this.getSchema();
|
|
92
|
-
const validationErrors = (0, graphql_1.validate)(schema, document,
|
|
92
|
+
const validationErrors = (0, graphql_1.validate)(schema, document, [
|
|
93
|
+
...graphql_1.specifiedRules,
|
|
94
|
+
(context) => ({
|
|
95
|
+
Field(node) {
|
|
96
|
+
if (env_1.default.GRAPHQL_INTROSPECTION === false && (node.name.value === '__schema' || node.name.value === '__type')) {
|
|
97
|
+
context.reportError(new graphql_1.GraphQLError('GraphQL introspection is not allowed. The query contained __schema or __type.', [node]));
|
|
98
|
+
}
|
|
99
|
+
},
|
|
100
|
+
}),
|
|
101
|
+
]);
|
|
93
102
|
if (validationErrors.length > 0) {
|
|
94
103
|
throw new exceptions_1.GraphQLValidationException({ graphqlErrors: validationErrors });
|
|
95
104
|
}
|
|
@@ -235,6 +244,14 @@ class GraphQLService {
|
|
|
235
244
|
function getTypes(action) {
|
|
236
245
|
var _a, _b, _c, _d, _e;
|
|
237
246
|
const CollectionTypes = {};
|
|
247
|
+
const CountFunctions = schemaComposer.createObjectTC({
|
|
248
|
+
name: 'count_functions',
|
|
249
|
+
fields: {
|
|
250
|
+
count: {
|
|
251
|
+
type: graphql_1.GraphQLInt,
|
|
252
|
+
},
|
|
253
|
+
},
|
|
254
|
+
});
|
|
238
255
|
const DateFunctions = schemaComposer.createObjectTC({
|
|
239
256
|
name: 'date_functions',
|
|
240
257
|
fields: {
|
|
@@ -328,6 +345,15 @@ class GraphQLService {
|
|
|
328
345
|
},
|
|
329
346
|
};
|
|
330
347
|
}
|
|
348
|
+
if (field.type === 'json' || field.type === 'alias') {
|
|
349
|
+
acc[`${field.field}_func`] = {
|
|
350
|
+
type: CountFunctions,
|
|
351
|
+
resolve: (obj) => {
|
|
352
|
+
const funcFields = Object.keys(CountFunctions.getFields()).map((key) => `${field.field}_${key}`);
|
|
353
|
+
return (0, lodash_1.mapKeys)((0, lodash_1.pick)(obj, funcFields), (_value, key) => key.substring(field.field.length + 1));
|
|
354
|
+
},
|
|
355
|
+
};
|
|
356
|
+
}
|
|
331
357
|
return acc;
|
|
332
358
|
}, {}),
|
|
333
359
|
});
|
|
@@ -550,6 +576,14 @@ class GraphQLService {
|
|
|
550
576
|
},
|
|
551
577
|
},
|
|
552
578
|
});
|
|
579
|
+
const CountFunctionFilterOperators = schemaComposer.createInputTC({
|
|
580
|
+
name: 'count_function_filter_operators',
|
|
581
|
+
fields: {
|
|
582
|
+
count: {
|
|
583
|
+
type: NumberFilterOperators,
|
|
584
|
+
},
|
|
585
|
+
},
|
|
586
|
+
});
|
|
553
587
|
const DateFunctionFilterOperators = schemaComposer.createInputTC({
|
|
554
588
|
name: 'date_function_filter_operators',
|
|
555
589
|
fields: {
|
|
@@ -634,6 +668,11 @@ class GraphQLService {
|
|
|
634
668
|
type: DateTimeFunctionFilterOperators,
|
|
635
669
|
};
|
|
636
670
|
}
|
|
671
|
+
if (field.type === 'json' || field.type === 'alias') {
|
|
672
|
+
acc[`${field.field}_func`] = {
|
|
673
|
+
type: CountFunctionFilterOperators,
|
|
674
|
+
};
|
|
675
|
+
}
|
|
637
676
|
return acc;
|
|
638
677
|
}, {}),
|
|
639
678
|
});
|
|
@@ -1145,6 +1184,7 @@ class GraphQLService {
|
|
|
1145
1184
|
continue;
|
|
1146
1185
|
selection = selection;
|
|
1147
1186
|
let current;
|
|
1187
|
+
let currentAlias = null;
|
|
1148
1188
|
// Union type (Many-to-Any)
|
|
1149
1189
|
if (selection.kind === 'InlineFragment') {
|
|
1150
1190
|
if (selection.typeCondition.name.value.startsWith('__'))
|
|
@@ -1157,8 +1197,20 @@ class GraphQLService {
|
|
|
1157
1197
|
if (selection.name.value.startsWith('__'))
|
|
1158
1198
|
continue;
|
|
1159
1199
|
current = selection.name.value;
|
|
1200
|
+
if (selection.alias) {
|
|
1201
|
+
currentAlias = selection.alias.value;
|
|
1202
|
+
}
|
|
1160
1203
|
if (parent) {
|
|
1161
1204
|
current = `${parent}.${current}`;
|
|
1205
|
+
if (currentAlias) {
|
|
1206
|
+
currentAlias = `${parent}.${currentAlias}`;
|
|
1207
|
+
// add nested aliases into deep query
|
|
1208
|
+
if (selection.selectionSet) {
|
|
1209
|
+
if (!query.deep)
|
|
1210
|
+
query.deep = {};
|
|
1211
|
+
(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 } }));
|
|
1212
|
+
}
|
|
1213
|
+
}
|
|
1162
1214
|
}
|
|
1163
1215
|
}
|
|
1164
1216
|
if (selection.selectionSet) {
|
|
@@ -1173,7 +1225,7 @@ class GraphQLService {
|
|
|
1173
1225
|
}
|
|
1174
1226
|
}
|
|
1175
1227
|
else {
|
|
1176
|
-
children = parseFields(selection.selectionSet.selections, current);
|
|
1228
|
+
children = parseFields(selection.selectionSet.selections, currentAlias !== null && currentAlias !== void 0 ? currentAlias : current);
|
|
1177
1229
|
}
|
|
1178
1230
|
fields.push(...children);
|
|
1179
1231
|
}
|
|
@@ -1244,8 +1296,10 @@ class GraphQLService {
|
|
|
1244
1296
|
*/
|
|
1245
1297
|
formatError(error) {
|
|
1246
1298
|
if (Array.isArray(error)) {
|
|
1299
|
+
error[0].extensions.code = error[0].code;
|
|
1247
1300
|
return new graphql_1.GraphQLError(error[0].message, undefined, undefined, undefined, undefined, error[0]);
|
|
1248
1301
|
}
|
|
1302
|
+
error.extensions.code = error.code;
|
|
1249
1303
|
return new graphql_1.GraphQLError(error.message, undefined, undefined, undefined, undefined, error);
|
|
1250
1304
|
}
|
|
1251
1305
|
/**
|
|
@@ -1308,7 +1362,7 @@ class GraphQLService {
|
|
|
1308
1362
|
return result;
|
|
1309
1363
|
}
|
|
1310
1364
|
injectSystemResolvers(schemaComposer, { CreateCollectionTypes, ReadCollectionTypes, UpdateCollectionTypes, DeleteCollectionTypes, }, schema) {
|
|
1311
|
-
var _a, _b, _c, _d, _e;
|
|
1365
|
+
var _a, _b, _c, _d, _e, _f;
|
|
1312
1366
|
const AuthTokens = schemaComposer.createObjectTC({
|
|
1313
1367
|
name: 'auth_tokens',
|
|
1314
1368
|
fields: {
|
|
@@ -2131,7 +2185,7 @@ class GraphQLService {
|
|
|
2131
2185
|
},
|
|
2132
2186
|
});
|
|
2133
2187
|
}
|
|
2134
|
-
if ('directus_users' in schema.update.collections) {
|
|
2188
|
+
if ('directus_users' in schema.update.collections && ((_c = this.accountability) === null || _c === void 0 ? void 0 : _c.user)) {
|
|
2135
2189
|
schemaComposer.Mutation.addFields({
|
|
2136
2190
|
update_users_me: {
|
|
2137
2191
|
type: ReadCollectionTypes['directus_users'],
|
|
@@ -2160,7 +2214,7 @@ class GraphQLService {
|
|
|
2160
2214
|
if ('directus_activity' in schema.create.collections) {
|
|
2161
2215
|
schemaComposer.Mutation.addFields({
|
|
2162
2216
|
create_comment: {
|
|
2163
|
-
type: (
|
|
2217
|
+
type: (_d = ReadCollectionTypes['directus_activity']) !== null && _d !== void 0 ? _d : graphql_1.GraphQLBoolean,
|
|
2164
2218
|
args: {
|
|
2165
2219
|
collection: (0, graphql_1.GraphQLNonNull)(graphql_1.GraphQLString),
|
|
2166
2220
|
item: (0, graphql_1.GraphQLNonNull)(graphql_1.GraphQLID),
|
|
@@ -2192,7 +2246,7 @@ class GraphQLService {
|
|
|
2192
2246
|
if ('directus_activity' in schema.update.collections) {
|
|
2193
2247
|
schemaComposer.Mutation.addFields({
|
|
2194
2248
|
update_comment: {
|
|
2195
|
-
type: (
|
|
2249
|
+
type: (_e = ReadCollectionTypes['directus_activity']) !== null && _e !== void 0 ? _e : graphql_1.GraphQLBoolean,
|
|
2196
2250
|
args: {
|
|
2197
2251
|
id: (0, graphql_1.GraphQLNonNull)(graphql_1.GraphQLID),
|
|
2198
2252
|
comment: (0, graphql_1.GraphQLNonNull)(graphql_1.GraphQLString),
|
|
@@ -2235,7 +2289,7 @@ class GraphQLService {
|
|
|
2235
2289
|
if ('directus_files' in schema.create.collections) {
|
|
2236
2290
|
schemaComposer.Mutation.addFields({
|
|
2237
2291
|
import_file: {
|
|
2238
|
-
type: (
|
|
2292
|
+
type: (_f = ReadCollectionTypes['directus_files']) !== null && _f !== void 0 ? _f : graphql_1.GraphQLBoolean,
|
|
2239
2293
|
args: {
|
|
2240
2294
|
url: (0, graphql_1.GraphQLNonNull)(graphql_1.GraphQLString),
|
|
2241
2295
|
data: (0, graphql_compose_1.toInputObjectType)(CreateCollectionTypes['directus_files']).setTypeName('create_directus_files_input'),
|
|
@@ -22,6 +22,7 @@ const get_date_formatted_1 = require("../utils/get-date-formatted");
|
|
|
22
22
|
const utils_1 = require("@directus/shared/utils");
|
|
23
23
|
const notifications_1 = require("./notifications");
|
|
24
24
|
const logger_1 = __importDefault(require("../logger"));
|
|
25
|
+
const strip_bom_stream_1 = __importDefault(require("strip-bom-stream"));
|
|
25
26
|
class ImportService {
|
|
26
27
|
constructor(options) {
|
|
27
28
|
this.knex = options.knex || (0, database_1.default)();
|
|
@@ -91,6 +92,7 @@ class ImportService {
|
|
|
91
92
|
});
|
|
92
93
|
return new Promise((resolve, reject) => {
|
|
93
94
|
stream
|
|
95
|
+
.pipe((0, strip_bom_stream_1.default)())
|
|
94
96
|
.pipe((0, csv_parser_1.default)())
|
|
95
97
|
.on('data', (value) => {
|
|
96
98
|
const obj = (0, lodash_1.transform)(value, (result, value, key) => {
|
package/dist/services/items.js
CHANGED
|
@@ -90,8 +90,13 @@ class ItemsService {
|
|
|
90
90
|
// In case of manual string / UUID primary keys, the PK already exists in the object we're saving.
|
|
91
91
|
let primaryKey = payloadWithTypeCasting[primaryKeyField];
|
|
92
92
|
try {
|
|
93
|
-
const result = await trx
|
|
94
|
-
|
|
93
|
+
const result = await trx
|
|
94
|
+
.insert(payloadWithoutAliases)
|
|
95
|
+
.into(this.collection)
|
|
96
|
+
.returning(primaryKeyField)
|
|
97
|
+
.then((result) => result[0]);
|
|
98
|
+
const returnedKey = typeof result === 'object' ? result[primaryKeyField] : result;
|
|
99
|
+
primaryKey = primaryKey !== null && primaryKey !== void 0 ? primaryKey : returnedKey;
|
|
95
100
|
}
|
|
96
101
|
catch (err) {
|
|
97
102
|
throw await (0, translate_1.translateDatabaseError)(err);
|
|
@@ -354,13 +359,14 @@ class ItemsService {
|
|
|
354
359
|
knex: trx,
|
|
355
360
|
schema: this.schema,
|
|
356
361
|
});
|
|
357
|
-
const
|
|
362
|
+
const revisions = (await Promise.all(activity.map(async (activity, index) => ({
|
|
358
363
|
activity: activity,
|
|
359
364
|
collection: this.collection,
|
|
360
365
|
item: keys[index],
|
|
361
366
|
data: snapshots && Array.isArray(snapshots) ? JSON.stringify(snapshots[index]) : JSON.stringify(snapshots),
|
|
362
367
|
delta: await payloadService.prepareDelta(payloadWithTypeCasting),
|
|
363
|
-
}))));
|
|
368
|
+
})))).filter((revision) => revision.delta);
|
|
369
|
+
const revisionIDs = await revisionsService.createMany(revisions);
|
|
364
370
|
for (let i = 0; i < revisionIDs.length; i++) {
|
|
365
371
|
const revisionID = revisionIDs[i];
|
|
366
372
|
if (opts === null || opts === void 0 ? void 0 : opts.onRevisionCreate) {
|
|
@@ -529,7 +535,8 @@ class ItemsService {
|
|
|
529
535
|
defaults[name] = null;
|
|
530
536
|
continue;
|
|
531
537
|
}
|
|
532
|
-
|
|
538
|
+
if (field.defaultValue)
|
|
539
|
+
defaults[name] = field.defaultValue;
|
|
533
540
|
}
|
|
534
541
|
return defaults;
|
|
535
542
|
}
|
|
@@ -10,6 +10,7 @@ declare type Transformers = {
|
|
|
10
10
|
payload: Partial<Item>;
|
|
11
11
|
accountability: Accountability | null;
|
|
12
12
|
specials: string[];
|
|
13
|
+
helpers: Helpers;
|
|
13
14
|
}) => Promise<any>;
|
|
14
15
|
};
|
|
15
16
|
/**
|
|
@@ -64,6 +65,6 @@ export declare class PayloadService {
|
|
|
64
65
|
* Transforms the input partial payload to match the output structure, to have consistency
|
|
65
66
|
* between delta and data
|
|
66
67
|
*/
|
|
67
|
-
prepareDelta(data: Partial<Item>): Promise<string>;
|
|
68
|
+
prepareDelta(data: Partial<Item>): Promise<string | null>;
|
|
68
69
|
}
|
|
69
70
|
export {};
|
package/dist/services/payload.js
CHANGED
|
@@ -89,14 +89,14 @@ class PayloadService {
|
|
|
89
89
|
return (accountability === null || accountability === void 0 ? void 0 : accountability.role) || null;
|
|
90
90
|
return value;
|
|
91
91
|
},
|
|
92
|
-
async 'date-created'({ action, value }) {
|
|
92
|
+
async 'date-created'({ action, value, helpers }) {
|
|
93
93
|
if (action === 'create')
|
|
94
|
-
return new Date();
|
|
94
|
+
return new Date(helpers.date.writeTimestamp(new Date().toISOString()));
|
|
95
95
|
return value;
|
|
96
96
|
},
|
|
97
|
-
async 'date-updated'({ action, value }) {
|
|
97
|
+
async 'date-updated'({ action, value, helpers }) {
|
|
98
98
|
if (action === 'update')
|
|
99
|
-
return new Date();
|
|
99
|
+
return new Date(helpers.date.writeTimestamp(new Date().toISOString()));
|
|
100
100
|
return value;
|
|
101
101
|
},
|
|
102
102
|
async 'cast-csv'({ action, value }) {
|
|
@@ -181,6 +181,7 @@ class PayloadService {
|
|
|
181
181
|
payload,
|
|
182
182
|
accountability,
|
|
183
183
|
specials: fieldSpecials,
|
|
184
|
+
helpers: this.helpers,
|
|
184
185
|
});
|
|
185
186
|
}
|
|
186
187
|
}
|
|
@@ -233,21 +234,23 @@ class PayloadService {
|
|
|
233
234
|
value = new Date(value);
|
|
234
235
|
}
|
|
235
236
|
if (dateColumn.type === 'timestamp') {
|
|
236
|
-
const newValue = value.toISOString();
|
|
237
|
+
const newValue = this.helpers.date.readTimestampString(value.toISOString());
|
|
237
238
|
payload[name] = newValue;
|
|
238
239
|
}
|
|
239
240
|
if (dateColumn.type === 'dateTime') {
|
|
240
|
-
const year = String(value.
|
|
241
|
-
const month = String(value.
|
|
242
|
-
const
|
|
243
|
-
const hours = String(value.
|
|
244
|
-
const minutes = String(value.
|
|
245
|
-
const seconds = String(value.
|
|
246
|
-
const newValue = `${year}-${month}-${
|
|
241
|
+
const year = String(value.getFullYear());
|
|
242
|
+
const month = String(value.getMonth() + 1).padStart(2, '0');
|
|
243
|
+
const day = String(value.getDate()).padStart(2, '0');
|
|
244
|
+
const hours = String(value.getHours()).padStart(2, '0');
|
|
245
|
+
const minutes = String(value.getMinutes()).padStart(2, '0');
|
|
246
|
+
const seconds = String(value.getSeconds()).padStart(2, '0');
|
|
247
|
+
const newValue = `${year}-${month}-${day}T${hours}:${minutes}:${seconds}`;
|
|
247
248
|
payload[name] = newValue;
|
|
248
249
|
}
|
|
249
250
|
if (dateColumn.type === 'date') {
|
|
250
|
-
const
|
|
251
|
+
const year = String(value.getFullYear());
|
|
252
|
+
const month = String(value.getMonth() + 1).padStart(2, '0');
|
|
253
|
+
const day = String(value.getDate()).padStart(2, '0');
|
|
251
254
|
// Strip off the time / timezone information from a date-only value
|
|
252
255
|
const newValue = `${year}-${month}-${day}`;
|
|
253
256
|
payload[name] = newValue;
|
|
@@ -258,16 +261,16 @@ class PayloadService {
|
|
|
258
261
|
if (dateColumn.type === 'date') {
|
|
259
262
|
const [date] = value.split('T');
|
|
260
263
|
const [year, month, day] = date.split('-');
|
|
261
|
-
payload[name] = new Date(
|
|
264
|
+
payload[name] = new Date(Number(year), Number(month) - 1, Number(day));
|
|
262
265
|
}
|
|
263
266
|
if (dateColumn.type === 'dateTime') {
|
|
264
267
|
const [date, time] = value.split('T');
|
|
265
268
|
const [year, month, day] = date.split('-');
|
|
266
269
|
const [hours, minutes, seconds] = time.substring(0, 8).split(':');
|
|
267
|
-
payload[name] = new Date(
|
|
270
|
+
payload[name] = new Date(Number(year), Number(month) - 1, Number(day), Number(hours), Number(minutes), Number(seconds));
|
|
268
271
|
}
|
|
269
272
|
if (dateColumn.type === 'timestamp') {
|
|
270
|
-
const newValue =
|
|
273
|
+
const newValue = this.helpers.date.writeTimestamp(value);
|
|
271
274
|
payload[name] = newValue;
|
|
272
275
|
}
|
|
273
276
|
}
|
|
@@ -315,7 +318,7 @@ class PayloadService {
|
|
|
315
318
|
}
|
|
316
319
|
const allowedCollections = relation.meta.one_allowed_collections;
|
|
317
320
|
if (allowedCollections.includes(relatedCollection) === false) {
|
|
318
|
-
throw new exceptions_1.InvalidPayloadException(`"${relation.collection}.${relation.field}" can't be linked to collection "${relatedCollection}`);
|
|
321
|
+
throw new exceptions_1.InvalidPayloadException(`"${relation.collection}.${relation.field}" can't be linked to collection "${relatedCollection}"`);
|
|
319
322
|
}
|
|
320
323
|
const itemsService = new items_1.ItemsService(relatedCollection, {
|
|
321
324
|
accountability: this.accountability,
|
|
@@ -575,6 +578,8 @@ class PayloadService {
|
|
|
575
578
|
}
|
|
576
579
|
}
|
|
577
580
|
payload = await this.processValues('read', payload);
|
|
581
|
+
if (Object.keys(payload).length === 0)
|
|
582
|
+
return null;
|
|
578
583
|
return JSON.stringify(payload);
|
|
579
584
|
}
|
|
580
585
|
}
|
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
|
}
|
package/dist/types/files.d.ts
CHANGED
|
@@ -19,3 +19,11 @@ export declare type File = {
|
|
|
19
19
|
tags: string | null;
|
|
20
20
|
metadata: Record<string, any> | null;
|
|
21
21
|
};
|
|
22
|
+
export declare type Metadata = {
|
|
23
|
+
height?: number | undefined;
|
|
24
|
+
width?: number | undefined;
|
|
25
|
+
description?: string | undefined;
|
|
26
|
+
title?: string | undefined;
|
|
27
|
+
tags?: any | undefined;
|
|
28
|
+
metadata?: any | undefined;
|
|
29
|
+
};
|
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
import { Knex } from 'knex';
|
|
2
1
|
import { Aggregate, Filter, Query, SchemaOverview } from '@directus/shared/types';
|
|
2
|
+
import { Knex } from 'knex';
|
|
3
3
|
/**
|
|
4
4
|
* Apply the Query to a given Knex query builder instance
|
|
5
5
|
*/
|
|
6
6
|
export default function applyQuery(knex: Knex, collection: string, dbQuery: Knex.QueryBuilder, query: Query, schema: SchemaOverview, subQuery?: boolean): Knex.QueryBuilder;
|
|
7
|
+
export declare function applySort(knex: Knex, schema: SchemaOverview, rootQuery: Knex.QueryBuilder, rootSort: string[], collection: string, subQuery?: boolean): void;
|
|
7
8
|
export declare function applyFilter(knex: Knex, schema: SchemaOverview, rootQuery: Knex.QueryBuilder, rootFilter: Filter, collection: string, subQuery?: boolean): Knex.QueryBuilder<any, any>;
|
|
8
9
|
export declare function applySearch(schema: SchemaOverview, dbQuery: Knex.QueryBuilder, searchQuery: string, collection: string): Promise<void>;
|
|
9
10
|
export declare function applyAggregate(dbQuery: Knex.QueryBuilder, aggregate: Aggregate, collection: string): void;
|