directus 9.12.1 → 9.12.2
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 +6 -0
- package/dist/constants.d.ts +1 -0
- package/dist/constants.js +5 -1
- package/dist/database/helpers/fn/dialects/oracle.d.ts +9 -9
- package/dist/database/helpers/fn/dialects/oracle.js +22 -16
- package/dist/database/helpers/fn/dialects/sqlite.d.ts +9 -9
- package/dist/database/helpers/fn/dialects/sqlite.js +46 -16
- package/dist/database/helpers/fn/types.d.ts +12 -9
- package/dist/database/system-data/fields/flows.yaml +1 -1
- package/dist/extensions.d.ts +2 -1
- package/dist/extensions.js +23 -19
- package/dist/flows.d.ts +5 -0
- package/dist/flows.js +51 -29
- package/dist/operations/request/index.d.ts +4 -1
- package/dist/operations/request/index.js +5 -1
- package/dist/services/flows.d.ts +0 -2
- package/dist/services/flows.js +13 -8
- package/dist/services/operations.d.ts +0 -2
- package/dist/services/operations.js +13 -8
- package/dist/services/users.js +5 -0
- package/dist/utils/apply-snapshot.js +3 -0
- package/dist/utils/get-column.js +1 -1
- package/dist/utils/job-queue.d.ts +9 -0
- package/dist/utils/job-queue.js +24 -0
- package/package.json +12 -12
package/dist/app.js
CHANGED
|
@@ -72,6 +72,7 @@ const extract_token_1 = __importDefault(require("./middleware/extract-token"));
|
|
|
72
72
|
const rate_limiter_1 = __importDefault(require("./middleware/rate-limiter"));
|
|
73
73
|
const sanitize_query_1 = __importDefault(require("./middleware/sanitize-query"));
|
|
74
74
|
const schema_1 = __importDefault(require("./middleware/schema"));
|
|
75
|
+
const constants_1 = require("./constants");
|
|
75
76
|
const track_1 = require("./utils/track");
|
|
76
77
|
const validate_env_1 = require("./utils/validate-env");
|
|
77
78
|
const validate_storage_1 = require("./utils/validate-storage");
|
|
@@ -157,6 +158,11 @@ async function createApp() {
|
|
|
157
158
|
next();
|
|
158
159
|
}
|
|
159
160
|
});
|
|
161
|
+
app.get('/robots.txt', (_, res) => {
|
|
162
|
+
res.set('Content-Type', 'text/plain');
|
|
163
|
+
res.status(200);
|
|
164
|
+
res.send(constants_1.ROBOTSTXT);
|
|
165
|
+
});
|
|
160
166
|
if (env_1.default.SERVE_APP) {
|
|
161
167
|
const adminPath = require.resolve('@directus/app');
|
|
162
168
|
const adminUrl = new url_1.Url(env_1.default.PUBLIC_URL).addPath('admin');
|
package/dist/constants.d.ts
CHANGED
package/dist/constants.js
CHANGED
|
@@ -4,7 +4,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
4
4
|
};
|
|
5
5
|
var _a;
|
|
6
6
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
-
exports.COOKIE_OPTIONS = exports.UUID_REGEX = exports.COLUMN_TRANSFORMS = exports.DEFAULT_AUTH_PROVIDER = exports.ALIAS_TYPES = exports.FILTER_VARIABLES = exports.ASSET_TRANSFORM_QUERY_KEYS = exports.SYSTEM_ASSET_ALLOW_LIST = void 0;
|
|
7
|
+
exports.ROBOTSTXT = exports.COOKIE_OPTIONS = exports.UUID_REGEX = exports.COLUMN_TRANSFORMS = exports.DEFAULT_AUTH_PROVIDER = exports.ALIAS_TYPES = exports.FILTER_VARIABLES = exports.ASSET_TRANSFORM_QUERY_KEYS = exports.SYSTEM_ASSET_ALLOW_LIST = void 0;
|
|
8
8
|
const env_1 = __importDefault(require("./env"));
|
|
9
9
|
const ms_1 = __importDefault(require("ms"));
|
|
10
10
|
exports.SYSTEM_ASSET_ALLOW_LIST = [
|
|
@@ -55,3 +55,7 @@ exports.COOKIE_OPTIONS = {
|
|
|
55
55
|
secure: (_a = env_1.default.REFRESH_TOKEN_COOKIE_SECURE) !== null && _a !== void 0 ? _a : false,
|
|
56
56
|
sameSite: env_1.default.REFRESH_TOKEN_COOKIE_SAME_SITE || 'strict',
|
|
57
57
|
};
|
|
58
|
+
exports.ROBOTSTXT = `
|
|
59
|
+
User-agent: *
|
|
60
|
+
Disallow: /
|
|
61
|
+
`.trim();
|
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
import { FnHelper } from '../types';
|
|
1
|
+
import { FnHelper, FnHelperOptions } from '../types';
|
|
2
2
|
import { Knex } from 'knex';
|
|
3
3
|
export declare class FnHelperOracle extends FnHelper {
|
|
4
|
-
year(table: string, column: string): Knex.Raw;
|
|
5
|
-
month(table: string, column: string): Knex.Raw;
|
|
6
|
-
week(table: string, column: string): Knex.Raw;
|
|
7
|
-
day(table: string, column: string): Knex.Raw;
|
|
8
|
-
weekday(table: string, column: string): Knex.Raw;
|
|
9
|
-
hour(table: string, column: string): Knex.Raw;
|
|
10
|
-
minute(table: string, column: string): Knex.Raw;
|
|
11
|
-
second(table: string, column: string): Knex.Raw;
|
|
4
|
+
year(table: string, column: string, options: FnHelperOptions): Knex.Raw;
|
|
5
|
+
month(table: string, column: string, options: FnHelperOptions): Knex.Raw;
|
|
6
|
+
week(table: string, column: string, options: FnHelperOptions): Knex.Raw;
|
|
7
|
+
day(table: string, column: string, options: FnHelperOptions): Knex.Raw;
|
|
8
|
+
weekday(table: string, column: string, options: FnHelperOptions): Knex.Raw;
|
|
9
|
+
hour(table: string, column: string, options: FnHelperOptions): Knex.Raw;
|
|
10
|
+
minute(table: string, column: string, options: FnHelperOptions): Knex.Raw;
|
|
11
|
+
second(table: string, column: string, options: FnHelperOptions): Knex.Raw;
|
|
12
12
|
count(table: string, column: string): Knex.Raw<any>;
|
|
13
13
|
}
|
|
@@ -2,30 +2,36 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.FnHelperOracle = void 0;
|
|
4
4
|
const types_1 = require("../types");
|
|
5
|
+
const parseLocaltime = (columnType) => {
|
|
6
|
+
if (columnType === 'timestamp') {
|
|
7
|
+
return ` AT TIME ZONE 'UTC'`;
|
|
8
|
+
}
|
|
9
|
+
return '';
|
|
10
|
+
};
|
|
5
11
|
class FnHelperOracle extends types_1.FnHelper {
|
|
6
|
-
year(table, column) {
|
|
7
|
-
return this.knex.raw(
|
|
12
|
+
year(table, column, options) {
|
|
13
|
+
return this.knex.raw(`TO_CHAR(??.??${parseLocaltime(options === null || options === void 0 ? void 0 : options.type)}, 'IYYY')`, [table, column]);
|
|
8
14
|
}
|
|
9
|
-
month(table, column) {
|
|
10
|
-
return this.knex.raw(
|
|
15
|
+
month(table, column, options) {
|
|
16
|
+
return this.knex.raw(`TO_CHAR(??.??${parseLocaltime(options === null || options === void 0 ? void 0 : options.type)}, 'MM')`, [table, column]);
|
|
11
17
|
}
|
|
12
|
-
week(table, column) {
|
|
13
|
-
return this.knex.raw(
|
|
18
|
+
week(table, column, options) {
|
|
19
|
+
return this.knex.raw(`TO_CHAR(??.??${parseLocaltime(options === null || options === void 0 ? void 0 : options.type)}, 'IW')`, [table, column]);
|
|
14
20
|
}
|
|
15
|
-
day(table, column) {
|
|
16
|
-
return this.knex.raw(
|
|
21
|
+
day(table, column, options) {
|
|
22
|
+
return this.knex.raw(`TO_CHAR(??.??${parseLocaltime(options === null || options === void 0 ? void 0 : options.type)}, 'DD')`, [table, column]);
|
|
17
23
|
}
|
|
18
|
-
weekday(table, column) {
|
|
19
|
-
return this.knex.raw(
|
|
24
|
+
weekday(table, column, options) {
|
|
25
|
+
return this.knex.raw(`TO_CHAR(??.??${parseLocaltime(options === null || options === void 0 ? void 0 : options.type)}, 'D')`, [table, column]);
|
|
20
26
|
}
|
|
21
|
-
hour(table, column) {
|
|
22
|
-
return this.knex.raw(
|
|
27
|
+
hour(table, column, options) {
|
|
28
|
+
return this.knex.raw(`TO_CHAR(??.??${parseLocaltime(options === null || options === void 0 ? void 0 : options.type)}, 'HH24')`, [table, column]);
|
|
23
29
|
}
|
|
24
|
-
minute(table, column) {
|
|
25
|
-
return this.knex.raw(
|
|
30
|
+
minute(table, column, options) {
|
|
31
|
+
return this.knex.raw(`TO_CHAR(??.??${parseLocaltime(options === null || options === void 0 ? void 0 : options.type)}, 'MI')`, [table, column]);
|
|
26
32
|
}
|
|
27
|
-
second(table, column) {
|
|
28
|
-
return this.knex.raw(
|
|
33
|
+
second(table, column, options) {
|
|
34
|
+
return this.knex.raw(`TO_CHAR(??.??${parseLocaltime(options === null || options === void 0 ? void 0 : options.type)}, 'SS')`, [table, column]);
|
|
29
35
|
}
|
|
30
36
|
count(table, column) {
|
|
31
37
|
var _a, _b, _c, _d, _e;
|
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
import { FnHelper } from '../types';
|
|
1
|
+
import { FnHelper, FnHelperOptions } from '../types';
|
|
2
2
|
import { Knex } from 'knex';
|
|
3
3
|
export declare class FnHelperSQLite extends FnHelper {
|
|
4
|
-
year(table: string, column: string): Knex.Raw;
|
|
5
|
-
month(table: string, column: string): Knex.Raw;
|
|
6
|
-
week(table: string, column: string): Knex.Raw;
|
|
7
|
-
day(table: string, column: string): Knex.Raw;
|
|
8
|
-
weekday(table: string, column: string): Knex.Raw;
|
|
9
|
-
hour(table: string, column: string): Knex.Raw;
|
|
10
|
-
minute(table: string, column: string): Knex.Raw;
|
|
11
|
-
second(table: string, column: string): Knex.Raw;
|
|
4
|
+
year(table: string, column: string, options?: FnHelperOptions): Knex.Raw;
|
|
5
|
+
month(table: string, column: string, options?: FnHelperOptions): Knex.Raw;
|
|
6
|
+
week(table: string, column: string, options?: FnHelperOptions): Knex.Raw;
|
|
7
|
+
day(table: string, column: string, options?: FnHelperOptions): Knex.Raw;
|
|
8
|
+
weekday(table: string, column: string, options?: FnHelperOptions): Knex.Raw;
|
|
9
|
+
hour(table: string, column: string, options?: FnHelperOptions): Knex.Raw;
|
|
10
|
+
minute(table: string, column: string, options?: FnHelperOptions): Knex.Raw;
|
|
11
|
+
second(table: string, column: string, options?: FnHelperOptions): Knex.Raw;
|
|
12
12
|
count(table: string, column: string): Knex.Raw<any>;
|
|
13
13
|
}
|
|
@@ -2,30 +2,60 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.FnHelperSQLite = void 0;
|
|
4
4
|
const types_1 = require("../types");
|
|
5
|
+
const parseLocaltime = (columnType) => {
|
|
6
|
+
if (columnType === 'timestamp') {
|
|
7
|
+
return '';
|
|
8
|
+
}
|
|
9
|
+
return `, 'localtime'`;
|
|
10
|
+
};
|
|
5
11
|
class FnHelperSQLite extends types_1.FnHelper {
|
|
6
|
-
year(table, column) {
|
|
7
|
-
return this.knex.raw(
|
|
12
|
+
year(table, column, options) {
|
|
13
|
+
return this.knex.raw(`CAST(strftime('%Y', ??.?? / 1000, 'unixepoch'${parseLocaltime(options === null || options === void 0 ? void 0 : options.type)}) AS INTEGER)`, [
|
|
14
|
+
table,
|
|
15
|
+
column,
|
|
16
|
+
]);
|
|
8
17
|
}
|
|
9
|
-
month(table, column) {
|
|
10
|
-
return this.knex.raw(
|
|
18
|
+
month(table, column, options) {
|
|
19
|
+
return this.knex.raw(`CAST(strftime('%m', ??.?? / 1000, 'unixepoch'${parseLocaltime(options === null || options === void 0 ? void 0 : options.type)}) AS INTEGER)`, [
|
|
20
|
+
table,
|
|
21
|
+
column,
|
|
22
|
+
]);
|
|
11
23
|
}
|
|
12
|
-
week(table, column) {
|
|
13
|
-
return this.knex.raw(
|
|
24
|
+
week(table, column, options) {
|
|
25
|
+
return this.knex.raw(`CAST(strftime('%W', ??.?? / 1000, 'unixepoch'${parseLocaltime(options === null || options === void 0 ? void 0 : options.type)}) AS INTEGER)`, [
|
|
26
|
+
table,
|
|
27
|
+
column,
|
|
28
|
+
]);
|
|
14
29
|
}
|
|
15
|
-
day(table, column) {
|
|
16
|
-
return this.knex.raw(
|
|
30
|
+
day(table, column, options) {
|
|
31
|
+
return this.knex.raw(`CAST(strftime('%d', ??.?? / 1000, 'unixepoch'${parseLocaltime(options === null || options === void 0 ? void 0 : options.type)}) AS INTEGER)`, [
|
|
32
|
+
table,
|
|
33
|
+
column,
|
|
34
|
+
]);
|
|
17
35
|
}
|
|
18
|
-
weekday(table, column) {
|
|
19
|
-
return this.knex.raw(
|
|
36
|
+
weekday(table, column, options) {
|
|
37
|
+
return this.knex.raw(`CAST(strftime('%w', ??.?? / 1000, 'unixepoch'${parseLocaltime(options === null || options === void 0 ? void 0 : options.type)}) AS INTEGER)`, [
|
|
38
|
+
table,
|
|
39
|
+
column,
|
|
40
|
+
]);
|
|
20
41
|
}
|
|
21
|
-
hour(table, column) {
|
|
22
|
-
return this.knex.raw(
|
|
42
|
+
hour(table, column, options) {
|
|
43
|
+
return this.knex.raw(`CAST(strftime('%H', ??.?? / 1000, 'unixepoch'${parseLocaltime(options === null || options === void 0 ? void 0 : options.type)}) AS INTEGER)`, [
|
|
44
|
+
table,
|
|
45
|
+
column,
|
|
46
|
+
]);
|
|
23
47
|
}
|
|
24
|
-
minute(table, column) {
|
|
25
|
-
return this.knex.raw(
|
|
48
|
+
minute(table, column, options) {
|
|
49
|
+
return this.knex.raw(`CAST(strftime('%M', ??.?? / 1000, 'unixepoch'${parseLocaltime(options === null || options === void 0 ? void 0 : options.type)}) AS INTEGER)`, [
|
|
50
|
+
table,
|
|
51
|
+
column,
|
|
52
|
+
]);
|
|
26
53
|
}
|
|
27
|
-
second(table, column) {
|
|
28
|
-
return this.knex.raw(
|
|
54
|
+
second(table, column, options) {
|
|
55
|
+
return this.knex.raw(`CAST(strftime('%S', ??.?? / 1000, 'unixepoch'${parseLocaltime(options === null || options === void 0 ? void 0 : options.type)}) AS INTEGER)`, [
|
|
56
|
+
table,
|
|
57
|
+
column,
|
|
58
|
+
]);
|
|
29
59
|
}
|
|
30
60
|
count(table, column) {
|
|
31
61
|
var _a, _b, _c, _d, _e;
|
|
@@ -1,18 +1,21 @@
|
|
|
1
1
|
import { SchemaOverview } from '@directus/shared/types';
|
|
2
2
|
import { Knex } from 'knex';
|
|
3
3
|
import { DatabaseHelper } from '../types';
|
|
4
|
+
export declare type FnHelperOptions = {
|
|
5
|
+
type?: string;
|
|
6
|
+
};
|
|
4
7
|
export declare abstract class FnHelper extends DatabaseHelper {
|
|
5
8
|
protected knex: Knex;
|
|
6
9
|
protected schema: SchemaOverview;
|
|
7
10
|
constructor(knex: Knex, schema: SchemaOverview);
|
|
8
|
-
abstract year(table: string, column: string): Knex.Raw;
|
|
9
|
-
abstract month(table: string, column: string): Knex.Raw;
|
|
10
|
-
abstract week(table: string, column: string): Knex.Raw;
|
|
11
|
-
abstract day(table: string, column: string): Knex.Raw;
|
|
12
|
-
abstract weekday(table: string, column: string): Knex.Raw;
|
|
13
|
-
abstract hour(table: string, column: string): Knex.Raw;
|
|
14
|
-
abstract minute(table: string, column: string): Knex.Raw;
|
|
15
|
-
abstract second(table: string, column: string): Knex.Raw;
|
|
16
|
-
abstract count(table: string, column: string): Knex.Raw;
|
|
11
|
+
abstract year(table: string, column: string, options?: FnHelperOptions): Knex.Raw;
|
|
12
|
+
abstract month(table: string, column: string, options?: FnHelperOptions): Knex.Raw;
|
|
13
|
+
abstract week(table: string, column: string, options?: FnHelperOptions): Knex.Raw;
|
|
14
|
+
abstract day(table: string, column: string, options?: FnHelperOptions): Knex.Raw;
|
|
15
|
+
abstract weekday(table: string, column: string, options?: FnHelperOptions): Knex.Raw;
|
|
16
|
+
abstract hour(table: string, column: string, options?: FnHelperOptions): Knex.Raw;
|
|
17
|
+
abstract minute(table: string, column: string, options?: FnHelperOptions): Knex.Raw;
|
|
18
|
+
abstract second(table: string, column: string, options?: FnHelperOptions): Knex.Raw;
|
|
19
|
+
abstract count(table: string, column: string, options?: FnHelperOptions): Knex.Raw;
|
|
17
20
|
protected _relationalCount(table: string, column: string): Knex.Raw;
|
|
18
21
|
}
|
package/dist/extensions.d.ts
CHANGED
|
@@ -13,10 +13,11 @@ declare class ExtensionManager {
|
|
|
13
13
|
private apiExtensions;
|
|
14
14
|
private apiEmitter;
|
|
15
15
|
private endpointRouter;
|
|
16
|
+
private reloadQueue;
|
|
16
17
|
private watcher;
|
|
17
18
|
constructor();
|
|
18
19
|
initialize(options?: Partial<Options>): Promise<void>;
|
|
19
|
-
reload():
|
|
20
|
+
reload(): void;
|
|
20
21
|
getExtensionsList(type?: ExtensionType): string[];
|
|
21
22
|
getAppExtensions(type: AppExtensionType): string | undefined;
|
|
22
23
|
getEndpointRouter(): Router;
|
package/dist/extensions.js
CHANGED
|
@@ -47,6 +47,7 @@ const chokidar_1 = __importDefault(require("chokidar"));
|
|
|
47
47
|
const utils_1 = require("@directus/shared/utils");
|
|
48
48
|
const flows_1 = require("./flows");
|
|
49
49
|
const globby_1 = __importDefault(require("globby"));
|
|
50
|
+
const job_queue_1 = require("./utils/job-queue");
|
|
50
51
|
let extensionManager;
|
|
51
52
|
function getExtensionManager() {
|
|
52
53
|
if (extensionManager) {
|
|
@@ -70,6 +71,7 @@ class ExtensionManager {
|
|
|
70
71
|
this.options = defaultOptions;
|
|
71
72
|
this.apiEmitter = new emitter_1.Emitter();
|
|
72
73
|
this.endpointRouter = (0, express_1.Router)();
|
|
74
|
+
this.reloadQueue = new job_queue_1.JobQueue();
|
|
73
75
|
}
|
|
74
76
|
async initialize(options = {}) {
|
|
75
77
|
this.options = {
|
|
@@ -86,27 +88,29 @@ class ExtensionManager {
|
|
|
86
88
|
}
|
|
87
89
|
}
|
|
88
90
|
}
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
91
|
+
reload() {
|
|
92
|
+
this.reloadQueue.enqueue(async () => {
|
|
93
|
+
if (this.isLoaded) {
|
|
94
|
+
logger_1.default.info('Reloading extensions');
|
|
95
|
+
const prevExtensions = (0, lodash_1.clone)(this.extensions);
|
|
96
|
+
await this.unload();
|
|
97
|
+
await this.load();
|
|
98
|
+
const added = this.extensions.filter((extension) => !prevExtensions.some((prevExtension) => extension.path === prevExtension.path));
|
|
99
|
+
const removed = prevExtensions.filter((prevExtension) => !this.extensions.some((extension) => prevExtension.path === extension.path));
|
|
100
|
+
this.updateWatchedExtensions(added, removed);
|
|
101
|
+
const addedExtensions = added.map((extension) => extension.name);
|
|
102
|
+
const removedExtensions = removed.map((extension) => extension.name);
|
|
103
|
+
if (addedExtensions.length > 0) {
|
|
104
|
+
logger_1.default.info(`Added extensions: ${addedExtensions.join(', ')}`);
|
|
105
|
+
}
|
|
106
|
+
if (removedExtensions.length > 0) {
|
|
107
|
+
logger_1.default.info(`Removed extensions: ${removedExtensions.join(', ')}`);
|
|
108
|
+
}
|
|
102
109
|
}
|
|
103
|
-
|
|
104
|
-
logger_1.default.
|
|
110
|
+
else {
|
|
111
|
+
logger_1.default.warn('Extensions have to be loaded before they can be reloaded');
|
|
105
112
|
}
|
|
106
|
-
}
|
|
107
|
-
else {
|
|
108
|
-
logger_1.default.warn('Extensions have to be loaded before they can be reloaded');
|
|
109
|
-
}
|
|
113
|
+
});
|
|
110
114
|
}
|
|
111
115
|
getExtensionsList(type) {
|
|
112
116
|
if (type === undefined) {
|
package/dist/flows.d.ts
CHANGED
|
@@ -1,16 +1,21 @@
|
|
|
1
1
|
import { OperationHandler } from '@directus/shared/types';
|
|
2
2
|
export declare function getFlowManager(): FlowManager;
|
|
3
3
|
declare class FlowManager {
|
|
4
|
+
private isLoaded;
|
|
4
5
|
private operations;
|
|
5
6
|
private triggerHandlers;
|
|
6
7
|
private operationFlowHandlers;
|
|
7
8
|
private webhookFlowHandlers;
|
|
9
|
+
private reloadQueue;
|
|
10
|
+
constructor();
|
|
8
11
|
initialize(): Promise<void>;
|
|
9
12
|
reload(): Promise<void>;
|
|
10
13
|
addOperation(id: string, operation: OperationHandler): void;
|
|
11
14
|
clearOperations(): void;
|
|
12
15
|
runOperationFlow(id: string, data: unknown, context: Record<string, unknown>): Promise<unknown>;
|
|
13
16
|
runWebhookFlow(id: string, data: unknown, context: Record<string, unknown>): Promise<unknown>;
|
|
17
|
+
private load;
|
|
18
|
+
private unload;
|
|
14
19
|
private executeFlow;
|
|
15
20
|
private executeOperation;
|
|
16
21
|
}
|
package/dist/flows.js
CHANGED
|
@@ -42,6 +42,7 @@ const lodash_1 = require("lodash");
|
|
|
42
42
|
const messenger_1 = require("./messenger");
|
|
43
43
|
const fast_redact_1 = __importDefault(require("fast-redact"));
|
|
44
44
|
const operation_options_1 = require("./utils/operation-options");
|
|
45
|
+
const job_queue_1 = require("./utils/job-queue");
|
|
45
46
|
let flowManager;
|
|
46
47
|
const redactLogs = (0, fast_redact_1.default)({
|
|
47
48
|
censor: '--redacted--',
|
|
@@ -61,12 +62,59 @@ const ACCOUNTABILITY_KEY = '$accountability';
|
|
|
61
62
|
const LAST_KEY = '$last';
|
|
62
63
|
class FlowManager {
|
|
63
64
|
constructor() {
|
|
65
|
+
this.isLoaded = false;
|
|
64
66
|
this.operations = {};
|
|
65
67
|
this.triggerHandlers = [];
|
|
66
68
|
this.operationFlowHandlers = {};
|
|
67
69
|
this.webhookFlowHandlers = {};
|
|
70
|
+
this.reloadQueue = new job_queue_1.JobQueue();
|
|
71
|
+
const messenger = (0, messenger_1.getMessenger)();
|
|
72
|
+
messenger.subscribe('flows', (event) => {
|
|
73
|
+
if (event.type === 'reload') {
|
|
74
|
+
this.reloadQueue.enqueue(async () => {
|
|
75
|
+
if (this.isLoaded) {
|
|
76
|
+
await this.unload();
|
|
77
|
+
await this.load();
|
|
78
|
+
}
|
|
79
|
+
else {
|
|
80
|
+
logger_1.default.warn('Flows have to be loaded before they can be reloaded');
|
|
81
|
+
}
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
});
|
|
68
85
|
}
|
|
69
86
|
async initialize() {
|
|
87
|
+
if (!this.isLoaded) {
|
|
88
|
+
await this.load();
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
async reload() {
|
|
92
|
+
const messenger = (0, messenger_1.getMessenger)();
|
|
93
|
+
messenger.publish('flows', { type: 'reload' });
|
|
94
|
+
}
|
|
95
|
+
addOperation(id, operation) {
|
|
96
|
+
this.operations[id] = operation;
|
|
97
|
+
}
|
|
98
|
+
clearOperations() {
|
|
99
|
+
this.operations = {};
|
|
100
|
+
}
|
|
101
|
+
async runOperationFlow(id, data, context) {
|
|
102
|
+
if (!(id in this.operationFlowHandlers)) {
|
|
103
|
+
logger_1.default.warn(`Couldn't find operation triggered flow with id "${id}"`);
|
|
104
|
+
return null;
|
|
105
|
+
}
|
|
106
|
+
const handler = this.operationFlowHandlers[id];
|
|
107
|
+
return handler(data, context);
|
|
108
|
+
}
|
|
109
|
+
async runWebhookFlow(id, data, context) {
|
|
110
|
+
if (!(id in this.webhookFlowHandlers)) {
|
|
111
|
+
logger_1.default.warn(`Couldn't find webhook or manual triggered flow with id "${id}"`);
|
|
112
|
+
throw new exceptions.ForbiddenException();
|
|
113
|
+
}
|
|
114
|
+
const handler = this.webhookFlowHandlers[id];
|
|
115
|
+
return handler(data, context);
|
|
116
|
+
}
|
|
117
|
+
async load() {
|
|
70
118
|
var _a, _b, _c, _d, _e, _f, _g;
|
|
71
119
|
const flowsService = new services_1.FlowsService({ knex: (0, database_1.default)(), schema: await (0, get_schema_1.getSchema)() });
|
|
72
120
|
const flows = await flowsService.readByQuery({
|
|
@@ -177,13 +225,9 @@ class FlowManager {
|
|
|
177
225
|
this.webhookFlowHandlers[`POST-${flow.id}`] = handler;
|
|
178
226
|
}
|
|
179
227
|
}
|
|
180
|
-
|
|
181
|
-
if (event.type === 'reload') {
|
|
182
|
-
this.reload();
|
|
183
|
-
}
|
|
184
|
-
});
|
|
228
|
+
this.isLoaded = true;
|
|
185
229
|
}
|
|
186
|
-
async
|
|
230
|
+
async unload() {
|
|
187
231
|
for (const trigger of this.triggerHandlers) {
|
|
188
232
|
trigger.events.forEach((event) => {
|
|
189
233
|
switch (event.type) {
|
|
@@ -202,29 +246,7 @@ class FlowManager {
|
|
|
202
246
|
this.triggerHandlers = [];
|
|
203
247
|
this.operationFlowHandlers = {};
|
|
204
248
|
this.webhookFlowHandlers = {};
|
|
205
|
-
|
|
206
|
-
}
|
|
207
|
-
addOperation(id, operation) {
|
|
208
|
-
this.operations[id] = operation;
|
|
209
|
-
}
|
|
210
|
-
clearOperations() {
|
|
211
|
-
this.operations = {};
|
|
212
|
-
}
|
|
213
|
-
async runOperationFlow(id, data, context) {
|
|
214
|
-
if (!(id in this.operationFlowHandlers)) {
|
|
215
|
-
logger_1.default.warn(`Couldn't find operation triggered flow with id "${id}"`);
|
|
216
|
-
return null;
|
|
217
|
-
}
|
|
218
|
-
const handler = this.operationFlowHandlers[id];
|
|
219
|
-
return handler(data, context);
|
|
220
|
-
}
|
|
221
|
-
async runWebhookFlow(id, data, context) {
|
|
222
|
-
if (!(id in this.webhookFlowHandlers)) {
|
|
223
|
-
logger_1.default.warn(`Couldn't find webhook or manual triggered flow with id "${id}"`);
|
|
224
|
-
throw new exceptions.ForbiddenException();
|
|
225
|
-
}
|
|
226
|
-
const handler = this.webhookFlowHandlers[id];
|
|
227
|
-
return handler(data, context);
|
|
249
|
+
this.isLoaded = false;
|
|
228
250
|
}
|
|
229
251
|
async executeFlow(flow, data = null, context = {}) {
|
|
230
252
|
var _a, _b, _c, _d, _e, _f;
|
|
@@ -3,7 +3,10 @@ declare type Options = {
|
|
|
3
3
|
url: string;
|
|
4
4
|
method: Method;
|
|
5
5
|
body: Record<string, any> | string | null;
|
|
6
|
-
headers
|
|
6
|
+
headers?: {
|
|
7
|
+
header: string;
|
|
8
|
+
value: string;
|
|
9
|
+
}[] | null;
|
|
7
10
|
};
|
|
8
11
|
declare const _default: import("@directus/shared/types").OperationApiConfig<Options>;
|
|
9
12
|
export default _default;
|
|
@@ -8,7 +8,11 @@ const axios_1 = __importDefault(require("axios"));
|
|
|
8
8
|
exports.default = (0, utils_1.defineOperationApi)({
|
|
9
9
|
id: 'request',
|
|
10
10
|
handler: async ({ url, method, body, headers }) => {
|
|
11
|
-
const
|
|
11
|
+
const customHeaders = headers === null || headers === void 0 ? void 0 : headers.reduce((acc, { header, value }) => {
|
|
12
|
+
acc[header] = value;
|
|
13
|
+
return acc;
|
|
14
|
+
}, {});
|
|
15
|
+
const result = await (0, axios_1.default)({ url, method, data: body, headers: customHeaders });
|
|
12
16
|
return { status: result.status, statusText: result.statusText, headers: result.headers, data: result.data };
|
|
13
17
|
},
|
|
14
18
|
});
|
package/dist/services/flows.d.ts
CHANGED
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
import { FlowRaw } from '@directus/shared/types';
|
|
2
|
-
import { Messenger } from '../messenger';
|
|
3
2
|
import { AbstractServiceOptions, Item, MutationOptions, PrimaryKey } from '../types';
|
|
4
3
|
import { ItemsService } from './items';
|
|
5
4
|
export declare class FlowsService extends ItemsService<FlowRaw> {
|
|
6
|
-
messenger: Messenger;
|
|
7
5
|
constructor(options: AbstractServiceOptions);
|
|
8
6
|
createOne(data: Partial<Item>, opts?: MutationOptions): Promise<PrimaryKey>;
|
|
9
7
|
createMany(data: Partial<Item>[], opts?: MutationOptions): Promise<PrimaryKey[]>;
|
package/dist/services/flows.js
CHANGED
|
@@ -1,41 +1,46 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.FlowsService = void 0;
|
|
4
|
-
const
|
|
4
|
+
const flows_1 = require("../flows");
|
|
5
5
|
const items_1 = require("./items");
|
|
6
6
|
class FlowsService extends items_1.ItemsService {
|
|
7
7
|
constructor(options) {
|
|
8
8
|
super('directus_flows', options);
|
|
9
|
-
this.messenger = (0, messenger_1.getMessenger)();
|
|
10
9
|
}
|
|
11
10
|
async createOne(data, opts) {
|
|
11
|
+
const flowManager = (0, flows_1.getFlowManager)();
|
|
12
12
|
const result = await super.createOne(data, opts);
|
|
13
|
-
|
|
13
|
+
await flowManager.reload();
|
|
14
14
|
return result;
|
|
15
15
|
}
|
|
16
16
|
async createMany(data, opts) {
|
|
17
|
+
const flowManager = (0, flows_1.getFlowManager)();
|
|
17
18
|
const result = await super.createMany(data, opts);
|
|
18
|
-
|
|
19
|
+
await flowManager.reload();
|
|
19
20
|
return result;
|
|
20
21
|
}
|
|
21
22
|
async updateOne(key, data, opts) {
|
|
23
|
+
const flowManager = (0, flows_1.getFlowManager)();
|
|
22
24
|
const result = await super.updateOne(key, data, opts);
|
|
23
|
-
|
|
25
|
+
await flowManager.reload();
|
|
24
26
|
return result;
|
|
25
27
|
}
|
|
26
28
|
async updateMany(keys, data, opts) {
|
|
29
|
+
const flowManager = (0, flows_1.getFlowManager)();
|
|
27
30
|
const result = await super.updateMany(keys, data, opts);
|
|
28
|
-
|
|
31
|
+
await flowManager.reload();
|
|
29
32
|
return result;
|
|
30
33
|
}
|
|
31
34
|
async deleteOne(key, opts) {
|
|
35
|
+
const flowManager = (0, flows_1.getFlowManager)();
|
|
32
36
|
const result = await super.deleteOne(key, opts);
|
|
33
|
-
|
|
37
|
+
await flowManager.reload();
|
|
34
38
|
return result;
|
|
35
39
|
}
|
|
36
40
|
async deleteMany(keys, opts) {
|
|
41
|
+
const flowManager = (0, flows_1.getFlowManager)();
|
|
37
42
|
const result = await super.deleteMany(keys, opts);
|
|
38
|
-
|
|
43
|
+
await flowManager.reload();
|
|
39
44
|
return result;
|
|
40
45
|
}
|
|
41
46
|
}
|
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
import { OperationRaw } from '@directus/shared/types';
|
|
2
|
-
import { Messenger } from '../messenger';
|
|
3
2
|
import { AbstractServiceOptions, Item, MutationOptions, PrimaryKey } from '../types';
|
|
4
3
|
import { ItemsService } from './items';
|
|
5
4
|
export declare class OperationsService extends ItemsService<OperationRaw> {
|
|
6
|
-
messenger: Messenger;
|
|
7
5
|
constructor(options: AbstractServiceOptions);
|
|
8
6
|
createOne(data: Partial<Item>, opts?: MutationOptions): Promise<PrimaryKey>;
|
|
9
7
|
createMany(data: Partial<Item>[], opts?: MutationOptions): Promise<PrimaryKey[]>;
|
|
@@ -1,41 +1,46 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.OperationsService = void 0;
|
|
4
|
-
const
|
|
4
|
+
const flows_1 = require("../flows");
|
|
5
5
|
const items_1 = require("./items");
|
|
6
6
|
class OperationsService extends items_1.ItemsService {
|
|
7
7
|
constructor(options) {
|
|
8
8
|
super('directus_operations', options);
|
|
9
|
-
this.messenger = (0, messenger_1.getMessenger)();
|
|
10
9
|
}
|
|
11
10
|
async createOne(data, opts) {
|
|
11
|
+
const flowManager = (0, flows_1.getFlowManager)();
|
|
12
12
|
const result = await super.createOne(data, opts);
|
|
13
|
-
|
|
13
|
+
await flowManager.reload();
|
|
14
14
|
return result;
|
|
15
15
|
}
|
|
16
16
|
async createMany(data, opts) {
|
|
17
|
+
const flowManager = (0, flows_1.getFlowManager)();
|
|
17
18
|
const result = await super.createMany(data, opts);
|
|
18
|
-
|
|
19
|
+
await flowManager.reload();
|
|
19
20
|
return result;
|
|
20
21
|
}
|
|
21
22
|
async updateOne(key, data, opts) {
|
|
23
|
+
const flowManager = (0, flows_1.getFlowManager)();
|
|
22
24
|
const result = await super.updateOne(key, data, opts);
|
|
23
|
-
|
|
25
|
+
await flowManager.reload();
|
|
24
26
|
return result;
|
|
25
27
|
}
|
|
26
28
|
async updateMany(keys, data, opts) {
|
|
29
|
+
const flowManager = (0, flows_1.getFlowManager)();
|
|
27
30
|
const result = await super.updateMany(keys, data, opts);
|
|
28
|
-
|
|
31
|
+
await flowManager.reload();
|
|
29
32
|
return result;
|
|
30
33
|
}
|
|
31
34
|
async deleteOne(key, opts) {
|
|
35
|
+
const flowManager = (0, flows_1.getFlowManager)();
|
|
32
36
|
const result = await super.deleteOne(key, opts);
|
|
33
|
-
|
|
37
|
+
await flowManager.reload();
|
|
34
38
|
return result;
|
|
35
39
|
}
|
|
36
40
|
async deleteMany(keys, opts) {
|
|
41
|
+
const flowManager = (0, flows_1.getFlowManager)();
|
|
37
42
|
const result = await super.deleteMany(keys, opts);
|
|
38
|
-
|
|
43
|
+
await flowManager.reload();
|
|
39
44
|
return result;
|
|
40
45
|
}
|
|
41
46
|
}
|
package/dist/services/users.js
CHANGED
|
@@ -305,6 +305,7 @@ class UsersService extends items_1.ItemsService {
|
|
|
305
305
|
await (0, stall_1.stall)(STALL_TIME, timeStart);
|
|
306
306
|
}
|
|
307
307
|
async resetPassword(token, password) {
|
|
308
|
+
var _a;
|
|
308
309
|
const { email, scope, hash } = jsonwebtoken_1.default.verify(token, env_1.default.SECRET, { issuer: 'directus' });
|
|
309
310
|
if (scope !== 'password-reset' || !hash)
|
|
310
311
|
throw new exceptions_2.ForbiddenException();
|
|
@@ -317,6 +318,10 @@ class UsersService extends items_1.ItemsService {
|
|
|
317
318
|
const service = new UsersService({
|
|
318
319
|
knex: this.knex,
|
|
319
320
|
schema: this.schema,
|
|
321
|
+
accountability: {
|
|
322
|
+
...((_a = this.accountability) !== null && _a !== void 0 ? _a : { role: null }),
|
|
323
|
+
admin: true, // We need to skip permissions checks for the update call below
|
|
324
|
+
},
|
|
320
325
|
});
|
|
321
326
|
await service.updateOne(user.id, { password, status: 'active' });
|
|
322
327
|
}
|
|
@@ -11,10 +11,12 @@ const services_1 = require("../services");
|
|
|
11
11
|
const get_schema_1 = require("./get-schema");
|
|
12
12
|
const get_snapshot_1 = require("./get-snapshot");
|
|
13
13
|
const get_snapshot_diff_1 = require("./get-snapshot-diff");
|
|
14
|
+
const cache_1 = require("../cache");
|
|
14
15
|
async function applySnapshot(snapshot, options) {
|
|
15
16
|
var _a, _b, _c, _d;
|
|
16
17
|
const database = (_a = options === null || options === void 0 ? void 0 : options.database) !== null && _a !== void 0 ? _a : (0, database_1.default)();
|
|
17
18
|
const schema = (_b = options === null || options === void 0 ? void 0 : options.schema) !== null && _b !== void 0 ? _b : (await (0, get_schema_1.getSchema)({ database }));
|
|
19
|
+
const { systemCache } = (0, cache_1.getCache)();
|
|
18
20
|
const current = (_c = options === null || options === void 0 ? void 0 : options.current) !== null && _c !== void 0 ? _c : (await (0, get_snapshot_1.getSnapshot)({ database, schema }));
|
|
19
21
|
const snapshotDiff = (_d = options === null || options === void 0 ? void 0 : options.diff) !== null && _d !== void 0 ? _d : (0, get_snapshot_diff_1.getSnapshotDiff)(current, snapshot);
|
|
20
22
|
await database.transaction(async (trx) => {
|
|
@@ -178,6 +180,7 @@ async function applySnapshot(snapshot, options) {
|
|
|
178
180
|
}
|
|
179
181
|
}
|
|
180
182
|
});
|
|
183
|
+
await (systemCache === null || systemCache === void 0 ? void 0 : systemCache.clear());
|
|
181
184
|
}
|
|
182
185
|
exports.applySnapshot = applySnapshot;
|
|
183
186
|
function isNestedMetaUpdate(diff) {
|
package/dist/utils/get-column.js
CHANGED
|
@@ -28,7 +28,7 @@ function getColumn(knex, table, column, alias = (0, apply_function_to_column_nam
|
|
|
28
28
|
if (allowedFunctions.includes(functionName) === false) {
|
|
29
29
|
throw new exceptions_1.InvalidQueryException(`Invalid function specified "${functionName}"`);
|
|
30
30
|
}
|
|
31
|
-
const result = fn[functionName](table, columnName);
|
|
31
|
+
const result = fn[functionName](table, columnName, { type });
|
|
32
32
|
if (alias) {
|
|
33
33
|
return knex.raw(result + ' AS ??', [alias]);
|
|
34
34
|
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.JobQueue = void 0;
|
|
4
|
+
class JobQueue {
|
|
5
|
+
constructor() {
|
|
6
|
+
this.running = false;
|
|
7
|
+
this.jobs = [];
|
|
8
|
+
}
|
|
9
|
+
enqueue(job) {
|
|
10
|
+
this.jobs.push(job);
|
|
11
|
+
if (!this.running) {
|
|
12
|
+
this.run();
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
async run() {
|
|
16
|
+
this.running = true;
|
|
17
|
+
while (this.jobs.length > 0) {
|
|
18
|
+
const job = this.jobs.shift();
|
|
19
|
+
await job();
|
|
20
|
+
}
|
|
21
|
+
this.running = false;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
exports.JobQueue = JobQueue;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "directus",
|
|
3
|
-
"version": "9.12.
|
|
3
|
+
"version": "9.12.2",
|
|
4
4
|
"license": "GPL-3.0-only",
|
|
5
5
|
"homepage": "https://github.com/directus/directus#readme",
|
|
6
6
|
"description": "Directus is a real-time API and App dashboard for managing SQL database content.",
|
|
@@ -77,16 +77,16 @@
|
|
|
77
77
|
],
|
|
78
78
|
"dependencies": {
|
|
79
79
|
"@aws-sdk/client-ses": "^3.40.0",
|
|
80
|
-
"@directus/app": "9.12.
|
|
81
|
-
"@directus/drive": "9.12.
|
|
82
|
-
"@directus/drive-azure": "9.12.
|
|
83
|
-
"@directus/drive-gcs": "9.12.
|
|
84
|
-
"@directus/drive-s3": "9.12.
|
|
85
|
-
"@directus/extensions-sdk": "9.12.
|
|
86
|
-
"@directus/format-title": "9.12.
|
|
87
|
-
"@directus/schema": "9.12.
|
|
88
|
-
"@directus/shared": "9.12.
|
|
89
|
-
"@directus/specs": "9.12.
|
|
80
|
+
"@directus/app": "9.12.2",
|
|
81
|
+
"@directus/drive": "9.12.2",
|
|
82
|
+
"@directus/drive-azure": "9.12.2",
|
|
83
|
+
"@directus/drive-gcs": "9.12.2",
|
|
84
|
+
"@directus/drive-s3": "9.12.2",
|
|
85
|
+
"@directus/extensions-sdk": "9.12.2",
|
|
86
|
+
"@directus/format-title": "9.12.2",
|
|
87
|
+
"@directus/schema": "9.12.2",
|
|
88
|
+
"@directus/shared": "9.12.2",
|
|
89
|
+
"@directus/specs": "9.12.2",
|
|
90
90
|
"@godaddy/terminus": "^4.9.0",
|
|
91
91
|
"@rollup/plugin-alias": "^3.1.9",
|
|
92
92
|
"@rollup/plugin-virtual": "^2.0.3",
|
|
@@ -173,7 +173,7 @@
|
|
|
173
173
|
"sqlite3": "^5.0.6",
|
|
174
174
|
"tedious": "^13.0.0"
|
|
175
175
|
},
|
|
176
|
-
"gitHead": "
|
|
176
|
+
"gitHead": "bce19abf6f52adc933ebc4f557e6959aa69d083e",
|
|
177
177
|
"devDependencies": {
|
|
178
178
|
"@types/async": "3.2.10",
|
|
179
179
|
"@types/body-parser": "1.19.2",
|