directus 9.10.0 → 9.12.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 +8 -1
- 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/cli/utils/create-env/env-stub.liquid +266 -9
- package/dist/controllers/activity.js +1 -1
- package/dist/controllers/assets.js +8 -9
- package/dist/controllers/flows.d.ts +2 -0
- package/dist/controllers/flows.js +157 -0
- package/dist/controllers/folders.js +1 -1
- package/dist/controllers/notifications.js +1 -1
- package/dist/controllers/operations.d.ts +2 -0
- package/dist/controllers/operations.js +138 -0
- package/dist/database/helpers/date/dialects/sqlite.js +6 -2
- package/dist/database/index.js +15 -19
- 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/migrations/20220429A-add-flows.d.ts +3 -0
- package/dist/database/migrations/20220429A-add-flows.js +83 -0
- package/dist/database/migrations/20220429B-add-color-to-insights-icon.d.ts +3 -0
- package/dist/database/migrations/20220429B-add-color-to-insights-icon.js +15 -0
- package/dist/database/migrations/20220429C-drop-non-null-from-ip-of-activity.d.ts +3 -0
- package/dist/database/migrations/20220429C-drop-non-null-from-ip-of-activity.js +15 -0
- package/dist/database/migrations/20220429D-drop-non-null-from-sender-of-notifications.d.ts +3 -0
- package/dist/database/migrations/20220429D-drop-non-null-from-sender-of-notifications.js +15 -0
- package/dist/database/run-ast.js +10 -14
- package/dist/database/seeds/05-activity.yaml +0 -1
- package/dist/database/system-data/collections/collections.yaml +4 -0
- package/dist/database/system-data/fields/activity.yaml +3 -0
- package/dist/database/system-data/fields/dashboards.yaml +3 -1
- package/dist/database/system-data/fields/flows.yaml +21 -0
- package/dist/database/system-data/fields/notifications.yaml +3 -1
- package/dist/database/system-data/fields/operations.yaml +19 -0
- package/dist/database/system-data/fields/panels.yaml +3 -1
- package/dist/database/system-data/fields/shares.yaml +3 -1
- package/dist/database/system-data/fields/users.yaml +2 -4
- package/dist/database/system-data/relations/relations.yaml +20 -0
- package/dist/env.d.ts +1 -1
- package/dist/env.js +167 -12
- 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/extensions.d.ts +3 -0
- package/dist/extensions.js +73 -20
- package/dist/flows.d.ts +17 -0
- package/dist/flows.js +310 -0
- package/dist/messenger.d.ts +24 -0
- package/dist/messenger.js +64 -0
- package/dist/middleware/graphql.js +2 -1
- package/dist/operations/condition/index.d.ts +6 -0
- package/dist/operations/condition/index.js +15 -0
- package/dist/operations/item-create/index.d.ts +8 -0
- package/dist/operations/item-create/index.js +40 -0
- package/dist/operations/item-delete/index.d.ts +9 -0
- package/dist/operations/item-delete/index.js +45 -0
- package/dist/operations/item-read/index.d.ts +9 -0
- package/dist/operations/item-read/index.js +45 -0
- package/dist/operations/item-update/index.d.ts +10 -0
- package/dist/operations/item-update/index.js +50 -0
- package/dist/operations/log/index.d.ts +5 -0
- package/dist/operations/log/index.js +14 -0
- package/dist/operations/mail/index.d.ts +7 -0
- package/dist/operations/mail/index.js +16 -0
- package/dist/operations/notification/index.d.ts +8 -0
- package/dist/operations/notification/index.js +39 -0
- package/dist/operations/request/index.d.ts +9 -0
- package/dist/operations/request/index.js +14 -0
- package/dist/operations/sleep/index.d.ts +5 -0
- package/dist/operations/sleep/index.js +9 -0
- package/dist/operations/transform/index.d.ts +5 -0
- package/dist/operations/transform/index.js +10 -0
- package/dist/operations/trigger/index.d.ts +6 -0
- package/dist/operations/trigger/index.js +21 -0
- package/dist/services/activity.d.ts +1 -2
- package/dist/services/activity.js +10 -10
- package/dist/services/assets.js +27 -1
- package/dist/services/authentication.d.ts +2 -2
- package/dist/services/authentication.js +11 -8
- package/dist/services/authorization.js +12 -0
- package/dist/services/fields.js +15 -8
- package/dist/services/flows.d.ts +14 -0
- package/dist/services/flows.js +42 -0
- package/dist/services/graphql.js +56 -33
- package/dist/services/import-export.d.ts +1 -1
- package/dist/services/import-export.js +13 -12
- package/dist/services/index.d.ts +2 -0
- package/dist/services/index.js +2 -0
- package/dist/services/items.d.ts +3 -3
- package/dist/services/items.js +25 -2
- package/dist/services/mail/index.js +2 -1
- package/dist/services/notifications.d.ts +2 -1
- package/dist/services/notifications.js +4 -3
- package/dist/services/operations.d.ts +14 -0
- package/dist/services/operations.js +42 -0
- package/dist/services/payload.d.ts +2 -2
- package/dist/services/payload.js +8 -7
- package/dist/services/users.d.ts +4 -0
- package/dist/services/users.js +20 -0
- package/dist/services/webhooks.d.ts +2 -0
- package/dist/services/webhooks.js +8 -7
- package/dist/types/events.d.ts +18 -0
- package/dist/types/events.js +2 -0
- package/dist/types/index.d.ts +1 -1
- package/dist/types/index.js +1 -1
- package/dist/utils/apply-query.js +31 -4
- package/dist/utils/apply-snapshot.d.ts +3 -3
- package/dist/utils/apply-snapshot.js +64 -49
- package/dist/utils/construct-flow-tree.d.ts +2 -0
- package/dist/utils/construct-flow-tree.js +31 -0
- package/dist/utils/get-accountability-for-role.d.ts +7 -0
- package/dist/utils/get-accountability-for-role.js +36 -0
- package/dist/utils/get-ast-from-query.js +1 -7
- 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-schema.js +2 -1
- package/dist/utils/get-snapshot.js +22 -4
- package/dist/utils/operation-options.d.ts +3 -0
- package/dist/utils/operation-options.js +45 -0
- package/dist/utils/parse-json.d.ts +5 -0
- package/dist/utils/parse-json.js +19 -0
- package/dist/utils/sanitize-query.d.ts +1 -2
- package/dist/utils/sanitize-query.js +6 -5
- package/dist/utils/validate-keys.d.ts +6 -0
- package/dist/utils/validate-keys.js +28 -0
- package/dist/utils/validate-query.js +1 -1
- package/dist/webhooks.d.ts +2 -0
- package/dist/webhooks.js +17 -2
- package/package.json +18 -14
- package/dist/types/activity.d.ts +0 -9
- package/dist/types/activity.js +0 -13
- package/example.env +0 -202
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.FlowsService = void 0;
|
|
4
|
+
const messenger_1 = require("../messenger");
|
|
5
|
+
const items_1 = require("./items");
|
|
6
|
+
class FlowsService extends items_1.ItemsService {
|
|
7
|
+
constructor(options) {
|
|
8
|
+
super('directus_flows', options);
|
|
9
|
+
this.messenger = (0, messenger_1.getMessenger)();
|
|
10
|
+
}
|
|
11
|
+
async createOne(data, opts) {
|
|
12
|
+
const result = await super.createOne(data, opts);
|
|
13
|
+
this.messenger.publish('flows', { type: 'reload' });
|
|
14
|
+
return result;
|
|
15
|
+
}
|
|
16
|
+
async createMany(data, opts) {
|
|
17
|
+
const result = await super.createMany(data, opts);
|
|
18
|
+
this.messenger.publish('flows', { type: 'reload' });
|
|
19
|
+
return result;
|
|
20
|
+
}
|
|
21
|
+
async updateOne(key, data, opts) {
|
|
22
|
+
const result = await super.updateOne(key, data, opts);
|
|
23
|
+
this.messenger.publish('flows', { type: 'reload' });
|
|
24
|
+
return result;
|
|
25
|
+
}
|
|
26
|
+
async updateMany(keys, data, opts) {
|
|
27
|
+
const result = await super.updateMany(keys, data, opts);
|
|
28
|
+
this.messenger.publish('flows', { type: 'reload' });
|
|
29
|
+
return result;
|
|
30
|
+
}
|
|
31
|
+
async deleteOne(key, opts) {
|
|
32
|
+
const result = await super.deleteOne(key, opts);
|
|
33
|
+
this.messenger.publish('flows', { type: 'reload' });
|
|
34
|
+
return result;
|
|
35
|
+
}
|
|
36
|
+
async deleteMany(keys, opts) {
|
|
37
|
+
const result = await super.deleteMany(keys, opts);
|
|
38
|
+
this.messenger.publish('flows', { type: 'reload' });
|
|
39
|
+
return result;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
exports.FlowsService = FlowsService;
|
package/dist/services/graphql.js
CHANGED
|
@@ -4,6 +4,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.GraphQLService = exports.GraphQLDate = exports.GraphQLGeoJSON = void 0;
|
|
7
|
+
const types_1 = require("@directus/shared/types");
|
|
7
8
|
const argon2_1 = __importDefault(require("argon2"));
|
|
8
9
|
const graphql_1 = require("graphql");
|
|
9
10
|
const graphql_compose_1 = require("graphql-compose");
|
|
@@ -15,7 +16,6 @@ const database_1 = __importDefault(require("../database"));
|
|
|
15
16
|
const env_1 = __importDefault(require("../env"));
|
|
16
17
|
const exceptions_1 = require("../exceptions");
|
|
17
18
|
const extensions_1 = require("../extensions");
|
|
18
|
-
const types_1 = require("../types");
|
|
19
19
|
const generate_hash_1 = require("../utils/generate-hash");
|
|
20
20
|
const get_graphql_type_1 = require("../utils/get-graphql-type");
|
|
21
21
|
const reduce_schema_1 = require("../utils/reduce-schema");
|
|
@@ -26,9 +26,11 @@ const authentication_1 = require("./authentication");
|
|
|
26
26
|
const collections_1 = require("./collections");
|
|
27
27
|
const fields_1 = require("./fields");
|
|
28
28
|
const files_1 = require("./files");
|
|
29
|
+
const flows_1 = require("./flows");
|
|
29
30
|
const folders_1 = require("./folders");
|
|
30
31
|
const items_1 = require("./items");
|
|
31
32
|
const notifications_1 = require("./notifications");
|
|
33
|
+
const operations_1 = require("./operations");
|
|
32
34
|
const permissions_1 = require("./permissions");
|
|
33
35
|
const presets_1 = require("./presets");
|
|
34
36
|
const relations_1 = require("./relations");
|
|
@@ -170,16 +172,7 @@ class GraphQLService {
|
|
|
170
172
|
acc[collectionName] = ReadCollectionTypes[collection.collection].getResolver(collection.collection);
|
|
171
173
|
if (this.schema.collections[collection.collection].singleton === false) {
|
|
172
174
|
acc[`${collectionName}_by_id`] = ReadCollectionTypes[collection.collection].getResolver(`${collection.collection}_by_id`);
|
|
173
|
-
|
|
174
|
-
const graphqlType = (0, get_graphql_type_1.getGraphQLType)(field.type);
|
|
175
|
-
if (graphqlType === graphql_1.GraphQLInt || graphqlType === graphql_1.GraphQLFloat) {
|
|
176
|
-
return true;
|
|
177
|
-
}
|
|
178
|
-
return false;
|
|
179
|
-
});
|
|
180
|
-
if (hasAggregate) {
|
|
181
|
-
acc[`${collectionName}_aggregated`] = ReadCollectionTypes[collection.collection].getResolver(`${collection.collection}_aggregated`);
|
|
182
|
-
}
|
|
175
|
+
acc[`${collectionName}_aggregated`] = ReadCollectionTypes[collection.collection].getResolver(`${collection.collection}_aggregated`);
|
|
183
176
|
}
|
|
184
177
|
return acc;
|
|
185
178
|
}, {}));
|
|
@@ -424,7 +417,8 @@ class GraphQLService {
|
|
|
424
417
|
const { CollectionTypes: ReadCollectionTypes } = getTypes('read');
|
|
425
418
|
const ReadableCollectionFilterTypes = {};
|
|
426
419
|
const AggregatedFunctions = {};
|
|
427
|
-
const
|
|
420
|
+
const AggregatedFields = {};
|
|
421
|
+
const AggregateMethods = {};
|
|
428
422
|
const StringFilterOperators = schemaComposer.createInputTC({
|
|
429
423
|
name: 'string_filter_operators',
|
|
430
424
|
fields: {
|
|
@@ -680,7 +674,7 @@ class GraphQLService {
|
|
|
680
674
|
_and: [ReadableCollectionFilterTypes[collection.collection]],
|
|
681
675
|
_or: [ReadableCollectionFilterTypes[collection.collection]],
|
|
682
676
|
});
|
|
683
|
-
|
|
677
|
+
AggregatedFields[collection.collection] = schemaComposer.createObjectTC({
|
|
684
678
|
name: `${collection.collection}_aggregated_fields`,
|
|
685
679
|
fields: Object.values(collection.fields).reduce((acc, field) => {
|
|
686
680
|
const graphqlType = (0, get_graphql_type_1.getGraphQLType)(field.type);
|
|
@@ -698,46 +692,71 @@ class GraphQLService {
|
|
|
698
692
|
return acc;
|
|
699
693
|
}, {}),
|
|
700
694
|
});
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
695
|
+
AggregateMethods[collection.collection] = {
|
|
696
|
+
group: {
|
|
697
|
+
name: 'group',
|
|
698
|
+
type: graphql_compose_1.GraphQLJSON,
|
|
699
|
+
},
|
|
700
|
+
countAll: {
|
|
701
|
+
name: 'countAll',
|
|
702
|
+
type: graphql_1.GraphQLInt,
|
|
703
|
+
},
|
|
704
|
+
count: {
|
|
705
|
+
name: 'count',
|
|
706
|
+
type: schemaComposer.createObjectTC({
|
|
707
|
+
name: `${collection.collection}_aggregated_count`,
|
|
708
|
+
fields: Object.values(collection.fields).reduce((acc, field) => {
|
|
709
|
+
acc[field.field] = {
|
|
710
|
+
type: graphql_1.GraphQLInt,
|
|
711
|
+
description: field.note,
|
|
712
|
+
};
|
|
713
|
+
return acc;
|
|
714
|
+
}, {}),
|
|
715
|
+
}),
|
|
716
|
+
},
|
|
717
|
+
};
|
|
718
|
+
const hasNumericAggregates = Object.values(collection.fields).some((field) => {
|
|
719
|
+
const graphqlType = (0, get_graphql_type_1.getGraphQLType)(field.type);
|
|
720
|
+
if (graphqlType === graphql_1.GraphQLInt || graphqlType === graphql_1.GraphQLFloat) {
|
|
721
|
+
return true;
|
|
722
|
+
}
|
|
723
|
+
return false;
|
|
724
|
+
});
|
|
725
|
+
if (hasNumericAggregates) {
|
|
726
|
+
Object.assign(AggregateMethods[collection.collection], {
|
|
708
727
|
avg: {
|
|
709
728
|
name: 'avg',
|
|
710
|
-
type:
|
|
729
|
+
type: AggregatedFields[collection.collection],
|
|
711
730
|
},
|
|
712
731
|
sum: {
|
|
713
732
|
name: 'sum',
|
|
714
|
-
type:
|
|
715
|
-
},
|
|
716
|
-
count: {
|
|
717
|
-
name: 'count',
|
|
718
|
-
type: AggregatedFilters[collection.collection],
|
|
733
|
+
type: AggregatedFields[collection.collection],
|
|
719
734
|
},
|
|
720
735
|
countDistinct: {
|
|
721
736
|
name: 'countDistinct',
|
|
722
|
-
type:
|
|
737
|
+
type: AggregatedFields[collection.collection],
|
|
723
738
|
},
|
|
724
739
|
avgDistinct: {
|
|
725
740
|
name: 'avgDistinct',
|
|
726
|
-
type:
|
|
741
|
+
type: AggregatedFields[collection.collection],
|
|
727
742
|
},
|
|
728
743
|
sumDistinct: {
|
|
729
744
|
name: 'sumDistinct',
|
|
730
|
-
type:
|
|
745
|
+
type: AggregatedFields[collection.collection],
|
|
731
746
|
},
|
|
732
747
|
min: {
|
|
733
748
|
name: 'min',
|
|
734
|
-
type:
|
|
749
|
+
type: AggregatedFields[collection.collection],
|
|
735
750
|
},
|
|
736
751
|
max: {
|
|
737
752
|
name: 'max',
|
|
738
|
-
type:
|
|
753
|
+
type: AggregatedFields[collection.collection],
|
|
739
754
|
},
|
|
740
|
-
}
|
|
755
|
+
});
|
|
756
|
+
}
|
|
757
|
+
AggregatedFunctions[collection.collection] = schemaComposer.createObjectTC({
|
|
758
|
+
name: `${collection.collection}_aggregated`,
|
|
759
|
+
fields: AggregateMethods[collection.collection],
|
|
741
760
|
});
|
|
742
761
|
ReadCollectionTypes[collection.collection].addResolver({
|
|
743
762
|
name: collection.collection,
|
|
@@ -1237,7 +1256,7 @@ class GraphQLService {
|
|
|
1237
1256
|
if (!query.deep)
|
|
1238
1257
|
query.deep = {};
|
|
1239
1258
|
const args = this.parseArgs(selection.arguments, variableValues);
|
|
1240
|
-
(0, lodash_1.set)(query.deep, current, (0, lodash_1.merge)((0, lodash_1.get)(query.deep, current), (0, lodash_1.mapKeys)((0, sanitize_query_1.sanitizeQuery)(args, this.accountability), (value, key) => `_${key}`)));
|
|
1259
|
+
(0, lodash_1.set)(query.deep, currentAlias !== null && currentAlias !== void 0 ? currentAlias : current, (0, lodash_1.merge)((0, lodash_1.get)(query.deep, currentAlias !== null && currentAlias !== void 0 ? currentAlias : current), (0, lodash_1.mapKeys)((0, sanitize_query_1.sanitizeQuery)(args, this.accountability), (value, key) => `_${key}`)));
|
|
1241
1260
|
}
|
|
1242
1261
|
}
|
|
1243
1262
|
}
|
|
@@ -1337,6 +1356,10 @@ class GraphQLService {
|
|
|
1337
1356
|
return new webhooks_1.WebhooksService(opts);
|
|
1338
1357
|
case 'directus_shares':
|
|
1339
1358
|
return new shares_1.SharesService(opts);
|
|
1359
|
+
case 'directus_flows':
|
|
1360
|
+
return new flows_1.FlowsService(opts);
|
|
1361
|
+
case 'directus_operations':
|
|
1362
|
+
return new operations_1.OperationsService(opts);
|
|
1340
1363
|
default:
|
|
1341
1364
|
return new items_1.ItemsService(collection, opts);
|
|
1342
1365
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/// <reference types="node" />
|
|
2
|
+
import { Accountability, Query, SchemaOverview } from '@directus/shared/types';
|
|
2
3
|
import { Knex } from 'knex';
|
|
3
4
|
import { AbstractServiceOptions, File } from '../types';
|
|
4
|
-
import { Accountability, Query, SchemaOverview } from '@directus/shared/types';
|
|
5
5
|
export declare class ImportService {
|
|
6
6
|
knex: Knex;
|
|
7
7
|
accountability: Accountability | null;
|
|
@@ -4,25 +4,26 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.ExportService = exports.ImportService = void 0;
|
|
7
|
-
const
|
|
8
|
-
const exceptions_1 = require("../exceptions");
|
|
9
|
-
const StreamArray_1 = __importDefault(require("stream-json/streamers/StreamArray"));
|
|
10
|
-
const items_1 = require("./items");
|
|
7
|
+
const utils_1 = require("@directus/shared/utils");
|
|
11
8
|
const async_1 = require("async");
|
|
12
|
-
const destroy_1 = __importDefault(require("destroy"));
|
|
13
9
|
const csv_parser_1 = __importDefault(require("csv-parser"));
|
|
14
|
-
const
|
|
10
|
+
const destroy_1 = __importDefault(require("destroy"));
|
|
11
|
+
const fs_extra_1 = require("fs-extra");
|
|
15
12
|
const js2xmlparser_1 = require("js2xmlparser");
|
|
16
13
|
const json2csv_1 = require("json2csv");
|
|
17
|
-
const
|
|
14
|
+
const lodash_1 = require("lodash");
|
|
15
|
+
const StreamArray_1 = __importDefault(require("stream-json/streamers/StreamArray"));
|
|
16
|
+
const strip_bom_stream_1 = __importDefault(require("strip-bom-stream"));
|
|
18
17
|
const tmp_promise_1 = require("tmp-promise");
|
|
18
|
+
const database_1 = __importDefault(require("../database"));
|
|
19
19
|
const env_1 = __importDefault(require("../env"));
|
|
20
|
-
const
|
|
20
|
+
const exceptions_1 = require("../exceptions");
|
|
21
|
+
const logger_1 = __importDefault(require("../logger"));
|
|
21
22
|
const get_date_formatted_1 = require("../utils/get-date-formatted");
|
|
22
|
-
const
|
|
23
|
+
const parse_json_1 = require("../utils/parse-json");
|
|
24
|
+
const files_1 = require("./files");
|
|
25
|
+
const items_1 = require("./items");
|
|
23
26
|
const notifications_1 = require("./notifications");
|
|
24
|
-
const logger_1 = __importDefault(require("../logger"));
|
|
25
|
-
const strip_bom_stream_1 = __importDefault(require("strip-bom-stream"));
|
|
26
27
|
class ImportService {
|
|
27
28
|
constructor(options) {
|
|
28
29
|
this.knex = options.knex || (0, database_1.default)();
|
|
@@ -101,7 +102,7 @@ class ImportService {
|
|
|
101
102
|
}
|
|
102
103
|
else {
|
|
103
104
|
try {
|
|
104
|
-
const parsedJson =
|
|
105
|
+
const parsedJson = (0, parse_json_1.parseJSON)(value);
|
|
105
106
|
(0, lodash_1.set)(result, key, parsedJson);
|
|
106
107
|
}
|
|
107
108
|
catch {
|
package/dist/services/index.d.ts
CHANGED
|
@@ -7,12 +7,14 @@ export * from './collections';
|
|
|
7
7
|
export * from './dashboards';
|
|
8
8
|
export * from './fields';
|
|
9
9
|
export * from './files';
|
|
10
|
+
export * from './flows';
|
|
10
11
|
export * from './folders';
|
|
11
12
|
export * from './graphql';
|
|
12
13
|
export * from './import-export';
|
|
13
14
|
export * from './mail';
|
|
14
15
|
export * from './meta';
|
|
15
16
|
export * from './notifications';
|
|
17
|
+
export * from './operations';
|
|
16
18
|
export * from './panels';
|
|
17
19
|
export * from './payload';
|
|
18
20
|
export * from './permissions';
|
package/dist/services/index.js
CHANGED
|
@@ -20,12 +20,14 @@ __exportStar(require("./collections"), exports);
|
|
|
20
20
|
__exportStar(require("./dashboards"), exports);
|
|
21
21
|
__exportStar(require("./fields"), exports);
|
|
22
22
|
__exportStar(require("./files"), exports);
|
|
23
|
+
__exportStar(require("./flows"), exports);
|
|
23
24
|
__exportStar(require("./folders"), exports);
|
|
24
25
|
__exportStar(require("./graphql"), exports);
|
|
25
26
|
__exportStar(require("./import-export"), exports);
|
|
26
27
|
__exportStar(require("./mail"), exports);
|
|
27
28
|
__exportStar(require("./meta"), exports);
|
|
28
29
|
__exportStar(require("./notifications"), exports);
|
|
30
|
+
__exportStar(require("./operations"), exports);
|
|
29
31
|
__exportStar(require("./panels"), exports);
|
|
30
32
|
__exportStar(require("./payload"), exports);
|
|
31
33
|
__exportStar(require("./permissions"), exports);
|
package/dist/services/items.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Accountability, PermissionsAction, Query, SchemaOverview } from '@directus/shared/types';
|
|
2
2
|
import Keyv from 'keyv';
|
|
3
|
-
import {
|
|
4
|
-
import { AbstractService, AbstractServiceOptions, Item as AnyItem,
|
|
3
|
+
import { Knex } from 'knex';
|
|
4
|
+
import { AbstractService, AbstractServiceOptions, Item as AnyItem, MutationOptions, PrimaryKey } from '../types';
|
|
5
5
|
export declare type QueryOptions = {
|
|
6
6
|
stripNonRequested?: boolean;
|
|
7
7
|
permissionsAction?: PermissionsAction;
|
package/dist/services/items.js
CHANGED
|
@@ -4,6 +4,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.ItemsService = void 0;
|
|
7
|
+
const types_1 = require("@directus/shared/types");
|
|
7
8
|
const lodash_1 = require("lodash");
|
|
8
9
|
const cache_1 = require("../cache");
|
|
9
10
|
const database_1 = __importDefault(require("../database"));
|
|
@@ -12,11 +13,11 @@ const emitter_1 = __importDefault(require("../emitter"));
|
|
|
12
13
|
const env_1 = __importDefault(require("../env"));
|
|
13
14
|
const exceptions_1 = require("../exceptions");
|
|
14
15
|
const translate_1 = require("../exceptions/database/translate");
|
|
15
|
-
const types_1 = require("../types");
|
|
16
16
|
const get_ast_from_query_1 = __importDefault(require("../utils/get-ast-from-query"));
|
|
17
17
|
const authorization_1 = require("./authorization");
|
|
18
|
-
const payload_1 = require("./payload");
|
|
19
18
|
const index_1 = require("./index");
|
|
19
|
+
const payload_1 = require("./payload");
|
|
20
|
+
const validate_keys_1 = require("../utils/validate-keys");
|
|
20
21
|
class ItemsService {
|
|
21
22
|
constructor(collection, options) {
|
|
22
23
|
this.collection = collection;
|
|
@@ -244,6 +245,7 @@ class ItemsService {
|
|
|
244
245
|
*/
|
|
245
246
|
async readOne(key, query = {}, opts) {
|
|
246
247
|
const primaryKeyField = this.schema.collections[this.collection].primary;
|
|
248
|
+
(0, validate_keys_1.validateKeys)(this.schema, this.collection, primaryKeyField, key);
|
|
247
249
|
const filterWithKey = (0, lodash_1.assign)({}, query.filter, { [primaryKeyField]: { _eq: key } });
|
|
248
250
|
const queryWithKey = (0, lodash_1.assign)({}, query, { filter: filterWithKey });
|
|
249
251
|
const results = await this.readByQuery(queryWithKey, opts);
|
|
@@ -258,8 +260,13 @@ class ItemsService {
|
|
|
258
260
|
async readMany(keys, query = {}, opts) {
|
|
259
261
|
var _a;
|
|
260
262
|
const primaryKeyField = this.schema.collections[this.collection].primary;
|
|
263
|
+
(0, validate_keys_1.validateKeys)(this.schema, this.collection, primaryKeyField, keys);
|
|
261
264
|
const filterWithKey = { _and: [{ [primaryKeyField]: { _in: keys } }, (_a = query.filter) !== null && _a !== void 0 ? _a : {}] };
|
|
262
265
|
const queryWithKey = (0, lodash_1.assign)({}, query, { filter: filterWithKey });
|
|
266
|
+
// Set query limit as the number of keys
|
|
267
|
+
if (Array.isArray(keys) && keys.length > 0 && !queryWithKey.limit) {
|
|
268
|
+
queryWithKey.limit = keys.length;
|
|
269
|
+
}
|
|
263
270
|
const results = await this.readByQuery(queryWithKey, opts);
|
|
264
271
|
return results;
|
|
265
272
|
}
|
|
@@ -268,12 +275,16 @@ class ItemsService {
|
|
|
268
275
|
*/
|
|
269
276
|
async updateByQuery(query, data, opts) {
|
|
270
277
|
const keys = await this.getKeysByQuery(query);
|
|
278
|
+
const primaryKeyField = this.schema.collections[this.collection].primary;
|
|
279
|
+
(0, validate_keys_1.validateKeys)(this.schema, this.collection, primaryKeyField, keys);
|
|
271
280
|
return keys.length ? await this.updateMany(keys, data, opts) : [];
|
|
272
281
|
}
|
|
273
282
|
/**
|
|
274
283
|
* Update a single item by primary key
|
|
275
284
|
*/
|
|
276
285
|
async updateOne(key, data, opts) {
|
|
286
|
+
const primaryKeyField = this.schema.collections[this.collection].primary;
|
|
287
|
+
(0, validate_keys_1.validateKeys)(this.schema, this.collection, primaryKeyField, key);
|
|
277
288
|
await this.updateMany([key], data, opts);
|
|
278
289
|
return key;
|
|
279
290
|
}
|
|
@@ -282,6 +293,7 @@ class ItemsService {
|
|
|
282
293
|
*/
|
|
283
294
|
async updateMany(keys, data, opts) {
|
|
284
295
|
const primaryKeyField = this.schema.collections[this.collection].primary;
|
|
296
|
+
(0, validate_keys_1.validateKeys)(this.schema, this.collection, primaryKeyField, keys);
|
|
285
297
|
const fields = Object.keys(this.schema.collections[this.collection].fields);
|
|
286
298
|
const aliases = Object.values(this.schema.collections[this.collection].fields)
|
|
287
299
|
.filter((field) => field.alias === true)
|
|
@@ -306,6 +318,8 @@ class ItemsService {
|
|
|
306
318
|
accountability: this.accountability,
|
|
307
319
|
})
|
|
308
320
|
: payload;
|
|
321
|
+
// Sort keys to ensure that the order is maintained
|
|
322
|
+
keys.sort();
|
|
309
323
|
if (this.accountability) {
|
|
310
324
|
await authorizationService.checkAccess('update', this.collection, keys);
|
|
311
325
|
}
|
|
@@ -409,6 +423,9 @@ class ItemsService {
|
|
|
409
423
|
async upsertOne(payload, opts) {
|
|
410
424
|
const primaryKeyField = this.schema.collections[this.collection].primary;
|
|
411
425
|
const primaryKey = payload[primaryKeyField];
|
|
426
|
+
if (primaryKey) {
|
|
427
|
+
(0, validate_keys_1.validateKeys)(this.schema, this.collection, primaryKeyField, primaryKey);
|
|
428
|
+
}
|
|
412
429
|
const exists = primaryKey &&
|
|
413
430
|
!!(await this.knex
|
|
414
431
|
.select(primaryKeyField)
|
|
@@ -449,12 +466,16 @@ class ItemsService {
|
|
|
449
466
|
*/
|
|
450
467
|
async deleteByQuery(query, opts) {
|
|
451
468
|
const keys = await this.getKeysByQuery(query);
|
|
469
|
+
const primaryKeyField = this.schema.collections[this.collection].primary;
|
|
470
|
+
(0, validate_keys_1.validateKeys)(this.schema, this.collection, primaryKeyField, keys);
|
|
452
471
|
return keys.length ? await this.deleteMany(keys, opts) : [];
|
|
453
472
|
}
|
|
454
473
|
/**
|
|
455
474
|
* Delete a single item by primary key
|
|
456
475
|
*/
|
|
457
476
|
async deleteOne(key, opts) {
|
|
477
|
+
const primaryKeyField = this.schema.collections[this.collection].primary;
|
|
478
|
+
(0, validate_keys_1.validateKeys)(this.schema, this.collection, primaryKeyField, key);
|
|
458
479
|
await this.deleteMany([key], opts);
|
|
459
480
|
return key;
|
|
460
481
|
}
|
|
@@ -463,10 +484,12 @@ class ItemsService {
|
|
|
463
484
|
*/
|
|
464
485
|
async deleteMany(keys, opts) {
|
|
465
486
|
const primaryKeyField = this.schema.collections[this.collection].primary;
|
|
487
|
+
(0, validate_keys_1.validateKeys)(this.schema, this.collection, primaryKeyField, keys);
|
|
466
488
|
if (this.accountability && this.accountability.admin !== true) {
|
|
467
489
|
const authorizationService = new authorization_1.AuthorizationService({
|
|
468
490
|
accountability: this.accountability,
|
|
469
491
|
schema: this.schema,
|
|
492
|
+
knex: this.knex,
|
|
470
493
|
});
|
|
471
494
|
await authorizationService.checkAccess('delete', this.collection, keys);
|
|
472
495
|
}
|
|
@@ -65,13 +65,14 @@ class MailService {
|
|
|
65
65
|
}
|
|
66
66
|
async getDefaultTemplateData() {
|
|
67
67
|
const projectInfo = await this.knex
|
|
68
|
-
.select(['project_name', 'project_logo', 'project_color'])
|
|
68
|
+
.select(['project_name', 'project_logo', 'project_color', 'project_url'])
|
|
69
69
|
.from('directus_settings')
|
|
70
70
|
.first();
|
|
71
71
|
return {
|
|
72
72
|
projectName: (projectInfo === null || projectInfo === void 0 ? void 0 : projectInfo.project_name) || 'Directus',
|
|
73
73
|
projectColor: (projectInfo === null || projectInfo === void 0 ? void 0 : projectInfo.project_color) || '#546e7a',
|
|
74
74
|
projectLogo: getProjectLogoURL(projectInfo === null || projectInfo === void 0 ? void 0 : projectInfo.project_logo),
|
|
75
|
+
projectUrl: (projectInfo === null || projectInfo === void 0 ? void 0 : projectInfo.project_url) || '',
|
|
75
76
|
};
|
|
76
77
|
function getProjectLogoURL(logoID) {
|
|
77
78
|
const projectLogoUrl = new url_1.Url(env_1.default.PUBLIC_URL);
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import { UsersService, MailService } from '.';
|
|
2
1
|
import { AbstractServiceOptions, PrimaryKey, MutationOptions } from '../types';
|
|
3
2
|
import { ItemsService } from './items';
|
|
4
3
|
import { Notification } from '@directus/shared/types';
|
|
4
|
+
import { UsersService } from './users';
|
|
5
|
+
import { MailService } from './mail';
|
|
5
6
|
export declare class NotificationsService extends ItemsService {
|
|
6
7
|
usersService: UsersService;
|
|
7
8
|
mailService: MailService;
|
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.NotificationsService = void 0;
|
|
4
|
-
const _1 = require(".");
|
|
5
4
|
const items_1 = require("./items");
|
|
6
5
|
const md_1 = require("../utils/md");
|
|
6
|
+
const users_1 = require("./users");
|
|
7
|
+
const mail_1 = require("./mail");
|
|
7
8
|
class NotificationsService extends items_1.ItemsService {
|
|
8
9
|
constructor(options) {
|
|
9
10
|
super('directus_notifications', options);
|
|
10
|
-
this.usersService = new
|
|
11
|
-
this.mailService = new
|
|
11
|
+
this.usersService = new users_1.UsersService({ schema: this.schema });
|
|
12
|
+
this.mailService = new mail_1.MailService({ schema: this.schema, accountability: this.accountability });
|
|
12
13
|
}
|
|
13
14
|
async createOne(data, opts) {
|
|
14
15
|
await this.sendEmail(data);
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { OperationRaw } from '@directus/shared/types';
|
|
2
|
+
import { Messenger } from '../messenger';
|
|
3
|
+
import { AbstractServiceOptions, Item, MutationOptions, PrimaryKey } from '../types';
|
|
4
|
+
import { ItemsService } from './items';
|
|
5
|
+
export declare class OperationsService extends ItemsService<OperationRaw> {
|
|
6
|
+
messenger: Messenger;
|
|
7
|
+
constructor(options: AbstractServiceOptions);
|
|
8
|
+
createOne(data: Partial<Item>, opts?: MutationOptions): Promise<PrimaryKey>;
|
|
9
|
+
createMany(data: Partial<Item>[], opts?: MutationOptions): Promise<PrimaryKey[]>;
|
|
10
|
+
updateOne(key: PrimaryKey, data: Partial<Item>, opts?: MutationOptions): Promise<PrimaryKey>;
|
|
11
|
+
updateMany(keys: PrimaryKey[], data: Partial<Item>, opts?: MutationOptions): Promise<PrimaryKey[]>;
|
|
12
|
+
deleteOne(key: PrimaryKey, opts?: MutationOptions): Promise<PrimaryKey>;
|
|
13
|
+
deleteMany(keys: PrimaryKey[], opts?: MutationOptions): Promise<PrimaryKey[]>;
|
|
14
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.OperationsService = void 0;
|
|
4
|
+
const messenger_1 = require("../messenger");
|
|
5
|
+
const items_1 = require("./items");
|
|
6
|
+
class OperationsService extends items_1.ItemsService {
|
|
7
|
+
constructor(options) {
|
|
8
|
+
super('directus_operations', options);
|
|
9
|
+
this.messenger = (0, messenger_1.getMessenger)();
|
|
10
|
+
}
|
|
11
|
+
async createOne(data, opts) {
|
|
12
|
+
const result = await super.createOne(data, opts);
|
|
13
|
+
this.messenger.publish('flows', { type: 'reload' });
|
|
14
|
+
return result;
|
|
15
|
+
}
|
|
16
|
+
async createMany(data, opts) {
|
|
17
|
+
const result = await super.createMany(data, opts);
|
|
18
|
+
this.messenger.publish('flows', { type: 'reload' });
|
|
19
|
+
return result;
|
|
20
|
+
}
|
|
21
|
+
async updateOne(key, data, opts) {
|
|
22
|
+
const result = await super.updateOne(key, data, opts);
|
|
23
|
+
this.messenger.publish('flows', { type: 'reload' });
|
|
24
|
+
return result;
|
|
25
|
+
}
|
|
26
|
+
async updateMany(keys, data, opts) {
|
|
27
|
+
const result = await super.updateMany(keys, data, opts);
|
|
28
|
+
this.messenger.publish('flows', { type: 'reload' });
|
|
29
|
+
return result;
|
|
30
|
+
}
|
|
31
|
+
async deleteOne(key, opts) {
|
|
32
|
+
const result = await super.deleteOne(key, opts);
|
|
33
|
+
this.messenger.publish('flows', { type: 'reload' });
|
|
34
|
+
return result;
|
|
35
|
+
}
|
|
36
|
+
async deleteMany(keys, opts) {
|
|
37
|
+
const result = await super.deleteMany(keys, opts);
|
|
38
|
+
this.messenger.publish('flows', { type: 'reload' });
|
|
39
|
+
return result;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
exports.OperationsService = OperationsService;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { Knex } from 'knex';
|
|
2
|
-
import { AbstractServiceOptions, Item, PrimaryKey } from '../types';
|
|
3
1
|
import { Accountability, SchemaOverview } from '@directus/shared/types';
|
|
2
|
+
import { Knex } from 'knex';
|
|
4
3
|
import { Helpers } from '../database/helpers';
|
|
4
|
+
import { AbstractServiceOptions, Item, PrimaryKey } from '../types';
|
|
5
5
|
declare type Action = 'create' | 'read' | 'update';
|
|
6
6
|
declare type Transformers = {
|
|
7
7
|
[type: string]: (context: {
|
package/dist/services/payload.js
CHANGED
|
@@ -4,18 +4,19 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.PayloadService = void 0;
|
|
7
|
+
const utils_1 = require("@directus/shared/utils");
|
|
7
8
|
const date_fns_1 = require("date-fns");
|
|
9
|
+
const flat_1 = require("flat");
|
|
8
10
|
const joi_1 = __importDefault(require("joi"));
|
|
9
11
|
const lodash_1 = require("lodash");
|
|
10
12
|
const uuid_1 = require("uuid");
|
|
13
|
+
const wellknown_1 = require("wellknown");
|
|
11
14
|
const database_1 = __importDefault(require("../database"));
|
|
12
|
-
const exceptions_1 = require("../exceptions");
|
|
13
|
-
const utils_1 = require("@directus/shared/utils");
|
|
14
|
-
const items_1 = require("./items");
|
|
15
|
-
const flat_1 = require("flat");
|
|
16
15
|
const helpers_1 = require("../database/helpers");
|
|
17
|
-
const
|
|
16
|
+
const exceptions_1 = require("../exceptions");
|
|
18
17
|
const generate_hash_1 = require("../utils/generate-hash");
|
|
18
|
+
const parse_json_1 = require("../utils/parse-json");
|
|
19
|
+
const items_1 = require("./items");
|
|
19
20
|
/**
|
|
20
21
|
* Process a given payload for a collection to ensure the special fields (hash, uuid, date etc) are
|
|
21
22
|
* handled correctly.
|
|
@@ -55,7 +56,7 @@ class PayloadService {
|
|
|
55
56
|
if (action === 'read') {
|
|
56
57
|
if (typeof value === 'string') {
|
|
57
58
|
try {
|
|
58
|
-
return
|
|
59
|
+
return (0, parse_json_1.parseJSON)(value);
|
|
59
60
|
}
|
|
60
61
|
catch {
|
|
61
62
|
return value;
|
|
@@ -196,7 +197,7 @@ class PayloadService {
|
|
|
196
197
|
processGeometries(payloads, action) {
|
|
197
198
|
const process = action == 'read'
|
|
198
199
|
? (value) => (typeof value === 'string' ? (0, wellknown_1.parse)(value) : value)
|
|
199
|
-
: (value) => this.helpers.st.fromGeoJSON(typeof value == 'string' ?
|
|
200
|
+
: (value) => this.helpers.st.fromGeoJSON(typeof value == 'string' ? (0, parse_json_1.parseJSON)(value) : value);
|
|
200
201
|
const fieldsInCollection = Object.entries(this.schema.collections[this.collection].fields);
|
|
201
202
|
const geometryColumns = fieldsInCollection.filter(([_, field]) => field.type.startsWith('geometry'));
|
|
202
203
|
for (const [name] of geometryColumns) {
|
package/dist/services/users.d.ts
CHANGED
|
@@ -18,6 +18,10 @@ export declare class UsersService extends ItemsService {
|
|
|
18
18
|
*/
|
|
19
19
|
private checkPasswordPolicy;
|
|
20
20
|
private checkRemainingAdminExistence;
|
|
21
|
+
/**
|
|
22
|
+
* Make sure there's at least one active admin user when updating user status
|
|
23
|
+
*/
|
|
24
|
+
private checkRemainingActiveAdmin;
|
|
21
25
|
/**
|
|
22
26
|
* Create a new user
|
|
23
27
|
*/
|
package/dist/services/users.js
CHANGED
|
@@ -101,6 +101,23 @@ class UsersService extends items_1.ItemsService {
|
|
|
101
101
|
throw new exceptions_2.UnprocessableEntityException(`You can't remove the last admin user from the role.`);
|
|
102
102
|
}
|
|
103
103
|
}
|
|
104
|
+
/**
|
|
105
|
+
* Make sure there's at least one active admin user when updating user status
|
|
106
|
+
*/
|
|
107
|
+
async checkRemainingActiveAdmin(excludeKeys) {
|
|
108
|
+
const otherAdminUsers = await this.knex
|
|
109
|
+
.count('*', { as: 'count' })
|
|
110
|
+
.from('directus_users')
|
|
111
|
+
.whereNotIn('directus_users.id', excludeKeys)
|
|
112
|
+
.andWhere({ 'directus_roles.admin_access': true })
|
|
113
|
+
.andWhere({ 'directus_users.status': 'active' })
|
|
114
|
+
.leftJoin('directus_roles', 'directus_users.role', 'directus_roles.id')
|
|
115
|
+
.first();
|
|
116
|
+
const otherAdminUsersCount = +((otherAdminUsers === null || otherAdminUsers === void 0 ? void 0 : otherAdminUsers.count) || 0);
|
|
117
|
+
if (otherAdminUsersCount === 0) {
|
|
118
|
+
throw new exceptions_2.UnprocessableEntityException(`You can't change the active status of the last admin user.`);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
104
121
|
/**
|
|
105
122
|
* Create a new user
|
|
106
123
|
*/
|
|
@@ -149,6 +166,9 @@ class UsersService extends items_1.ItemsService {
|
|
|
149
166
|
await this.checkRemainingAdminExistence(keys);
|
|
150
167
|
}
|
|
151
168
|
}
|
|
169
|
+
if (data.status !== undefined && data.status !== 'active') {
|
|
170
|
+
await this.checkRemainingActiveAdmin(keys);
|
|
171
|
+
}
|
|
152
172
|
if (data.email) {
|
|
153
173
|
if (keys.length > 1) {
|
|
154
174
|
throw new record_not_unique_1.RecordNotUniqueException('email', {
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { AbstractServiceOptions, Item, PrimaryKey, Webhook, MutationOptions } from '../types';
|
|
2
2
|
import { ItemsService } from './items';
|
|
3
|
+
import { Messenger } from '../messenger';
|
|
3
4
|
export declare class WebhooksService extends ItemsService<Webhook> {
|
|
5
|
+
messenger: Messenger;
|
|
4
6
|
constructor(options: AbstractServiceOptions);
|
|
5
7
|
createOne(data: Partial<Item>, opts?: MutationOptions): Promise<PrimaryKey>;
|
|
6
8
|
createMany(data: Partial<Item>[], opts?: MutationOptions): Promise<PrimaryKey[]>;
|