directus 9.3.0 → 9.4.3
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 +25 -4
- package/dist/auth/auth.d.ts +4 -6
- package/dist/auth/auth.js +5 -9
- package/dist/auth/drivers/ldap.d.ts +3 -3
- package/dist/auth/drivers/ldap.js +2 -3
- package/dist/auth/drivers/local.d.ts +2 -2
- package/dist/auth/drivers/local.js +7 -13
- package/dist/auth/drivers/oauth2.d.ts +3 -3
- package/dist/auth/drivers/oauth2.js +4 -4
- package/dist/auth/drivers/openid.d.ts +3 -3
- package/dist/auth/drivers/openid.js +4 -4
- package/dist/cache.js +1 -3
- package/dist/cli/commands/schema/apply.js +1 -1
- package/dist/cli/index.js +1 -1
- package/dist/constants.d.ts +8 -0
- package/dist/constants.js +16 -2
- package/dist/controllers/activity.js +2 -1
- package/dist/controllers/auth.js +5 -4
- package/dist/controllers/extensions.js +1 -1
- package/dist/controllers/shares.d.ts +2 -0
- package/dist/controllers/shares.js +212 -0
- package/dist/controllers/users.js +21 -9
- package/dist/database/index.js +3 -0
- package/dist/database/migrations/20211211A-add-shares.d.ts +3 -0
- package/dist/database/migrations/20211211A-add-shares.js +38 -0
- package/dist/database/migrations/20211230A-add-project-descriptor.d.ts +3 -0
- package/dist/database/migrations/20211230A-add-project-descriptor.js +15 -0
- package/dist/database/migrations/run.js +1 -1
- package/dist/database/run-ast.js +5 -5
- package/dist/database/system-data/app-access-permissions/app-access-permissions.yaml +0 -15
- package/dist/database/system-data/app-access-permissions/index.d.ts +1 -0
- package/dist/database/system-data/app-access-permissions/index.js +4 -2
- package/dist/database/system-data/app-access-permissions/schema-access-permissions.yaml +17 -0
- package/dist/database/system-data/collections/collections.yaml +3 -0
- package/dist/database/system-data/fields/_defaults.yaml +2 -0
- package/dist/database/system-data/fields/sessions.yaml +1 -1
- package/dist/database/system-data/fields/settings.yaml +20 -1
- package/dist/database/system-data/fields/shares.yaml +77 -0
- package/dist/database/system-data/fields/users.yaml +1 -1
- package/dist/database/system-data/relations/relations.yaml +15 -0
- package/dist/env.js +4 -1
- package/dist/extensions.d.ts +11 -6
- package/dist/extensions.js +97 -42
- package/dist/middleware/authenticate.js +7 -16
- package/dist/middleware/check-ip.js +9 -6
- package/dist/middleware/rate-limiter.js +2 -1
- package/dist/middleware/respond.js +4 -1
- package/dist/services/activity.d.ts +2 -1
- package/dist/services/activity.js +2 -2
- package/dist/services/assets.js +3 -3
- package/dist/services/authentication.d.ts +2 -7
- package/dist/services/authentication.js +84 -41
- package/dist/services/authorization.js +3 -3
- package/dist/services/collections.d.ts +1 -2
- package/dist/services/collections.js +2 -2
- package/dist/services/files.d.ts +2 -2
- package/dist/services/graphql.d.ts +1 -1
- package/dist/services/graphql.js +51 -10
- package/dist/services/index.d.ts +1 -0
- package/dist/services/index.js +1 -0
- package/dist/services/items.d.ts +1 -15
- package/dist/services/notifications.d.ts +2 -2
- package/dist/services/permissions.d.ts +2 -2
- package/dist/services/roles.d.ts +2 -2
- package/dist/services/server.js +1 -0
- package/dist/services/shares.d.ts +17 -0
- package/dist/services/shares.js +135 -0
- package/dist/services/specifications.js +1 -1
- package/dist/services/users.d.ts +2 -2
- package/dist/services/webhooks.d.ts +2 -2
- package/dist/types/ast.d.ts +3 -3
- package/dist/types/auth.d.ts +31 -0
- package/dist/types/items.d.ts +14 -0
- package/dist/utils/apply-query.d.ts +0 -38
- package/dist/utils/apply-query.js +66 -67
- package/dist/utils/get-ast-from-query.js +3 -3
- package/dist/utils/get-default-value.js +3 -1
- package/dist/utils/get-ip-from-req.d.ts +2 -0
- package/dist/utils/get-ip-from-req.js +24 -0
- package/dist/utils/get-local-type.js +1 -1
- package/dist/utils/get-permissions.js +15 -7
- package/dist/utils/get-relation-type.d.ts +1 -1
- package/dist/utils/get-relation-type.js +1 -1
- package/dist/utils/merge-permissions-for-share.d.ts +5 -0
- package/dist/utils/merge-permissions-for-share.js +116 -0
- package/dist/utils/merge-permissions.d.ts +13 -1
- package/dist/utils/merge-permissions.js +27 -19
- package/dist/utils/reduce-schema.d.ts +2 -2
- package/dist/utils/reduce-schema.js +7 -7
- package/dist/utils/user-name.js +3 -0
- package/example.env +1 -1
- package/package.json +15 -13
|
@@ -12,6 +12,9 @@ defaults:
|
|
|
12
12
|
sort_field: null
|
|
13
13
|
|
|
14
14
|
data:
|
|
15
|
+
- many_collection: directus_collections
|
|
16
|
+
many_field: group
|
|
17
|
+
one_collection: directus_collections
|
|
15
18
|
- many_collection: directus_users
|
|
16
19
|
many_field: role
|
|
17
20
|
one_collection: directus_roles
|
|
@@ -73,6 +76,9 @@ data:
|
|
|
73
76
|
- many_collection: directus_sessions
|
|
74
77
|
many_field: user
|
|
75
78
|
one_collection: directus_users
|
|
79
|
+
- many_collection: directus_sessions
|
|
80
|
+
many_field: share
|
|
81
|
+
one_collection: directus_shares
|
|
76
82
|
- many_collection: directus_settings
|
|
77
83
|
many_field: storage_default_folder
|
|
78
84
|
one_collection: directus_folders
|
|
@@ -88,3 +94,12 @@ data:
|
|
|
88
94
|
- many_collection: directus_notifications
|
|
89
95
|
many_field: sender
|
|
90
96
|
one_collection: directus_users
|
|
97
|
+
- many_collection: directus_shares
|
|
98
|
+
many_field: role
|
|
99
|
+
one_collection: directus_roles
|
|
100
|
+
- many_collection: directus_shares
|
|
101
|
+
many_field: collection
|
|
102
|
+
one_collection: directus_collections
|
|
103
|
+
- many_collection: directus_shares
|
|
104
|
+
many_field: user_created
|
|
105
|
+
one_collection: directus_users
|
package/dist/env.js
CHANGED
|
@@ -20,7 +20,7 @@ const defaults = {
|
|
|
20
20
|
PORT: 8055,
|
|
21
21
|
PUBLIC_URL: '/',
|
|
22
22
|
MAX_PAYLOAD_SIZE: '100kb',
|
|
23
|
-
DB_EXCLUDE_TABLES: 'spatial_ref_sys',
|
|
23
|
+
DB_EXCLUDE_TABLES: 'spatial_ref_sys,sysdiagrams',
|
|
24
24
|
STORAGE_LOCATIONS: 'local',
|
|
25
25
|
STORAGE_LOCAL_DRIVER: 'local',
|
|
26
26
|
STORAGE_LOCAL_ROOT: './uploads',
|
|
@@ -52,6 +52,7 @@ const defaults = {
|
|
|
52
52
|
AUTH_PROVIDERS: '',
|
|
53
53
|
AUTH_DISABLE_DEFAULT: false,
|
|
54
54
|
EXTENSIONS_PATH: './extensions',
|
|
55
|
+
EXTENSIONS_AUTO_RELOAD: false,
|
|
55
56
|
EMAIL_FROM: 'no-reply@directus.io',
|
|
56
57
|
EMAIL_TRANSPORT: 'sendmail',
|
|
57
58
|
EMAIL_SENDMAIL_NEW_LINE: 'unix',
|
|
@@ -61,6 +62,8 @@ const defaults = {
|
|
|
61
62
|
ASSETS_TRANSFORM_MAX_CONCURRENT: 1,
|
|
62
63
|
ASSETS_TRANSFORM_IMAGE_MAX_DIMENSION: 6000,
|
|
63
64
|
ASSETS_TRANSFORM_MAX_OPERATIONS: 5,
|
|
65
|
+
IP_TRUST_PROXY: true,
|
|
66
|
+
IP_CUSTOM_HEADER: false,
|
|
64
67
|
SERVE_APP: true,
|
|
65
68
|
};
|
|
66
69
|
// Allows us to force certain environment variable into a type, instead of relying
|
package/dist/extensions.d.ts
CHANGED
|
@@ -2,22 +2,27 @@ import { Router } from 'express';
|
|
|
2
2
|
import { AppExtensionType, ExtensionType } from '@directus/shared/types';
|
|
3
3
|
export declare function getExtensionManager(): ExtensionManager;
|
|
4
4
|
declare class ExtensionManager {
|
|
5
|
-
private
|
|
5
|
+
private isLoaded;
|
|
6
|
+
private isScheduleHookEnabled;
|
|
6
7
|
private extensions;
|
|
7
8
|
private appExtensions;
|
|
8
|
-
private
|
|
9
|
-
private apiEndpoints;
|
|
9
|
+
private apiExtensions;
|
|
10
10
|
private apiEmitter;
|
|
11
11
|
private endpointRouter;
|
|
12
|
-
private
|
|
12
|
+
private watcher;
|
|
13
13
|
constructor();
|
|
14
|
-
initialize({ schedule }?: {
|
|
14
|
+
initialize({ schedule, watch }?: {
|
|
15
15
|
schedule: boolean;
|
|
16
|
+
watch: boolean;
|
|
16
17
|
}): Promise<void>;
|
|
17
18
|
reload(): Promise<void>;
|
|
18
|
-
|
|
19
|
+
getExtensionsList(type?: ExtensionType): string[];
|
|
19
20
|
getAppExtensions(type: AppExtensionType): string | undefined;
|
|
20
21
|
getEndpointRouter(): Router;
|
|
22
|
+
private load;
|
|
23
|
+
private unload;
|
|
24
|
+
private initializeWatcher;
|
|
25
|
+
private updateWatchedExtensions;
|
|
21
26
|
private getExtensions;
|
|
22
27
|
private generateExtensionBundles;
|
|
23
28
|
private getSharedDepsMapping;
|
package/dist/extensions.js
CHANGED
|
@@ -44,6 +44,9 @@ const plugin_virtual_1 = __importDefault(require("@rollup/plugin-virtual"));
|
|
|
44
44
|
const plugin_alias_1 = __importDefault(require("@rollup/plugin-alias"));
|
|
45
45
|
const url_1 = require("./utils/url");
|
|
46
46
|
const get_module_default_1 = __importDefault(require("./utils/get-module-default"));
|
|
47
|
+
const lodash_1 = require("lodash");
|
|
48
|
+
const chokidar_1 = __importDefault(require("chokidar"));
|
|
49
|
+
const utils_1 = require("@directus/shared/utils");
|
|
47
50
|
let extensionManager;
|
|
48
51
|
function getExtensionManager() {
|
|
49
52
|
if (extensionManager) {
|
|
@@ -55,19 +58,66 @@ function getExtensionManager() {
|
|
|
55
58
|
exports.getExtensionManager = getExtensionManager;
|
|
56
59
|
class ExtensionManager {
|
|
57
60
|
constructor() {
|
|
58
|
-
this.
|
|
61
|
+
this.isLoaded = false;
|
|
62
|
+
this.isScheduleHookEnabled = true;
|
|
59
63
|
this.extensions = [];
|
|
60
64
|
this.appExtensions = {};
|
|
61
|
-
this.
|
|
62
|
-
this.
|
|
63
|
-
this.isScheduleHookEnabled = true;
|
|
65
|
+
this.apiExtensions = { hooks: [], endpoints: [] };
|
|
66
|
+
this.watcher = null;
|
|
64
67
|
this.apiEmitter = new emitter_1.Emitter();
|
|
65
68
|
this.endpointRouter = (0, express_1.Router)();
|
|
66
69
|
}
|
|
67
|
-
async initialize({ schedule } = { schedule: true }) {
|
|
70
|
+
async initialize({ schedule, watch } = { schedule: true, watch: true }) {
|
|
68
71
|
this.isScheduleHookEnabled = schedule;
|
|
69
|
-
if (
|
|
70
|
-
|
|
72
|
+
if (watch) {
|
|
73
|
+
this.initializeWatcher();
|
|
74
|
+
}
|
|
75
|
+
if (!this.isLoaded) {
|
|
76
|
+
await this.load();
|
|
77
|
+
this.updateWatchedExtensions(this.extensions);
|
|
78
|
+
const loadedExtensions = this.getExtensionsList();
|
|
79
|
+
if (loadedExtensions.length > 0) {
|
|
80
|
+
logger_1.default.info(`Loaded extensions: ${loadedExtensions.join(', ')}`);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
async reload() {
|
|
85
|
+
if (this.isLoaded) {
|
|
86
|
+
logger_1.default.info('Reloading extensions');
|
|
87
|
+
const prevExtensions = (0, lodash_1.clone)(this.extensions);
|
|
88
|
+
await this.unload();
|
|
89
|
+
await this.load();
|
|
90
|
+
const added = this.extensions.filter((extension) => !prevExtensions.some((prevExtension) => extension.path === prevExtension.path));
|
|
91
|
+
const removed = prevExtensions.filter((prevExtension) => !this.extensions.some((extension) => prevExtension.path === extension.path));
|
|
92
|
+
this.updateWatchedExtensions(added, removed);
|
|
93
|
+
const addedExtensions = added.map((extension) => extension.name);
|
|
94
|
+
const removedExtensions = removed.map((extension) => extension.name);
|
|
95
|
+
if (addedExtensions.length > 0) {
|
|
96
|
+
logger_1.default.info(`Added extensions: ${addedExtensions.join(', ')}`);
|
|
97
|
+
}
|
|
98
|
+
if (removedExtensions.length > 0) {
|
|
99
|
+
logger_1.default.info(`Removed extensions: ${removedExtensions.join(', ')}`);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
else {
|
|
103
|
+
logger_1.default.warn('Extensions have to be loaded before they can be reloaded');
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
getExtensionsList(type) {
|
|
107
|
+
if (type === undefined) {
|
|
108
|
+
return this.extensions.map((extension) => extension.name);
|
|
109
|
+
}
|
|
110
|
+
else {
|
|
111
|
+
return this.extensions.filter((extension) => extension.type === type).map((extension) => extension.name);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
getAppExtensions(type) {
|
|
115
|
+
return this.appExtensions[type];
|
|
116
|
+
}
|
|
117
|
+
getEndpointRouter() {
|
|
118
|
+
return this.endpointRouter;
|
|
119
|
+
}
|
|
120
|
+
async load() {
|
|
71
121
|
try {
|
|
72
122
|
await (0, node_1.ensureExtensionDirs)(env_1.default.EXTENSIONS_PATH, env_1.default.SERVE_APP ? constants_1.EXTENSION_TYPES : constants_1.API_EXTENSION_TYPES);
|
|
73
123
|
this.extensions = await this.getExtensions();
|
|
@@ -81,38 +131,42 @@ class ExtensionManager {
|
|
|
81
131
|
if (env_1.default.SERVE_APP) {
|
|
82
132
|
this.appExtensions = await this.generateExtensionBundles();
|
|
83
133
|
}
|
|
84
|
-
|
|
85
|
-
if (loadedExtensions.length > 0) {
|
|
86
|
-
logger_1.default.info(`Loaded extensions: ${loadedExtensions.join(', ')}`);
|
|
87
|
-
}
|
|
88
|
-
this.isInitialized = true;
|
|
134
|
+
this.isLoaded = true;
|
|
89
135
|
}
|
|
90
|
-
async
|
|
91
|
-
if (!this.isInitialized)
|
|
92
|
-
return;
|
|
93
|
-
logger_1.default.info('Reloading extensions');
|
|
136
|
+
async unload() {
|
|
94
137
|
this.unregisterHooks();
|
|
95
138
|
this.unregisterEndpoints();
|
|
96
139
|
this.apiEmitter.offAll();
|
|
97
140
|
if (env_1.default.SERVE_APP) {
|
|
98
141
|
this.appExtensions = {};
|
|
99
142
|
}
|
|
100
|
-
this.
|
|
101
|
-
await this.initialize();
|
|
143
|
+
this.isLoaded = false;
|
|
102
144
|
}
|
|
103
|
-
|
|
104
|
-
if (
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
145
|
+
initializeWatcher() {
|
|
146
|
+
if (env_1.default.EXTENSIONS_AUTO_RELOAD && env_1.default.NODE_ENV !== 'development' && !this.watcher) {
|
|
147
|
+
logger_1.default.info('Watching extensions for changes...');
|
|
148
|
+
const localExtensionPaths = (env_1.default.SERVE_APP ? constants_1.EXTENSION_TYPES : constants_1.API_EXTENSION_TYPES).map((type) => path_1.default.resolve(env_1.default.EXTENSIONS_PATH, (0, utils_1.pluralize)(type)));
|
|
149
|
+
this.watcher = chokidar_1.default.watch([path_1.default.resolve('.', 'package.json'), ...localExtensionPaths], {
|
|
150
|
+
ignoreInitial: true,
|
|
151
|
+
});
|
|
152
|
+
this.watcher
|
|
153
|
+
.on('add', () => this.reload())
|
|
154
|
+
.on('change', () => this.reload())
|
|
155
|
+
.on('unlink', () => this.reload());
|
|
109
156
|
}
|
|
110
157
|
}
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
158
|
+
updateWatchedExtensions(added, removed = []) {
|
|
159
|
+
if (this.watcher) {
|
|
160
|
+
const toPackageExtensionPaths = (extensions) => extensions
|
|
161
|
+
.filter((extension) => !extension.local)
|
|
162
|
+
.map((extension) => extension.type !== 'pack'
|
|
163
|
+
? path_1.default.resolve(extension.path, extension.entrypoint || '')
|
|
164
|
+
: path_1.default.resolve(extension.path, 'package.json'));
|
|
165
|
+
const addedPackageExtensionPaths = toPackageExtensionPaths(added);
|
|
166
|
+
const removedPackageExtensionPaths = toPackageExtensionPaths(removed);
|
|
167
|
+
this.watcher.add(addedPackageExtensionPaths);
|
|
168
|
+
this.watcher.unwatch(removedPackageExtensionPaths);
|
|
169
|
+
}
|
|
116
170
|
}
|
|
117
171
|
async getExtensions() {
|
|
118
172
|
const packageExtensions = await (0, node_1.getPackageExtensions)('.', env_1.default.SERVE_APP ? constants_1.EXTENSION_PACKAGE_TYPES : constants_1.API_EXTENSION_PACKAGE_TYPES);
|
|
@@ -141,12 +195,13 @@ class ExtensionManager {
|
|
|
141
195
|
return bundles;
|
|
142
196
|
}
|
|
143
197
|
async getSharedDepsMapping(deps) {
|
|
144
|
-
const appDir = await fs_extra_1.default.readdir(path_1.default.join((0, node_1.resolvePackage)('@directus/app'), 'dist'));
|
|
198
|
+
const appDir = await fs_extra_1.default.readdir(path_1.default.join((0, node_1.resolvePackage)('@directus/app'), 'dist', 'assets'));
|
|
145
199
|
const depsMapping = {};
|
|
146
200
|
for (const dep of deps) {
|
|
147
|
-
const
|
|
201
|
+
const depRegex = new RegExp(`${(0, lodash_1.escapeRegExp)(dep.replace(/\//g, '_'))}\\.[0-9a-f]{8}\\.entry\\.js`);
|
|
202
|
+
const depName = appDir.find((file) => depRegex.test(file));
|
|
148
203
|
if (depName) {
|
|
149
|
-
const depUrl = new url_1.Url(env_1.default.PUBLIC_URL).addPath('admin', depName);
|
|
204
|
+
const depUrl = new url_1.Url(env_1.default.PUBLIC_URL).addPath('admin', 'assets', depName);
|
|
150
205
|
depsMapping[dep] = depUrl.toString({ rootRelative: true });
|
|
151
206
|
}
|
|
152
207
|
else {
|
|
@@ -186,7 +241,7 @@ class ExtensionManager {
|
|
|
186
241
|
const registerFunctions = {
|
|
187
242
|
filter: (event, handler) => {
|
|
188
243
|
emitter_1.default.onFilter(event, handler);
|
|
189
|
-
this.
|
|
244
|
+
this.apiExtensions.hooks.push({
|
|
190
245
|
type: 'filter',
|
|
191
246
|
path: hookPath,
|
|
192
247
|
event,
|
|
@@ -195,7 +250,7 @@ class ExtensionManager {
|
|
|
195
250
|
},
|
|
196
251
|
action: (event, handler) => {
|
|
197
252
|
emitter_1.default.onAction(event, handler);
|
|
198
|
-
this.
|
|
253
|
+
this.apiExtensions.hooks.push({
|
|
199
254
|
type: 'action',
|
|
200
255
|
path: hookPath,
|
|
201
256
|
event,
|
|
@@ -204,7 +259,7 @@ class ExtensionManager {
|
|
|
204
259
|
},
|
|
205
260
|
init: (event, handler) => {
|
|
206
261
|
emitter_1.default.onInit(event, handler);
|
|
207
|
-
this.
|
|
262
|
+
this.apiExtensions.hooks.push({
|
|
208
263
|
type: 'init',
|
|
209
264
|
path: hookPath,
|
|
210
265
|
event,
|
|
@@ -223,7 +278,7 @@ class ExtensionManager {
|
|
|
223
278
|
}
|
|
224
279
|
}
|
|
225
280
|
});
|
|
226
|
-
this.
|
|
281
|
+
this.apiExtensions.hooks.push({
|
|
227
282
|
type: 'schedule',
|
|
228
283
|
path: hookPath,
|
|
229
284
|
task,
|
|
@@ -261,12 +316,12 @@ class ExtensionManager {
|
|
|
261
316
|
logger: logger_1.default,
|
|
262
317
|
getSchema: get_schema_1.getSchema,
|
|
263
318
|
});
|
|
264
|
-
this.
|
|
319
|
+
this.apiExtensions.endpoints.push({
|
|
265
320
|
path: endpointPath,
|
|
266
321
|
});
|
|
267
322
|
}
|
|
268
323
|
unregisterHooks() {
|
|
269
|
-
for (const hook of this.
|
|
324
|
+
for (const hook of this.apiExtensions.hooks) {
|
|
270
325
|
switch (hook.type) {
|
|
271
326
|
case 'filter':
|
|
272
327
|
emitter_1.default.offFilter(hook.event, hook.handler);
|
|
@@ -278,18 +333,18 @@ class ExtensionManager {
|
|
|
278
333
|
emitter_1.default.offInit(hook.event, hook.handler);
|
|
279
334
|
break;
|
|
280
335
|
case 'schedule':
|
|
281
|
-
hook.task.
|
|
336
|
+
hook.task.stop();
|
|
282
337
|
break;
|
|
283
338
|
}
|
|
284
339
|
delete require.cache[require.resolve(hook.path)];
|
|
285
340
|
}
|
|
286
|
-
this.
|
|
341
|
+
this.apiExtensions.hooks = [];
|
|
287
342
|
}
|
|
288
343
|
unregisterEndpoints() {
|
|
289
|
-
for (const endpoint of this.
|
|
344
|
+
for (const endpoint of this.apiExtensions.endpoints) {
|
|
290
345
|
delete require.cache[require.resolve(endpoint.path)];
|
|
291
346
|
}
|
|
292
347
|
this.endpointRouter.stack = [];
|
|
293
|
-
this.
|
|
348
|
+
this.apiExtensions.endpoints = [];
|
|
294
349
|
}
|
|
295
350
|
}
|
|
@@ -27,6 +27,7 @@ const database_1 = __importDefault(require("../database"));
|
|
|
27
27
|
const env_1 = __importDefault(require("../env"));
|
|
28
28
|
const exceptions_1 = require("../exceptions");
|
|
29
29
|
const async_handler_1 = __importDefault(require("../utils/async-handler"));
|
|
30
|
+
const get_ip_from_req_1 = require("../utils/get-ip-from-req");
|
|
30
31
|
const is_directus_jwt_1 = __importDefault(require("../utils/is-directus-jwt"));
|
|
31
32
|
/**
|
|
32
33
|
* Verify the passed JWT and assign the user ID and role to `req`
|
|
@@ -37,7 +38,7 @@ const authenticate = (0, async_handler_1.default)(async (req, res, next) => {
|
|
|
37
38
|
role: null,
|
|
38
39
|
admin: false,
|
|
39
40
|
app: false,
|
|
40
|
-
ip:
|
|
41
|
+
ip: (0, get_ip_from_req_1.getIPFromReq)(req),
|
|
41
42
|
userAgent: req.get('user-agent'),
|
|
42
43
|
};
|
|
43
44
|
const database = (0, database_1.default)();
|
|
@@ -58,22 +59,12 @@ const authenticate = (0, async_handler_1.default)(async (req, res, next) => {
|
|
|
58
59
|
throw err;
|
|
59
60
|
}
|
|
60
61
|
}
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
.from('directus_users')
|
|
64
|
-
.leftJoin('directus_roles', 'directus_users.role', 'directus_roles.id')
|
|
65
|
-
.where({
|
|
66
|
-
'directus_users.id': payload.id,
|
|
67
|
-
status: 'active',
|
|
68
|
-
})
|
|
69
|
-
.first();
|
|
70
|
-
if (!user) {
|
|
71
|
-
throw new exceptions_1.InvalidCredentialsException();
|
|
72
|
-
}
|
|
62
|
+
req.accountability.share = payload.share;
|
|
63
|
+
req.accountability.share_scope = payload.share_scope;
|
|
73
64
|
req.accountability.user = payload.id;
|
|
74
|
-
req.accountability.role =
|
|
75
|
-
req.accountability.admin =
|
|
76
|
-
req.accountability.app =
|
|
65
|
+
req.accountability.role = payload.role;
|
|
66
|
+
req.accountability.admin = payload.admin_access === true || payload.admin_access == 1;
|
|
67
|
+
req.accountability.app = payload.app_access === true || payload.app_access == 1;
|
|
77
68
|
}
|
|
78
69
|
else {
|
|
79
70
|
// Try finding the user with the provided token
|
|
@@ -7,13 +7,16 @@ exports.checkIP = void 0;
|
|
|
7
7
|
const database_1 = __importDefault(require("../database"));
|
|
8
8
|
const exceptions_1 = require("../exceptions");
|
|
9
9
|
const async_handler_1 = __importDefault(require("../utils/async-handler"));
|
|
10
|
-
exports.checkIP = (0, async_handler_1.default)(async (req,
|
|
10
|
+
exports.checkIP = (0, async_handler_1.default)(async (req, _res, next) => {
|
|
11
11
|
const database = (0, database_1.default)();
|
|
12
|
-
const
|
|
13
|
-
|
|
14
|
-
.
|
|
15
|
-
|
|
16
|
-
|
|
12
|
+
const query = database.select('ip_access').from('directus_roles');
|
|
13
|
+
if (req.accountability.role) {
|
|
14
|
+
query.where({ id: req.accountability.role });
|
|
15
|
+
}
|
|
16
|
+
else {
|
|
17
|
+
query.whereNull('id');
|
|
18
|
+
}
|
|
19
|
+
const role = await query.first();
|
|
17
20
|
const ipAllowlist = ((role === null || role === void 0 ? void 0 : role.ip_access) || '').split(',').filter((ip) => ip);
|
|
18
21
|
if (ipAllowlist.length > 0 && ipAllowlist.includes(req.accountability.ip) === false)
|
|
19
22
|
throw new exceptions_1.InvalidIPException();
|
|
@@ -9,6 +9,7 @@ const env_1 = __importDefault(require("../env"));
|
|
|
9
9
|
const exceptions_1 = require("../exceptions");
|
|
10
10
|
const rate_limiter_1 = require("../rate-limiter");
|
|
11
11
|
const async_handler_1 = __importDefault(require("../utils/async-handler"));
|
|
12
|
+
const get_ip_from_req_1 = require("../utils/get-ip-from-req");
|
|
12
13
|
const validate_env_1 = require("../utils/validate-env");
|
|
13
14
|
let checkRateLimit = (req, res, next) => next();
|
|
14
15
|
if (env_1.default.RATE_LIMITER_ENABLED === true) {
|
|
@@ -16,7 +17,7 @@ if (env_1.default.RATE_LIMITER_ENABLED === true) {
|
|
|
16
17
|
exports.rateLimiter = (0, rate_limiter_1.createRateLimiter)();
|
|
17
18
|
checkRateLimit = (0, async_handler_1.default)(async (req, res, next) => {
|
|
18
19
|
try {
|
|
19
|
-
await exports.rateLimiter.consume(req
|
|
20
|
+
await exports.rateLimiter.consume((0, get_ip_from_req_1.getIPFromReq)(req), 1);
|
|
20
21
|
}
|
|
21
22
|
catch (rateLimiterRes) {
|
|
22
23
|
if (rateLimiterRes instanceof Error)
|
|
@@ -77,9 +77,12 @@ exports.respond = (0, async_handler_1.default)(async (req, res) => {
|
|
|
77
77
|
if (Buffer.isBuffer(res.locals.payload)) {
|
|
78
78
|
return res.end(res.locals.payload);
|
|
79
79
|
}
|
|
80
|
-
else {
|
|
80
|
+
else if (res.locals.payload) {
|
|
81
81
|
return res.json(res.locals.payload);
|
|
82
82
|
}
|
|
83
|
+
else {
|
|
84
|
+
return res.status(204).end();
|
|
85
|
+
}
|
|
83
86
|
});
|
|
84
87
|
function getDateFormatted() {
|
|
85
88
|
const date = new Date();
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { AbstractServiceOptions, PrimaryKey, Item } from '../types';
|
|
2
|
-
import { ItemsService
|
|
2
|
+
import { ItemsService } from './items';
|
|
3
|
+
import { MutationOptions } from '../types';
|
|
3
4
|
import { NotificationsService } from './notifications';
|
|
4
5
|
import { UsersService } from './users';
|
|
5
6
|
export declare class ActivityService extends ItemsService {
|
|
@@ -5,7 +5,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.ActivityService = void 0;
|
|
7
7
|
const types_1 = require("../types");
|
|
8
|
-
const
|
|
8
|
+
const items_1 = require("./items");
|
|
9
9
|
const notifications_1 = require("./notifications");
|
|
10
10
|
const users_1 = require("./users");
|
|
11
11
|
const authorization_1 = require("./authorization");
|
|
@@ -16,7 +16,7 @@ const user_name_1 = require("../utils/user-name");
|
|
|
16
16
|
const lodash_1 = require("lodash");
|
|
17
17
|
const env_1 = __importDefault(require("../env"));
|
|
18
18
|
const uuid_validate_1 = __importDefault(require("uuid-validate"));
|
|
19
|
-
class ActivityService extends
|
|
19
|
+
class ActivityService extends items_1.ItemsService {
|
|
20
20
|
constructor(options) {
|
|
21
21
|
super('directus_activity', options);
|
|
22
22
|
this.notificationsService = new notifications_1.NotificationsService({ schema: this.schema });
|
package/dist/services/assets.js
CHANGED
|
@@ -52,9 +52,6 @@ class AssetsService {
|
|
|
52
52
|
.from('directus_settings')
|
|
53
53
|
.first();
|
|
54
54
|
const systemPublicKeys = Object.values(publicSettings || {});
|
|
55
|
-
if (systemPublicKeys.includes(id) === false && ((_a = this.accountability) === null || _a === void 0 ? void 0 : _a.admin) !== true) {
|
|
56
|
-
await this.authorizationService.checkAccess('read', 'directus_files', id);
|
|
57
|
-
}
|
|
58
55
|
/**
|
|
59
56
|
* This is a little annoying. Postgres will error out if you're trying to search in `where`
|
|
60
57
|
* with a wrong type. In case of directus_files where id is a uuid, we'll have to verify the
|
|
@@ -63,6 +60,9 @@ class AssetsService {
|
|
|
63
60
|
const isValidUUID = (0, uuid_validate_1.default)(id, 4);
|
|
64
61
|
if (isValidUUID === false)
|
|
65
62
|
throw new exceptions_1.ForbiddenException();
|
|
63
|
+
if (systemPublicKeys.includes(id) === false && ((_a = this.accountability) === null || _a === void 0 ? void 0 : _a.admin) !== true) {
|
|
64
|
+
await this.authorizationService.checkAccess('read', 'directus_files', id);
|
|
65
|
+
}
|
|
66
66
|
const file = (await this.knex.select('*').from('directus_files').where({ id }).first());
|
|
67
67
|
if (!file)
|
|
68
68
|
throw new exceptions_1.ForbiddenException();
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Knex } from 'knex';
|
|
2
2
|
import { ActivityService } from './activity';
|
|
3
|
-
import { AbstractServiceOptions, SchemaOverview } from '../types';
|
|
3
|
+
import { AbstractServiceOptions, SchemaOverview, LoginResult } from '../types';
|
|
4
4
|
import { Accountability } from '@directus/shared/types';
|
|
5
5
|
export declare class AuthenticationService {
|
|
6
6
|
knex: Knex;
|
|
@@ -14,12 +14,7 @@ export declare class AuthenticationService {
|
|
|
14
14
|
* Password is optional to allow usage of this function within the SSO flow and extensions. Make sure
|
|
15
15
|
* to handle password existence checks elsewhere
|
|
16
16
|
*/
|
|
17
|
-
login(providerName: string | undefined, payload: Record<string, any>, otp?: string): Promise<
|
|
18
|
-
accessToken: any;
|
|
19
|
-
refreshToken: any;
|
|
20
|
-
expires: any;
|
|
21
|
-
id?: any;
|
|
22
|
-
}>;
|
|
17
|
+
login(providerName: string | undefined, payload: Record<string, any>, otp?: string): Promise<LoginResult>;
|
|
23
18
|
refresh(refreshToken: string): Promise<Record<string, any>>;
|
|
24
19
|
logout(refreshToken: string): Promise<void>;
|
|
25
20
|
verifyPassword(userID: string, password: string): Promise<void>;
|