directus 9.11.0 → 9.12.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/app.js +8 -1
- package/dist/cli/utils/create-env/env-stub.liquid +266 -9
- package/dist/controllers/activity.js +1 -1
- 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/index.js +15 -19
- 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/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 +165 -11
- 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/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/authentication.d.ts +2 -2
- package/dist/services/authentication.js +7 -7
- package/dist/services/authorization.js +12 -0
- package/dist/services/flows.d.ts +14 -0
- package/dist/services/flows.js +42 -0
- package/dist/services/graphql.js +13 -2
- package/dist/services/import-export.js +7 -3
- package/dist/services/index.d.ts +2 -0
- package/dist/services/index.js +2 -0
- package/dist/services/items.js +17 -1
- 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/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/index.d.ts → apply-query.d.ts} +0 -0
- package/dist/utils/{apply-query/index.js → apply-query.js} +147 -48
- 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/operation-options.d.ts +3 -0
- package/dist/utils/operation-options.js +45 -0
- 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 +19 -15
- package/dist/types/activity.d.ts +0 -9
- package/dist/types/activity.js +0 -13
- package/dist/utils/apply-query/operators/between.operator.d.ts +0 -2
- package/dist/utils/apply-query/operators/between.operator.js +0 -16
- package/dist/utils/apply-query/operators/contains.operator.d.ts +0 -2
- package/dist/utils/apply-query/operators/contains.operator.js +0 -9
- package/dist/utils/apply-query/operators/ends-with.operator.d.ts +0 -2
- package/dist/utils/apply-query/operators/ends-with.operator.js +0 -9
- package/dist/utils/apply-query/operators/equals.operator.d.ts +0 -2
- package/dist/utils/apply-query/operators/equals.operator.js +0 -9
- package/dist/utils/apply-query/operators/greather-than-equals.operator.d.ts +0 -2
- package/dist/utils/apply-query/operators/greather-than-equals.operator.js +0 -9
- package/dist/utils/apply-query/operators/greather-than.operator.d.ts +0 -2
- package/dist/utils/apply-query/operators/greather-than.operator.js +0 -9
- package/dist/utils/apply-query/operators/in.operator.d.ts +0 -2
- package/dist/utils/apply-query/operators/in.operator.js +0 -14
- package/dist/utils/apply-query/operators/index.d.ts +0 -3
- package/dist/utils/apply-query/operators/index.js +0 -72
- package/dist/utils/apply-query/operators/insensitive-contains.operator.d.ts +0 -2
- package/dist/utils/apply-query/operators/insensitive-contains.operator.js +0 -9
- package/dist/utils/apply-query/operators/insensitive-ends-with.operator.d.ts +0 -2
- package/dist/utils/apply-query/operators/insensitive-ends-with.operator.js +0 -9
- package/dist/utils/apply-query/operators/insensitive-equals.operator.d.ts +0 -2
- package/dist/utils/apply-query/operators/insensitive-equals.operator.js +0 -9
- package/dist/utils/apply-query/operators/insensitive-not-contains.operator.d.ts +0 -2
- package/dist/utils/apply-query/operators/insensitive-not-contains.operator.js +0 -9
- package/dist/utils/apply-query/operators/insensitive-not-ends-with.operator.d.ts +0 -2
- package/dist/utils/apply-query/operators/insensitive-not-ends-with.operator.js +0 -9
- package/dist/utils/apply-query/operators/insensitive-not-equals.operator.d.ts +0 -2
- package/dist/utils/apply-query/operators/insensitive-not-equals.operator.js +0 -9
- package/dist/utils/apply-query/operators/insensitive-not-starts-with.operator.d.ts +0 -2
- package/dist/utils/apply-query/operators/insensitive-not-starts-with.operator.js +0 -9
- package/dist/utils/apply-query/operators/insensitive-starts-with.operator.d.ts +0 -2
- package/dist/utils/apply-query/operators/insensitive-starts-with.operator.js +0 -9
- package/dist/utils/apply-query/operators/intersects-bbox.operator.d.ts +0 -2
- package/dist/utils/apply-query/operators/intersects-bbox.operator.js +0 -9
- package/dist/utils/apply-query/operators/intersects.operator.d.ts +0 -2
- package/dist/utils/apply-query/operators/intersects.operator.js +0 -9
- package/dist/utils/apply-query/operators/is-empty.operator.d.ts +0 -2
- package/dist/utils/apply-query/operators/is-empty.operator.js +0 -14
- package/dist/utils/apply-query/operators/is-not-empty.operator.d.ts +0 -2
- package/dist/utils/apply-query/operators/is-not-empty.operator.js +0 -14
- package/dist/utils/apply-query/operators/is-not-null.operator.d.ts +0 -2
- package/dist/utils/apply-query/operators/is-not-null.operator.js +0 -14
- package/dist/utils/apply-query/operators/is-null.operator.d.ts +0 -2
- package/dist/utils/apply-query/operators/is-null.operator.js +0 -14
- package/dist/utils/apply-query/operators/less-than-equals.operator.d.ts +0 -2
- package/dist/utils/apply-query/operators/less-than-equals.operator.js +0 -9
- package/dist/utils/apply-query/operators/less-than.operator.d.ts +0 -2
- package/dist/utils/apply-query/operators/less-than.operator.js +0 -9
- package/dist/utils/apply-query/operators/not-between.operator.d.ts +0 -2
- package/dist/utils/apply-query/operators/not-between.operator.js +0 -16
- package/dist/utils/apply-query/operators/not-contains.operator.d.ts +0 -2
- package/dist/utils/apply-query/operators/not-contains.operator.js +0 -9
- package/dist/utils/apply-query/operators/not-ends-with.operator.d.ts +0 -2
- package/dist/utils/apply-query/operators/not-ends-with.operator.js +0 -9
- package/dist/utils/apply-query/operators/not-equals.operator.d.ts +0 -2
- package/dist/utils/apply-query/operators/not-equals.operator.js +0 -9
- package/dist/utils/apply-query/operators/not-in.operator.d.ts +0 -2
- package/dist/utils/apply-query/operators/not-in.operator.js +0 -14
- package/dist/utils/apply-query/operators/not-intersects-bbox.operator.d.ts +0 -2
- package/dist/utils/apply-query/operators/not-intersects-bbox.operator.js +0 -9
- package/dist/utils/apply-query/operators/not-intersects.operator.d.ts +0 -2
- package/dist/utils/apply-query/operators/not-intersects.operator.js +0 -9
- package/dist/utils/apply-query/operators/not-starts-with.operator.d.ts +0 -2
- package/dist/utils/apply-query/operators/not-starts-with.operator.js +0 -9
- package/dist/utils/apply-query/operators/operator-register.d.ts +0 -13
- package/dist/utils/apply-query/operators/operator-register.js +0 -7
- package/dist/utils/apply-query/operators/starts-with.operator.d.ts +0 -2
- package/dist/utils/apply-query/operators/starts-with.operator.js +0 -9
- package/example.env +0 -202
|
@@ -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,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[]>;
|
|
@@ -1,40 +1,41 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.WebhooksService = void 0;
|
|
4
|
-
const webhooks_1 = require("../webhooks");
|
|
5
4
|
const items_1 = require("./items");
|
|
5
|
+
const messenger_1 = require("../messenger");
|
|
6
6
|
class WebhooksService extends items_1.ItemsService {
|
|
7
7
|
constructor(options) {
|
|
8
8
|
super('directus_webhooks', options);
|
|
9
|
+
this.messenger = (0, messenger_1.getMessenger)();
|
|
9
10
|
}
|
|
10
11
|
async createOne(data, opts) {
|
|
11
12
|
const result = await super.createOne(data, opts);
|
|
12
|
-
|
|
13
|
+
this.messenger.publish('webhooks', { type: 'reload' });
|
|
13
14
|
return result;
|
|
14
15
|
}
|
|
15
16
|
async createMany(data, opts) {
|
|
16
17
|
const result = await super.createMany(data, opts);
|
|
17
|
-
|
|
18
|
+
this.messenger.publish('webhooks', { type: 'reload' });
|
|
18
19
|
return result;
|
|
19
20
|
}
|
|
20
21
|
async updateOne(key, data, opts) {
|
|
21
22
|
const result = await super.updateOne(key, data, opts);
|
|
22
|
-
|
|
23
|
+
this.messenger.publish('webhooks', { type: 'reload' });
|
|
23
24
|
return result;
|
|
24
25
|
}
|
|
25
26
|
async updateMany(keys, data, opts) {
|
|
26
27
|
const result = await super.updateMany(keys, data, opts);
|
|
27
|
-
|
|
28
|
+
this.messenger.publish('webhooks', { type: 'reload' });
|
|
28
29
|
return result;
|
|
29
30
|
}
|
|
30
31
|
async deleteOne(key, opts) {
|
|
31
32
|
const result = await super.deleteOne(key, opts);
|
|
32
|
-
|
|
33
|
+
this.messenger.publish('webhooks', { type: 'reload' });
|
|
33
34
|
return result;
|
|
34
35
|
}
|
|
35
36
|
async deleteMany(keys, opts) {
|
|
36
37
|
const result = await super.deleteMany(keys, opts);
|
|
37
|
-
|
|
38
|
+
this.messenger.publish('webhooks', { type: 'reload' });
|
|
38
39
|
return result;
|
|
39
40
|
}
|
|
40
41
|
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { ActionHandler, FilterHandler, InitHandler } from '@directus/shared/types';
|
|
2
|
+
import { ScheduledTask } from 'node-cron';
|
|
3
|
+
export declare type EventHandler = {
|
|
4
|
+
type: 'filter';
|
|
5
|
+
name: string;
|
|
6
|
+
handler: FilterHandler;
|
|
7
|
+
} | {
|
|
8
|
+
type: 'action';
|
|
9
|
+
name: string;
|
|
10
|
+
handler: ActionHandler;
|
|
11
|
+
} | {
|
|
12
|
+
type: 'init';
|
|
13
|
+
name: string;
|
|
14
|
+
handler: InitHandler;
|
|
15
|
+
} | {
|
|
16
|
+
type: 'schedule';
|
|
17
|
+
task: ScheduledTask;
|
|
18
|
+
};
|
package/dist/types/index.d.ts
CHANGED
package/dist/types/index.js
CHANGED
|
@@ -10,11 +10,11 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
10
10
|
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
11
11
|
};
|
|
12
12
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
13
|
-
__exportStar(require("./activity"), exports);
|
|
14
13
|
__exportStar(require("./assets"), exports);
|
|
15
14
|
__exportStar(require("./ast"), exports);
|
|
16
15
|
__exportStar(require("./auth"), exports);
|
|
17
16
|
__exportStar(require("./collection"), exports);
|
|
17
|
+
__exportStar(require("./events"), exports);
|
|
18
18
|
__exportStar(require("./files"), exports);
|
|
19
19
|
__exportStar(require("./graphql"), exports);
|
|
20
20
|
__exportStar(require("./items"), exports);
|
|
File without changes
|
|
@@ -7,12 +7,12 @@ exports.applyAggregate = exports.applySearch = exports.applyFilter = exports.app
|
|
|
7
7
|
const lodash_1 = require("lodash");
|
|
8
8
|
const nanoid_1 = require("nanoid");
|
|
9
9
|
const uuid_validate_1 = __importDefault(require("uuid-validate"));
|
|
10
|
-
const helpers_1 = require("
|
|
11
|
-
const invalid_query_1 = require("
|
|
12
|
-
const get_column_1 = require("
|
|
13
|
-
const get_column_path_1 = require("
|
|
14
|
-
const get_relation_info_1 = require("
|
|
15
|
-
const
|
|
10
|
+
const helpers_1 = require("../database/helpers");
|
|
11
|
+
const invalid_query_1 = require("../exceptions/invalid-query");
|
|
12
|
+
const get_column_1 = require("./get-column");
|
|
13
|
+
const get_column_path_1 = require("./get-column-path");
|
|
14
|
+
const get_relation_info_1 = require("./get-relation-info");
|
|
15
|
+
const utils_1 = require("@directus/shared/utils");
|
|
16
16
|
const generateAlias = (0, nanoid_1.customAlphabet)('abcdefghijklmnopqrstuvwxyz', 5);
|
|
17
17
|
/**
|
|
18
18
|
* Apply the Query to a given Knex query builder instance
|
|
@@ -155,9 +155,6 @@ function applyFilter(knex, schema, rootQuery, rootFilter, collection, subQuery =
|
|
|
155
155
|
addJoins(rootQuery, rootFilter, collection);
|
|
156
156
|
addWhereClauses(knex, rootQuery, rootFilter, collection);
|
|
157
157
|
return rootQuery;
|
|
158
|
-
function isNegativeOperator(operator) {
|
|
159
|
-
return operator.indexOf('_n') === 0;
|
|
160
|
-
}
|
|
161
158
|
function addJoins(dbQuery, filter, collection) {
|
|
162
159
|
for (const [key, value] of Object.entries(filter)) {
|
|
163
160
|
if (key === '_or' || key === '_and') {
|
|
@@ -185,33 +182,8 @@ function applyFilter(knex, schema, rootQuery, rootFilter, collection, subQuery =
|
|
|
185
182
|
}
|
|
186
183
|
}
|
|
187
184
|
}
|
|
188
|
-
function callbackSubqueryRelation(relation, value) {
|
|
189
|
-
return function (subQueryKnex) {
|
|
190
|
-
const field = relation.field;
|
|
191
|
-
const collection = relation.collection;
|
|
192
|
-
const column = `${collection}.${field}`;
|
|
193
|
-
subQueryKnex.from(collection).whereRaw(`${field} = ${column}`);
|
|
194
|
-
applyQuery(knex, relation.collection, subQueryKnex, {
|
|
195
|
-
filter: value,
|
|
196
|
-
}, schema, true);
|
|
197
|
-
};
|
|
198
|
-
}
|
|
199
|
-
function inverseFilters(value) {
|
|
200
|
-
for (const field in value) {
|
|
201
|
-
for (const operator in value[field]) {
|
|
202
|
-
let inverseOperator = operator;
|
|
203
|
-
if (isNegativeOperator(operator)) {
|
|
204
|
-
inverseOperator = '_' + operator.substring(2);
|
|
205
|
-
}
|
|
206
|
-
else {
|
|
207
|
-
inverseOperator = '_n' + operator.substring(1);
|
|
208
|
-
}
|
|
209
|
-
value[field][inverseOperator] = value[field][operator];
|
|
210
|
-
delete value[field][operator];
|
|
211
|
-
}
|
|
212
|
-
}
|
|
213
|
-
}
|
|
214
185
|
function addWhereClauses(knex, dbQuery, filter, collection, logical = 'and') {
|
|
186
|
+
var _a, _b;
|
|
215
187
|
for (const [key, value] of Object.entries(filter)) {
|
|
216
188
|
if (key === '_or' || key === '_and') {
|
|
217
189
|
// If the _or array contains an empty object (full permissions), we should short-circuit and ignore all other
|
|
@@ -252,12 +224,24 @@ function applyFilter(knex, schema, rootQuery, rootFilter, collection, subQuery =
|
|
|
252
224
|
if (relationType === 'o2a') {
|
|
253
225
|
pkField = knex.raw(`CAST(?? AS CHAR(255))`, [pkField]);
|
|
254
226
|
}
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
227
|
+
const subQueryBuilder = (filter) => (subQueryKnex) => {
|
|
228
|
+
const field = relation.field;
|
|
229
|
+
const collection = relation.collection;
|
|
230
|
+
const column = `${collection}.${field}`;
|
|
231
|
+
subQueryKnex
|
|
232
|
+
.select({ [field]: column })
|
|
233
|
+
.from(collection)
|
|
234
|
+
.whereNotNull(column);
|
|
235
|
+
applyQuery(knex, relation.collection, subQueryKnex, { filter }, schema, true);
|
|
236
|
+
};
|
|
237
|
+
if (((_a = Object.keys(value)) === null || _a === void 0 ? void 0 : _a[0]) === '_none') {
|
|
238
|
+
dbQuery[logical].whereNotIn(pkField, subQueryBuilder(Object.values(value)[0]));
|
|
239
|
+
}
|
|
240
|
+
else if (((_b = Object.keys(value)) === null || _b === void 0 ? void 0 : _b[0]) === '_some') {
|
|
241
|
+
dbQuery[logical].whereIn(pkField, subQueryBuilder(Object.values(value)[0]));
|
|
258
242
|
}
|
|
259
243
|
else {
|
|
260
|
-
dbQuery[logical].
|
|
244
|
+
dbQuery[logical].whereIn(pkField, subQueryBuilder(value));
|
|
261
245
|
}
|
|
262
246
|
}
|
|
263
247
|
}
|
|
@@ -267,6 +251,32 @@ function applyFilter(knex, schema, rootQuery, rootFilter, collection, subQuery =
|
|
|
267
251
|
const selectionRaw = (0, get_column_1.getColumn)(knex, table, column, false, schema);
|
|
268
252
|
// Knex supports "raw" in the columnName parameter, but isn't typed as such. Too bad..
|
|
269
253
|
// See https://github.com/knex/knex/issues/4518 @TODO remove as any once knex is updated
|
|
254
|
+
// These operators don't rely on a value, and can thus be used without one (eg `?filter[field][_null]`)
|
|
255
|
+
if (operator === '_null' || (operator === '_nnull' && compareValue === false)) {
|
|
256
|
+
dbQuery[logical].whereNull(selectionRaw);
|
|
257
|
+
}
|
|
258
|
+
if (operator === '_nnull' || (operator === '_null' && compareValue === false)) {
|
|
259
|
+
dbQuery[logical].whereNotNull(selectionRaw);
|
|
260
|
+
}
|
|
261
|
+
if (operator === '_empty' || (operator === '_nempty' && compareValue === false)) {
|
|
262
|
+
dbQuery[logical].andWhere((query) => {
|
|
263
|
+
query.where(key, '=', '');
|
|
264
|
+
});
|
|
265
|
+
}
|
|
266
|
+
if (operator === '_nempty' || (operator === '_empty' && compareValue === false)) {
|
|
267
|
+
dbQuery[logical].andWhere((query) => {
|
|
268
|
+
query.where(key, '!=', '');
|
|
269
|
+
});
|
|
270
|
+
}
|
|
271
|
+
// Cast filter value (compareValue) based on function used
|
|
272
|
+
if (column.includes('(') && column.includes(')')) {
|
|
273
|
+
const functionName = column.split('(')[0];
|
|
274
|
+
const type = (0, utils_1.getOutputTypeForFunction)(functionName);
|
|
275
|
+
if (['bigInteger', 'integer', 'float', 'decimal'].includes(type)) {
|
|
276
|
+
compareValue = Number(compareValue);
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
// Cast filter value (compareValue) based on type of field being filtered against
|
|
270
280
|
const [collection, field] = key.split('.');
|
|
271
281
|
if (collection in schema.collections && field in schema.collections[collection].fields) {
|
|
272
282
|
const type = schema.collections[collection].fields[field].type;
|
|
@@ -298,16 +308,105 @@ function applyFilter(knex, schema, rootQuery, rootFilter, collection, subQuery =
|
|
|
298
308
|
// We need to remove any undefined values, as they are useless
|
|
299
309
|
compareValue = compareValue.filter((val) => val !== undefined);
|
|
300
310
|
}
|
|
301
|
-
if (operator
|
|
302
|
-
|
|
303
|
-
query: dbQuery[logical],
|
|
304
|
-
helpers,
|
|
305
|
-
selectionRaw,
|
|
306
|
-
compareValue,
|
|
307
|
-
});
|
|
311
|
+
if (operator === '_eq') {
|
|
312
|
+
dbQuery[logical].where(selectionRaw, '=', compareValue);
|
|
308
313
|
}
|
|
309
|
-
|
|
310
|
-
|
|
314
|
+
if (operator === '_neq') {
|
|
315
|
+
dbQuery[logical].whereNot(selectionRaw, compareValue);
|
|
316
|
+
}
|
|
317
|
+
if (operator === '_ieq') {
|
|
318
|
+
dbQuery[logical].whereRaw(`LOWER(??) = ?`, [selectionRaw, `${compareValue.toLowerCase()}`]);
|
|
319
|
+
}
|
|
320
|
+
if (operator === '_nieq') {
|
|
321
|
+
dbQuery[logical].whereRaw(`LOWER(??) <> ?`, [selectionRaw, `${compareValue.toLowerCase()}`]);
|
|
322
|
+
}
|
|
323
|
+
if (operator === '_contains') {
|
|
324
|
+
dbQuery[logical].where(selectionRaw, 'like', `%${compareValue}%`);
|
|
325
|
+
}
|
|
326
|
+
if (operator === '_ncontains') {
|
|
327
|
+
dbQuery[logical].whereNot(selectionRaw, 'like', `%${compareValue}%`);
|
|
328
|
+
}
|
|
329
|
+
if (operator === '_icontains') {
|
|
330
|
+
dbQuery[logical].whereRaw(`LOWER(??) LIKE ?`, [selectionRaw, `%${compareValue.toLowerCase()}%`]);
|
|
331
|
+
}
|
|
332
|
+
if (operator === '_nicontains') {
|
|
333
|
+
dbQuery[logical].whereRaw(`LOWER(??) NOT LIKE ?`, [selectionRaw, `%${compareValue.toLowerCase()}%`]);
|
|
334
|
+
}
|
|
335
|
+
if (operator === '_starts_with') {
|
|
336
|
+
dbQuery[logical].where(key, 'like', `${compareValue}%`);
|
|
337
|
+
}
|
|
338
|
+
if (operator === '_nstarts_with') {
|
|
339
|
+
dbQuery[logical].whereNot(key, 'like', `${compareValue}%`);
|
|
340
|
+
}
|
|
341
|
+
if (operator === '_istarts_with') {
|
|
342
|
+
dbQuery[logical].whereRaw(`LOWER(??) LIKE ?`, [selectionRaw, `${compareValue.toLowerCase()}%`]);
|
|
343
|
+
}
|
|
344
|
+
if (operator === '_nistarts_with') {
|
|
345
|
+
dbQuery[logical].whereRaw(`LOWER(??) NOT LIKE ?`, [selectionRaw, `${compareValue.toLowerCase()}%`]);
|
|
346
|
+
}
|
|
347
|
+
if (operator === '_ends_with') {
|
|
348
|
+
dbQuery[logical].where(key, 'like', `%${compareValue}`);
|
|
349
|
+
}
|
|
350
|
+
if (operator === '_nends_with') {
|
|
351
|
+
dbQuery[logical].whereNot(key, 'like', `%${compareValue}`);
|
|
352
|
+
}
|
|
353
|
+
if (operator === '_iends_with') {
|
|
354
|
+
dbQuery[logical].whereRaw(`LOWER(??) LIKE ?`, [selectionRaw, `%${compareValue.toLowerCase()}`]);
|
|
355
|
+
}
|
|
356
|
+
if (operator === '_niends_with') {
|
|
357
|
+
dbQuery[logical].whereRaw(`LOWER(??) NOT LIKE ?`, [selectionRaw, `%${compareValue.toLowerCase()}`]);
|
|
358
|
+
}
|
|
359
|
+
if (operator === '_gt') {
|
|
360
|
+
dbQuery[logical].where(selectionRaw, '>', compareValue);
|
|
361
|
+
}
|
|
362
|
+
if (operator === '_gte') {
|
|
363
|
+
dbQuery[logical].where(selectionRaw, '>=', compareValue);
|
|
364
|
+
}
|
|
365
|
+
if (operator === '_lt') {
|
|
366
|
+
dbQuery[logical].where(selectionRaw, '<', compareValue);
|
|
367
|
+
}
|
|
368
|
+
if (operator === '_lte') {
|
|
369
|
+
dbQuery[logical].where(selectionRaw, '<=', compareValue);
|
|
370
|
+
}
|
|
371
|
+
if (operator === '_in') {
|
|
372
|
+
let value = compareValue;
|
|
373
|
+
if (typeof value === 'string')
|
|
374
|
+
value = value.split(',');
|
|
375
|
+
dbQuery[logical].whereIn(selectionRaw, value);
|
|
376
|
+
}
|
|
377
|
+
if (operator === '_nin') {
|
|
378
|
+
let value = compareValue;
|
|
379
|
+
if (typeof value === 'string')
|
|
380
|
+
value = value.split(',');
|
|
381
|
+
dbQuery[logical].whereNotIn(selectionRaw, value);
|
|
382
|
+
}
|
|
383
|
+
if (operator === '_between') {
|
|
384
|
+
if (compareValue.length !== 2)
|
|
385
|
+
return;
|
|
386
|
+
let value = compareValue;
|
|
387
|
+
if (typeof value === 'string')
|
|
388
|
+
value = value.split(',');
|
|
389
|
+
dbQuery[logical].whereBetween(selectionRaw, value);
|
|
390
|
+
}
|
|
391
|
+
if (operator === '_nbetween') {
|
|
392
|
+
if (compareValue.length !== 2)
|
|
393
|
+
return;
|
|
394
|
+
let value = compareValue;
|
|
395
|
+
if (typeof value === 'string')
|
|
396
|
+
value = value.split(',');
|
|
397
|
+
dbQuery[logical].whereNotBetween(selectionRaw, value);
|
|
398
|
+
}
|
|
399
|
+
if (operator == '_intersects') {
|
|
400
|
+
dbQuery[logical].whereRaw(helpers.st.intersects(key, compareValue));
|
|
401
|
+
}
|
|
402
|
+
if (operator == '_nintersects') {
|
|
403
|
+
dbQuery[logical].whereRaw(helpers.st.nintersects(key, compareValue));
|
|
404
|
+
}
|
|
405
|
+
if (operator == '_intersects_bbox') {
|
|
406
|
+
dbQuery[logical].whereRaw(helpers.st.intersects_bbox(key, compareValue));
|
|
407
|
+
}
|
|
408
|
+
if (operator == '_nintersects_bbox') {
|
|
409
|
+
dbQuery[logical].whereRaw(helpers.st.nintersects_bbox(key, compareValue));
|
|
311
410
|
}
|
|
312
411
|
}
|
|
313
412
|
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.constructFlowTree = void 0;
|
|
4
|
+
const lodash_1 = require("lodash");
|
|
5
|
+
function constructFlowTree(flow) {
|
|
6
|
+
var _a;
|
|
7
|
+
const rootOperation = (_a = flow.operations.find((operation) => operation.id === flow.operation)) !== null && _a !== void 0 ? _a : null;
|
|
8
|
+
const operationTree = constructOperationTree(rootOperation, flow.operations);
|
|
9
|
+
const flowTree = {
|
|
10
|
+
...(0, lodash_1.omit)(flow, 'operations'),
|
|
11
|
+
operation: operationTree,
|
|
12
|
+
};
|
|
13
|
+
return flowTree;
|
|
14
|
+
}
|
|
15
|
+
exports.constructFlowTree = constructFlowTree;
|
|
16
|
+
function constructOperationTree(root, operations) {
|
|
17
|
+
if (root === null) {
|
|
18
|
+
return null;
|
|
19
|
+
}
|
|
20
|
+
const resolveOperation = root.resolve !== null ? operations.find((operation) => operation.id === root.resolve) : null;
|
|
21
|
+
const rejectOperation = root.reject !== null ? operations.find((operation) => operation.id === root.reject) : null;
|
|
22
|
+
if (resolveOperation === undefined || rejectOperation === undefined) {
|
|
23
|
+
throw new Error('Undefined reference in operations');
|
|
24
|
+
}
|
|
25
|
+
const operationTree = {
|
|
26
|
+
...(0, lodash_1.omit)(root, 'flow'),
|
|
27
|
+
resolve: constructOperationTree(resolveOperation, operations),
|
|
28
|
+
reject: constructOperationTree(rejectOperation, operations),
|
|
29
|
+
};
|
|
30
|
+
return operationTree;
|
|
31
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { Accountability, SchemaOverview } from '@directus/shared/types';
|
|
2
|
+
import { Knex } from 'knex';
|
|
3
|
+
export declare function getAccountabilityForRole(role: null | string, context: {
|
|
4
|
+
accountability: null | Accountability;
|
|
5
|
+
schema: SchemaOverview;
|
|
6
|
+
database: Knex;
|
|
7
|
+
}): Promise<Accountability>;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getAccountabilityForRole = void 0;
|
|
4
|
+
const get_permissions_1 = require("./get-permissions");
|
|
5
|
+
const exceptions_1 = require("../exceptions");
|
|
6
|
+
async function getAccountabilityForRole(role, context) {
|
|
7
|
+
let generatedAccountability = context.accountability;
|
|
8
|
+
if (role === null) {
|
|
9
|
+
generatedAccountability = {
|
|
10
|
+
role: null,
|
|
11
|
+
user: null,
|
|
12
|
+
admin: false,
|
|
13
|
+
app: false,
|
|
14
|
+
};
|
|
15
|
+
generatedAccountability.permissions = await (0, get_permissions_1.getPermissions)(generatedAccountability, context.schema);
|
|
16
|
+
}
|
|
17
|
+
else {
|
|
18
|
+
const roleInfo = await context.database
|
|
19
|
+
.select(['app_access', 'admin_access'])
|
|
20
|
+
.from('directus_roles')
|
|
21
|
+
.where({ id: role })
|
|
22
|
+
.first();
|
|
23
|
+
if (!roleInfo) {
|
|
24
|
+
throw new exceptions_1.InvalidConfigException(`Configured role "${role}" isn't a valid role ID or doesn't exist.`);
|
|
25
|
+
}
|
|
26
|
+
generatedAccountability = {
|
|
27
|
+
role,
|
|
28
|
+
user: null,
|
|
29
|
+
admin: roleInfo.admin_access === 1 || roleInfo.admin_access === '1' || roleInfo.admin_access === true,
|
|
30
|
+
app: roleInfo.app_access === 1 || roleInfo.app_access === '1' || roleInfo.app_access === true,
|
|
31
|
+
};
|
|
32
|
+
generatedAccountability.permissions = await (0, get_permissions_1.getPermissions)(generatedAccountability, context.schema);
|
|
33
|
+
}
|
|
34
|
+
return generatedAccountability;
|
|
35
|
+
}
|
|
36
|
+
exports.getAccountabilityForRole = getAccountabilityForRole;
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.optionToString = exports.optionToObject = exports.applyOperationOptions = void 0;
|
|
4
|
+
const micromustache_1 = require("micromustache");
|
|
5
|
+
const parse_json_1 = require("./parse-json");
|
|
6
|
+
function resolveFn(path, scope) {
|
|
7
|
+
if (!scope)
|
|
8
|
+
return undefined;
|
|
9
|
+
const value = (0, micromustache_1.get)(scope, path);
|
|
10
|
+
return typeof value === 'object' ? JSON.stringify(value) : value;
|
|
11
|
+
}
|
|
12
|
+
function renderMustache(item, scope) {
|
|
13
|
+
if (typeof item === 'string') {
|
|
14
|
+
return (0, micromustache_1.renderFn)(item, resolveFn, scope, { explicit: true });
|
|
15
|
+
}
|
|
16
|
+
else if (Array.isArray(item)) {
|
|
17
|
+
return item.map((element) => renderMustache(element, scope));
|
|
18
|
+
}
|
|
19
|
+
else if (typeof item === 'object' && item !== null) {
|
|
20
|
+
return Object.fromEntries(Object.entries(item).map(([key, value]) => [key, renderMustache(value, scope)]));
|
|
21
|
+
}
|
|
22
|
+
else {
|
|
23
|
+
return item;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
function applyOperationOptions(options, data) {
|
|
27
|
+
return Object.fromEntries(Object.entries(options).map(([key, value]) => {
|
|
28
|
+
if (typeof value === 'string') {
|
|
29
|
+
const single = value.match(/^\{\{\s*([^}\s]+)\s*\}\}$/);
|
|
30
|
+
if (single !== null) {
|
|
31
|
+
return [key, (0, micromustache_1.get)(data, single[1])];
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
return [key, renderMustache(value, data)];
|
|
35
|
+
}));
|
|
36
|
+
}
|
|
37
|
+
exports.applyOperationOptions = applyOperationOptions;
|
|
38
|
+
function optionToObject(option) {
|
|
39
|
+
return typeof option === 'string' ? (0, parse_json_1.parseJSON)(option) : option;
|
|
40
|
+
}
|
|
41
|
+
exports.optionToObject = optionToObject;
|
|
42
|
+
function optionToString(option) {
|
|
43
|
+
return typeof option === 'object' ? JSON.stringify(option) : String(option);
|
|
44
|
+
}
|
|
45
|
+
exports.optionToString = optionToString;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { SchemaOverview } from '@directus/shared/types';
|
|
2
|
+
import { PrimaryKey } from '../types';
|
|
3
|
+
/**
|
|
4
|
+
* Validate keys based on its type
|
|
5
|
+
*/
|
|
6
|
+
export declare function validateKeys(schema: SchemaOverview, collection: string, keyField: string, keys: PrimaryKey | PrimaryKey[]): void;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.validateKeys = void 0;
|
|
7
|
+
const exceptions_1 = require("../exceptions");
|
|
8
|
+
const uuid_validate_1 = __importDefault(require("uuid-validate"));
|
|
9
|
+
/**
|
|
10
|
+
* Validate keys based on its type
|
|
11
|
+
*/
|
|
12
|
+
function validateKeys(schema, collection, keyField, keys) {
|
|
13
|
+
if (Array.isArray(keys)) {
|
|
14
|
+
for (const key of keys) {
|
|
15
|
+
validateKeys(schema, collection, keyField, key);
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
else {
|
|
19
|
+
const primaryKeyFieldType = schema.collections[collection].fields[keyField].type;
|
|
20
|
+
if (primaryKeyFieldType === 'uuid' && !(0, uuid_validate_1.default)(String(keys))) {
|
|
21
|
+
throw new exceptions_1.ForbiddenException();
|
|
22
|
+
}
|
|
23
|
+
else if (primaryKeyFieldType === 'integer' && !Number.isInteger(Number(keys))) {
|
|
24
|
+
throw new exceptions_1.ForbiddenException();
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
exports.validateKeys = validateKeys;
|
|
@@ -104,7 +104,7 @@ function validateFilterPrimitive(value, key) {
|
|
|
104
104
|
false) {
|
|
105
105
|
throw new exceptions_1.InvalidQueryException(`The filter value for "${key}" has to be a string, number, or boolean`);
|
|
106
106
|
}
|
|
107
|
-
if (typeof value === 'number' && (Number.isNaN(value) ||
|
|
107
|
+
if (typeof value === 'number' && (Number.isNaN(value) || value > Number.MAX_SAFE_INTEGER)) {
|
|
108
108
|
throw new exceptions_1.InvalidQueryException(`The filter value for "${key}" is not a valid number`);
|
|
109
109
|
}
|
|
110
110
|
if (typeof value === 'string' && value.length === 0) {
|
package/dist/webhooks.d.ts
CHANGED
package/dist/webhooks.js
CHANGED
|
@@ -3,16 +3,31 @@ 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
|
-
exports.unregister = exports.register = void 0;
|
|
6
|
+
exports.unregister = exports.register = exports.reload = exports.init = void 0;
|
|
7
7
|
const axios_1 = __importDefault(require("axios"));
|
|
8
8
|
const database_1 = __importDefault(require("./database"));
|
|
9
9
|
const emitter_1 = __importDefault(require("./emitter"));
|
|
10
10
|
const logger_1 = __importDefault(require("./logger"));
|
|
11
11
|
const services_1 = require("./services");
|
|
12
12
|
const get_schema_1 = require("./utils/get-schema");
|
|
13
|
+
const messenger_1 = require("./messenger");
|
|
13
14
|
let registered = [];
|
|
14
|
-
async function
|
|
15
|
+
async function init() {
|
|
16
|
+
await register();
|
|
17
|
+
const messenger = (0, messenger_1.getMessenger)();
|
|
18
|
+
messenger.subscribe('webhooks', (event) => {
|
|
19
|
+
if (event.type === 'reload') {
|
|
20
|
+
reload();
|
|
21
|
+
}
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
exports.init = init;
|
|
25
|
+
async function reload() {
|
|
15
26
|
unregister();
|
|
27
|
+
await register();
|
|
28
|
+
}
|
|
29
|
+
exports.reload = reload;
|
|
30
|
+
async function register() {
|
|
16
31
|
const webhookService = new services_1.WebhooksService({ knex: (0, database_1.default)(), schema: await (0, get_schema_1.getSchema)() });
|
|
17
32
|
const webhooks = await webhookService.readByQuery({ filter: { status: { _eq: 'active' } } });
|
|
18
33
|
for (const webhook of webhooks) {
|