directus 9.12.2 → 9.13.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/app.js +5 -1
- package/dist/auth/drivers/index.js +5 -1
- package/dist/auth/drivers/ldap.js +5 -1
- package/dist/auth/drivers/oauth2.js +15 -23
- package/dist/auth/drivers/openid.js +16 -24
- package/dist/cli/commands/bootstrap/index.js +5 -1
- package/dist/cli/commands/schema/apply.js +7 -3
- package/dist/cli/commands/schema/snapshot.d.ts +1 -1
- package/dist/cli/commands/schema/snapshot.js +33 -25
- package/dist/cli/index.js +1 -1
- package/dist/cli/utils/create-env/env-stub.liquid +11 -11
- package/dist/controllers/assets.js +5 -5
- package/dist/controllers/dashboards.js +4 -1
- package/dist/controllers/files.js +8 -5
- package/dist/controllers/flows.js +4 -1
- package/dist/controllers/folders.js +4 -1
- package/dist/controllers/items.js +4 -1
- package/dist/controllers/notifications.js +4 -1
- package/dist/controllers/operations.js +4 -1
- package/dist/controllers/panels.js +4 -1
- package/dist/controllers/permissions.js +4 -1
- package/dist/controllers/presets.js +4 -1
- package/dist/controllers/roles.js +4 -1
- package/dist/controllers/shares.js +4 -1
- package/dist/controllers/users.js +75 -3
- package/dist/controllers/utils.js +3 -3
- package/dist/database/helpers/date/dialects/sqlite.js +3 -0
- package/dist/database/helpers/index.js +5 -1
- package/dist/database/index.js +2 -0
- package/dist/database/migrations/20210225A-add-relations-sort-field.js +2 -2
- package/dist/database/migrations/20210506A-rename-interfaces.js +2 -2
- package/dist/database/migrations/20210802A-replace-groups.js +2 -2
- package/dist/database/migrations/20210805A-update-groups.js +2 -2
- package/dist/database/migrations/20210805B-change-image-metadata-structure.js +3 -3
- package/dist/database/migrations/20211007A-update-presets.js +5 -5
- package/dist/database/migrations/20220429A-add-flows.js +1 -2
- package/dist/database/migrations/20220614A-rename-hook-trigger-to-event.d.ts +3 -0
- package/dist/database/migrations/20220614A-rename-hook-trigger-to-event.js +11 -0
- package/dist/database/system-data/fields/dashboards.yaml +1 -0
- package/dist/env.d.ts +1 -1
- package/dist/env.js +8 -3
- package/dist/exceptions/database/translate.js +5 -1
- package/dist/exceptions/index.js +5 -1
- package/dist/extensions.js +5 -1
- package/dist/flows.js +15 -11
- package/dist/index.js +5 -1
- package/dist/logger.js +5 -1
- package/dist/messenger.js +2 -2
- package/dist/middleware/graphql.js +2 -2
- package/dist/middleware/respond.js +10 -1
- package/dist/middleware/validate-batch.js +3 -1
- package/dist/operations/item-create/index.js +1 -2
- package/dist/operations/item-delete/index.d.ts +1 -0
- package/dist/operations/item-delete/index.js +8 -7
- package/dist/operations/item-read/index.js +7 -6
- package/dist/operations/item-update/index.d.ts +1 -0
- package/dist/operations/item-update/index.js +9 -8
- package/dist/operations/log/index.js +1 -2
- package/dist/operations/notification/index.js +1 -2
- package/dist/operations/transform/index.js +1 -2
- package/dist/operations/trigger/index.js +1 -2
- package/dist/server.js +5 -1
- package/dist/services/assets.js +5 -1
- package/dist/services/collections.js +5 -1
- package/dist/services/fields.d.ts +3 -3
- package/dist/services/fields.js +25 -17
- package/dist/services/files.js +5 -1
- package/dist/services/flows.d.ts +1 -0
- package/dist/services/flows.js +6 -0
- package/dist/services/{graphql.d.ts → graphql/index.d.ts} +3 -5
- package/dist/services/{graphql.js → graphql/index.js} +109 -101
- package/dist/services/graphql/types/date.d.ts +2 -0
- package/dist/services/graphql/types/date.js +9 -0
- package/dist/services/graphql/types/geojson.d.ts +2 -0
- package/dist/services/graphql/types/geojson.js +10 -0
- package/dist/services/graphql/types/string-or-float.d.ts +5 -0
- package/dist/services/graphql/types/string-or-float.js +34 -0
- package/dist/services/graphql/types/void.d.ts +2 -0
- package/dist/services/graphql/types/void.js +17 -0
- package/dist/services/graphql/utils/add-path-to-validation-error.d.ts +2 -0
- package/dist/services/graphql/utils/add-path-to-validation-error.js +20 -0
- package/dist/services/import-export.js +6 -7
- package/dist/services/index.js +5 -1
- package/dist/services/items.d.ts +5 -1
- package/dist/services/items.js +22 -2
- package/dist/services/mail/index.js +8 -6
- package/dist/services/operations.d.ts +1 -0
- package/dist/services/operations.js +6 -0
- package/dist/services/payload.js +2 -3
- package/dist/services/permissions.d.ts +1 -0
- package/dist/services/permissions.js +5 -0
- package/dist/services/relations.js +5 -1
- package/dist/services/roles.d.ts +1 -0
- package/dist/services/roles.js +9 -0
- package/dist/services/server.js +5 -1
- package/dist/services/users.d.ts +1 -0
- package/dist/services/users.js +17 -0
- package/dist/types/index.js +5 -1
- package/dist/utils/apply-query.js +24 -15
- package/dist/utils/calculate-field-depth.d.ts +33 -0
- package/dist/utils/calculate-field-depth.js +75 -0
- package/dist/utils/get-default-value.js +3 -13
- package/dist/utils/get-graphql-type.js +4 -3
- package/dist/utils/get-local-type.d.ts +6 -3
- package/dist/utils/get-permissions.js +3 -4
- package/dist/utils/get-schema.js +1 -2
- package/dist/utils/get-string-byte-size.d.ts +4 -0
- package/dist/utils/get-string-byte-size.js +10 -0
- package/dist/utils/jwt.js +5 -1
- package/dist/utils/sanitize-query.js +4 -5
- package/dist/utils/validate-query.js +50 -0
- package/dist/webhooks.js +5 -1
- package/package.json +74 -73
- package/dist/utils/operation-options.d.ts +0 -3
- package/dist/utils/operation-options.js +0 -45
- package/dist/utils/parse-json.d.ts +0 -5
- package/dist/utils/parse-json.js +0 -19
package/dist/app.js
CHANGED
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
3
|
if (k2 === undefined) k2 = k;
|
|
4
|
-
Object.
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
5
9
|
}) : (function(o, m, k, k2) {
|
|
6
10
|
if (k2 === undefined) k2 = k;
|
|
7
11
|
o[k2] = m[k];
|
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
3
|
if (k2 === undefined) k2 = k;
|
|
4
|
-
Object.
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
5
9
|
}) : (function(o, m, k, k2) {
|
|
6
10
|
if (k2 === undefined) k2 = k;
|
|
7
11
|
o[k2] = m[k];
|
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
3
|
if (k2 === undefined) k2 = k;
|
|
4
|
-
Object.
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
5
9
|
}) : (function(o, m, k, k2) {
|
|
6
10
|
if (k2 === undefined) k2 = k;
|
|
7
11
|
o[k2] = m[k];
|
|
@@ -4,6 +4,8 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.createOAuth2AuthRouter = exports.OAuth2AuthDriver = void 0;
|
|
7
|
+
const exceptions_1 = require("@directus/shared/exceptions");
|
|
8
|
+
const utils_1 = require("@directus/shared/utils");
|
|
7
9
|
const express_1 = require("express");
|
|
8
10
|
const flat_1 = __importDefault(require("flat"));
|
|
9
11
|
const jsonwebtoken_1 = __importDefault(require("jsonwebtoken"));
|
|
@@ -11,14 +13,13 @@ const ms_1 = __importDefault(require("ms"));
|
|
|
11
13
|
const openid_client_1 = require("openid-client");
|
|
12
14
|
const auth_1 = require("../../auth");
|
|
13
15
|
const env_1 = __importDefault(require("../../env"));
|
|
14
|
-
const
|
|
16
|
+
const exceptions_2 = require("../../exceptions");
|
|
15
17
|
const logger_1 = __importDefault(require("../../logger"));
|
|
16
18
|
const respond_1 = require("../../middleware/respond");
|
|
17
19
|
const services_1 = require("../../services");
|
|
18
20
|
const async_handler_1 = __importDefault(require("../../utils/async-handler"));
|
|
19
21
|
const get_config_from_env_1 = require("../../utils/get-config-from-env");
|
|
20
22
|
const get_ip_from_req_1 = require("../../utils/get-ip-from-req");
|
|
21
|
-
const parse_json_1 = require("../../utils/parse-json");
|
|
22
23
|
const url_1 = require("../../utils/url");
|
|
23
24
|
const local_1 = require("./local");
|
|
24
25
|
class OAuth2AuthDriver extends local_1.LocalAuthDriver {
|
|
@@ -26,7 +27,7 @@ class OAuth2AuthDriver extends local_1.LocalAuthDriver {
|
|
|
26
27
|
super(options, config);
|
|
27
28
|
const { authorizeUrl, accessUrl, profileUrl, clientId, clientSecret, ...additionalConfig } = config;
|
|
28
29
|
if (!authorizeUrl || !accessUrl || !profileUrl || !clientId || !clientSecret || !additionalConfig.provider) {
|
|
29
|
-
throw new
|
|
30
|
+
throw new exceptions_2.InvalidConfigException('Invalid provider config', { provider: additionalConfig.provider });
|
|
30
31
|
}
|
|
31
32
|
const redirectUrl = new url_1.Url(env_1.default.PUBLIC_URL).addPath('auth', 'login', additionalConfig.provider, 'callback');
|
|
32
33
|
this.redirectUrl = redirectUrl.toString();
|
|
@@ -81,7 +82,7 @@ class OAuth2AuthDriver extends local_1.LocalAuthDriver {
|
|
|
81
82
|
async getUserID(payload) {
|
|
82
83
|
if (!payload.code || !payload.codeVerifier) {
|
|
83
84
|
logger_1.default.trace('[OAuth2] No code or codeVerifier in payload');
|
|
84
|
-
throw new
|
|
85
|
+
throw new exceptions_2.InvalidCredentialsException();
|
|
85
86
|
}
|
|
86
87
|
let tokenSet;
|
|
87
88
|
let userInfo;
|
|
@@ -100,7 +101,7 @@ class OAuth2AuthDriver extends local_1.LocalAuthDriver {
|
|
|
100
101
|
const identifier = userInfo[identifierKey] ? String(userInfo[identifierKey]) : email;
|
|
101
102
|
if (!identifier) {
|
|
102
103
|
logger_1.default.warn(`[OAuth2] Failed to find user identifier for provider "${provider}"`);
|
|
103
|
-
throw new
|
|
104
|
+
throw new exceptions_2.InvalidCredentialsException();
|
|
104
105
|
}
|
|
105
106
|
const userId = await this.fetchUserId(identifier);
|
|
106
107
|
if (userId) {
|
|
@@ -115,7 +116,7 @@ class OAuth2AuthDriver extends local_1.LocalAuthDriver {
|
|
|
115
116
|
// Is public registration allowed?
|
|
116
117
|
if (!allowPublicRegistration) {
|
|
117
118
|
logger_1.default.trace(`[OAuth2] User doesn't exist, and public registration not allowed for provider "${provider}"`);
|
|
118
|
-
throw new
|
|
119
|
+
throw new exceptions_2.InvalidCredentialsException();
|
|
119
120
|
}
|
|
120
121
|
await this.usersService.createOne({
|
|
121
122
|
provider,
|
|
@@ -135,7 +136,7 @@ class OAuth2AuthDriver extends local_1.LocalAuthDriver {
|
|
|
135
136
|
let authData = user.auth_data;
|
|
136
137
|
if (typeof authData === 'string') {
|
|
137
138
|
try {
|
|
138
|
-
authData = (0,
|
|
139
|
+
authData = (0, utils_1.parseJSON)(authData);
|
|
139
140
|
}
|
|
140
141
|
catch {
|
|
141
142
|
logger_1.default.warn(`[OAuth2] Session data isn't valid JSON: ${authData}`);
|
|
@@ -163,11 +164,11 @@ const handleError = (e) => {
|
|
|
163
164
|
if (e.error === 'invalid_grant') {
|
|
164
165
|
// Invalid token
|
|
165
166
|
logger_1.default.trace(e, `[OAuth2] Invalid grant`);
|
|
166
|
-
return new
|
|
167
|
+
return new exceptions_2.InvalidTokenException();
|
|
167
168
|
}
|
|
168
169
|
// Server response error
|
|
169
170
|
logger_1.default.trace(e, `[OAuth2] Unknown OP error`);
|
|
170
|
-
return new
|
|
171
|
+
return new exceptions_2.ServiceUnavailableException('Service returned unexpected response', {
|
|
171
172
|
service: 'oauth2',
|
|
172
173
|
message: e.error_description,
|
|
173
174
|
});
|
|
@@ -175,7 +176,7 @@ const handleError = (e) => {
|
|
|
175
176
|
else if (e instanceof openid_client_1.errors.RPError) {
|
|
176
177
|
// Internal client error
|
|
177
178
|
logger_1.default.trace(e, `[OAuth2] Unknown RP error`);
|
|
178
|
-
return new
|
|
179
|
+
return new exceptions_2.InvalidCredentialsException();
|
|
179
180
|
}
|
|
180
181
|
logger_1.default.trace(e, `[OAuth2] Unknown error`);
|
|
181
182
|
return e;
|
|
@@ -204,7 +205,7 @@ function createOAuth2AuthRouter(providerName) {
|
|
|
204
205
|
}
|
|
205
206
|
catch (e) {
|
|
206
207
|
logger_1.default.warn(e, `[OAuth2] Couldn't verify OAuth2 cookie`);
|
|
207
|
-
throw new
|
|
208
|
+
throw new exceptions_2.InvalidCredentialsException();
|
|
208
209
|
}
|
|
209
210
|
const { verifier, redirect, prompt } = tokenData;
|
|
210
211
|
const authenticationService = new services_1.AuthenticationService({
|
|
@@ -229,22 +230,13 @@ function createOAuth2AuthRouter(providerName) {
|
|
|
229
230
|
}
|
|
230
231
|
catch (error) {
|
|
231
232
|
// Prompt user for a new refresh_token if invalidated
|
|
232
|
-
if (error instanceof
|
|
233
|
+
if (error instanceof exceptions_2.InvalidTokenException && !prompt) {
|
|
233
234
|
return res.redirect(`./?${redirect ? `redirect=${redirect}&` : ''}prompt=true`);
|
|
234
235
|
}
|
|
235
236
|
if (redirect) {
|
|
236
237
|
let reason = 'UNKNOWN_EXCEPTION';
|
|
237
|
-
if (error instanceof exceptions_1.
|
|
238
|
-
reason =
|
|
239
|
-
}
|
|
240
|
-
else if (error instanceof exceptions_1.InvalidCredentialsException) {
|
|
241
|
-
reason = 'INVALID_USER';
|
|
242
|
-
}
|
|
243
|
-
else if (error instanceof exceptions_1.InvalidTokenException) {
|
|
244
|
-
reason = 'INVALID_TOKEN';
|
|
245
|
-
}
|
|
246
|
-
else if (error instanceof exceptions_1.InvalidProviderException) {
|
|
247
|
-
reason = 'INVALID_PROVIDER';
|
|
238
|
+
if (error instanceof exceptions_1.BaseException) {
|
|
239
|
+
reason = error.code;
|
|
248
240
|
}
|
|
249
241
|
else {
|
|
250
242
|
logger_1.default.warn(error, `[OAuth2] Unexpected error during OAuth2 login`);
|
|
@@ -4,6 +4,8 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.createOpenIDAuthRouter = exports.OpenIDAuthDriver = void 0;
|
|
7
|
+
const exceptions_1 = require("@directus/shared/exceptions");
|
|
8
|
+
const utils_1 = require("@directus/shared/utils");
|
|
7
9
|
const express_1 = require("express");
|
|
8
10
|
const flat_1 = __importDefault(require("flat"));
|
|
9
11
|
const jsonwebtoken_1 = __importDefault(require("jsonwebtoken"));
|
|
@@ -11,14 +13,13 @@ const ms_1 = __importDefault(require("ms"));
|
|
|
11
13
|
const openid_client_1 = require("openid-client");
|
|
12
14
|
const auth_1 = require("../../auth");
|
|
13
15
|
const env_1 = __importDefault(require("../../env"));
|
|
14
|
-
const
|
|
16
|
+
const exceptions_2 = require("../../exceptions");
|
|
15
17
|
const logger_1 = __importDefault(require("../../logger"));
|
|
16
18
|
const respond_1 = require("../../middleware/respond");
|
|
17
19
|
const services_1 = require("../../services");
|
|
18
20
|
const async_handler_1 = __importDefault(require("../../utils/async-handler"));
|
|
19
21
|
const get_config_from_env_1 = require("../../utils/get-config-from-env");
|
|
20
22
|
const get_ip_from_req_1 = require("../../utils/get-ip-from-req");
|
|
21
|
-
const parse_json_1 = require("../../utils/parse-json");
|
|
22
23
|
const url_1 = require("../../utils/url");
|
|
23
24
|
const local_1 = require("./local");
|
|
24
25
|
class OpenIDAuthDriver extends local_1.LocalAuthDriver {
|
|
@@ -26,7 +27,7 @@ class OpenIDAuthDriver extends local_1.LocalAuthDriver {
|
|
|
26
27
|
super(options, config);
|
|
27
28
|
const { issuerUrl, clientId, clientSecret, ...additionalConfig } = config;
|
|
28
29
|
if (!issuerUrl || !clientId || !clientSecret || !additionalConfig.provider) {
|
|
29
|
-
throw new
|
|
30
|
+
throw new exceptions_2.InvalidConfigException('Invalid provider config', { provider: additionalConfig.provider });
|
|
30
31
|
}
|
|
31
32
|
const redirectUrl = new url_1.Url(env_1.default.PUBLIC_URL).addPath('auth', 'login', additionalConfig.provider, 'callback');
|
|
32
33
|
const clientOptionsOverrides = (0, get_config_from_env_1.getConfigFromEnv)(`AUTH_${config.provider.toUpperCase()}_CLIENT_`, [`AUTH_${config.provider.toUpperCase()}_CLIENT_ID`, `AUTH_${config.provider.toUpperCase()}_CLIENT_SECRET`], 'underscore');
|
|
@@ -38,7 +39,7 @@ class OpenIDAuthDriver extends local_1.LocalAuthDriver {
|
|
|
38
39
|
.then((issuer) => {
|
|
39
40
|
const supportedTypes = issuer.metadata.response_types_supported;
|
|
40
41
|
if (!(supportedTypes === null || supportedTypes === void 0 ? void 0 : supportedTypes.includes('code'))) {
|
|
41
|
-
reject(new
|
|
42
|
+
reject(new exceptions_2.InvalidConfigException('OpenID provider does not support required code flow', {
|
|
42
43
|
provider: additionalConfig.provider,
|
|
43
44
|
}));
|
|
44
45
|
}
|
|
@@ -88,7 +89,7 @@ class OpenIDAuthDriver extends local_1.LocalAuthDriver {
|
|
|
88
89
|
async getUserID(payload) {
|
|
89
90
|
if (!payload.code || !payload.codeVerifier) {
|
|
90
91
|
logger_1.default.trace('[OpenID] No code or codeVerifier in payload');
|
|
91
|
-
throw new
|
|
92
|
+
throw new exceptions_2.InvalidCredentialsException();
|
|
92
93
|
}
|
|
93
94
|
let tokenSet;
|
|
94
95
|
let userInfo;
|
|
@@ -114,7 +115,7 @@ class OpenIDAuthDriver extends local_1.LocalAuthDriver {
|
|
|
114
115
|
const identifier = userInfo[identifierKey !== null && identifierKey !== void 0 ? identifierKey : 'sub'] ? String(userInfo[identifierKey !== null && identifierKey !== void 0 ? identifierKey : 'sub']) : email;
|
|
115
116
|
if (!identifier) {
|
|
116
117
|
logger_1.default.warn(`[OpenID] Failed to find user identifier for provider "${provider}"`);
|
|
117
|
-
throw new
|
|
118
|
+
throw new exceptions_2.InvalidCredentialsException();
|
|
118
119
|
}
|
|
119
120
|
const userId = await this.fetchUserId(identifier);
|
|
120
121
|
if (userId) {
|
|
@@ -130,7 +131,7 @@ class OpenIDAuthDriver extends local_1.LocalAuthDriver {
|
|
|
130
131
|
// Is public registration allowed?
|
|
131
132
|
if (!allowPublicRegistration || !isEmailVerified) {
|
|
132
133
|
logger_1.default.trace(`[OpenID] User doesn't exist, and public registration not allowed for provider "${provider}"`);
|
|
133
|
-
throw new
|
|
134
|
+
throw new exceptions_2.InvalidCredentialsException();
|
|
134
135
|
}
|
|
135
136
|
await this.usersService.createOne({
|
|
136
137
|
provider,
|
|
@@ -150,7 +151,7 @@ class OpenIDAuthDriver extends local_1.LocalAuthDriver {
|
|
|
150
151
|
let authData = user.auth_data;
|
|
151
152
|
if (typeof authData === 'string') {
|
|
152
153
|
try {
|
|
153
|
-
authData = (0,
|
|
154
|
+
authData = (0, utils_1.parseJSON)(authData);
|
|
154
155
|
}
|
|
155
156
|
catch {
|
|
156
157
|
logger_1.default.warn(`[OpenID] Session data isn't valid JSON: ${authData}`);
|
|
@@ -179,11 +180,11 @@ const handleError = (e) => {
|
|
|
179
180
|
if (e.error === 'invalid_grant') {
|
|
180
181
|
// Invalid token
|
|
181
182
|
logger_1.default.trace(e, `[OpenID] Invalid grant`);
|
|
182
|
-
return new
|
|
183
|
+
return new exceptions_2.InvalidTokenException();
|
|
183
184
|
}
|
|
184
185
|
// Server response error
|
|
185
186
|
logger_1.default.trace(e, `[OpenID] Unknown OP error`);
|
|
186
|
-
return new
|
|
187
|
+
return new exceptions_2.ServiceUnavailableException('Service returned unexpected response', {
|
|
187
188
|
service: 'openid',
|
|
188
189
|
message: e.error_description,
|
|
189
190
|
});
|
|
@@ -191,7 +192,7 @@ const handleError = (e) => {
|
|
|
191
192
|
else if (e instanceof openid_client_1.errors.RPError) {
|
|
192
193
|
// Internal client error
|
|
193
194
|
logger_1.default.trace(e, `[OpenID] Unknown RP error`);
|
|
194
|
-
return new
|
|
195
|
+
return new exceptions_2.InvalidCredentialsException();
|
|
195
196
|
}
|
|
196
197
|
logger_1.default.trace(e, `[OpenID] Unknown error`);
|
|
197
198
|
return e;
|
|
@@ -220,7 +221,7 @@ function createOpenIDAuthRouter(providerName) {
|
|
|
220
221
|
}
|
|
221
222
|
catch (e) {
|
|
222
223
|
logger_1.default.warn(e, `[OpenID] Couldn't verify OpenID cookie`);
|
|
223
|
-
throw new
|
|
224
|
+
throw new exceptions_2.InvalidCredentialsException();
|
|
224
225
|
}
|
|
225
226
|
const { verifier, redirect, prompt } = tokenData;
|
|
226
227
|
const authenticationService = new services_1.AuthenticationService({
|
|
@@ -245,23 +246,14 @@ function createOpenIDAuthRouter(providerName) {
|
|
|
245
246
|
}
|
|
246
247
|
catch (error) {
|
|
247
248
|
// Prompt user for a new refresh_token if invalidated
|
|
248
|
-
if (error instanceof
|
|
249
|
+
if (error instanceof exceptions_2.InvalidTokenException && !prompt) {
|
|
249
250
|
return res.redirect(`./?${redirect ? `redirect=${redirect}&` : ''}prompt=true`);
|
|
250
251
|
}
|
|
251
252
|
logger_1.default.warn(error);
|
|
252
253
|
if (redirect) {
|
|
253
254
|
let reason = 'UNKNOWN_EXCEPTION';
|
|
254
|
-
if (error instanceof exceptions_1.
|
|
255
|
-
reason =
|
|
256
|
-
}
|
|
257
|
-
else if (error instanceof exceptions_1.InvalidCredentialsException) {
|
|
258
|
-
reason = 'INVALID_USER';
|
|
259
|
-
}
|
|
260
|
-
else if (error instanceof exceptions_1.InvalidTokenException) {
|
|
261
|
-
reason = 'INVALID_TOKEN';
|
|
262
|
-
}
|
|
263
|
-
else if (error instanceof exceptions_1.InvalidProviderException) {
|
|
264
|
-
reason = 'INVALID_PROVIDER';
|
|
255
|
+
if (error instanceof exceptions_1.BaseException) {
|
|
256
|
+
reason = error.code;
|
|
265
257
|
}
|
|
266
258
|
else {
|
|
267
259
|
logger_1.default.warn(error, `[OpenID] Unexpected error during OpenID login`);
|
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
3
|
if (k2 === undefined) k2 = k;
|
|
4
|
-
Object.
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
5
9
|
}) : (function(o, m, k, k2) {
|
|
6
10
|
if (k2 === undefined) k2 = k;
|
|
7
11
|
o[k2] = m[k];
|
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
3
|
if (k2 === undefined) k2 = k;
|
|
4
|
-
Object.
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
5
9
|
}) : (function(o, m, k, k2) {
|
|
6
10
|
if (k2 === undefined) k2 = k;
|
|
7
11
|
o[k2] = m[k];
|
|
@@ -23,6 +27,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
23
27
|
};
|
|
24
28
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
25
29
|
exports.apply = void 0;
|
|
30
|
+
const utils_1 = require("@directus/shared/utils");
|
|
26
31
|
const chalk_1 = __importDefault(require("chalk"));
|
|
27
32
|
const fs_1 = require("fs");
|
|
28
33
|
const inquirer_1 = __importDefault(require("inquirer"));
|
|
@@ -34,7 +39,6 @@ const logger_1 = __importDefault(require("../../../logger"));
|
|
|
34
39
|
const apply_snapshot_1 = require("../../../utils/apply-snapshot");
|
|
35
40
|
const get_snapshot_1 = require("../../../utils/get-snapshot");
|
|
36
41
|
const get_snapshot_diff_1 = require("../../../utils/get-snapshot-diff");
|
|
37
|
-
const parse_json_1 = require("../../../utils/parse-json");
|
|
38
42
|
async function apply(snapshotPath, options) {
|
|
39
43
|
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m;
|
|
40
44
|
const filename = path_1.default.resolve(process.cwd(), snapshotPath);
|
|
@@ -53,7 +57,7 @@ async function apply(snapshotPath, options) {
|
|
|
53
57
|
snapshot = (await (0, js_yaml_1.load)(fileContents));
|
|
54
58
|
}
|
|
55
59
|
else {
|
|
56
|
-
snapshot = (0,
|
|
60
|
+
snapshot = (0, utils_1.parseJSON)(fileContents);
|
|
57
61
|
}
|
|
58
62
|
const currentSnapshot = await (0, get_snapshot_1.getSnapshot)({ database });
|
|
59
63
|
const snapshotDiff = (0, get_snapshot_diff_1.getSnapshotDiff)(currentSnapshot, snapshot);
|
|
@@ -13,38 +13,46 @@ const inquirer_1 = __importDefault(require("inquirer"));
|
|
|
13
13
|
const js_yaml_1 = require("js-yaml");
|
|
14
14
|
const cache_1 = require("../../../cache");
|
|
15
15
|
async function snapshot(snapshotPath, options) {
|
|
16
|
-
const filename = path_1.default.resolve(process.cwd(), snapshotPath);
|
|
17
|
-
let snapshotExists;
|
|
18
|
-
try {
|
|
19
|
-
await fs_1.promises.access(filename, fs_1.constants.F_OK);
|
|
20
|
-
snapshotExists = true;
|
|
21
|
-
}
|
|
22
|
-
catch {
|
|
23
|
-
snapshotExists = false;
|
|
24
|
-
}
|
|
25
|
-
if (snapshotExists && (options === null || options === void 0 ? void 0 : options.yes) === false) {
|
|
26
|
-
const { overwrite } = await inquirer_1.default.prompt([
|
|
27
|
-
{
|
|
28
|
-
type: 'confirm',
|
|
29
|
-
name: 'overwrite',
|
|
30
|
-
message: 'Snapshot already exists. Do you want to overwrite the file?',
|
|
31
|
-
},
|
|
32
|
-
]);
|
|
33
|
-
if (overwrite === false) {
|
|
34
|
-
process.exit(0);
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
16
|
await (0, cache_1.flushCaches)();
|
|
38
17
|
const database = (0, database_1.default)();
|
|
39
|
-
const snapshot = await (0, get_snapshot_1.getSnapshot)({ database });
|
|
40
18
|
try {
|
|
19
|
+
const snapshot = await (0, get_snapshot_1.getSnapshot)({ database });
|
|
20
|
+
let snapshotString;
|
|
41
21
|
if ((options === null || options === void 0 ? void 0 : options.format) === 'yaml') {
|
|
42
|
-
|
|
22
|
+
snapshotString = (0, js_yaml_1.dump)(snapshot);
|
|
23
|
+
}
|
|
24
|
+
else {
|
|
25
|
+
snapshotString = JSON.stringify(snapshot);
|
|
26
|
+
}
|
|
27
|
+
if (snapshotPath) {
|
|
28
|
+
const filename = path_1.default.resolve(process.cwd(), snapshotPath);
|
|
29
|
+
let snapshotExists;
|
|
30
|
+
try {
|
|
31
|
+
await fs_1.promises.access(filename, fs_1.constants.F_OK);
|
|
32
|
+
snapshotExists = true;
|
|
33
|
+
}
|
|
34
|
+
catch {
|
|
35
|
+
snapshotExists = false;
|
|
36
|
+
}
|
|
37
|
+
if (snapshotExists && (options === null || options === void 0 ? void 0 : options.yes) === false) {
|
|
38
|
+
const { overwrite } = await inquirer_1.default.prompt([
|
|
39
|
+
{
|
|
40
|
+
type: 'confirm',
|
|
41
|
+
name: 'overwrite',
|
|
42
|
+
message: 'Snapshot already exists. Do you want to overwrite the file?',
|
|
43
|
+
},
|
|
44
|
+
]);
|
|
45
|
+
if (overwrite === false) {
|
|
46
|
+
database.destroy();
|
|
47
|
+
process.exit(0);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
await fs_1.promises.writeFile(filename, snapshotString);
|
|
51
|
+
logger_1.default.info(`Snapshot saved to ${filename}`);
|
|
43
52
|
}
|
|
44
53
|
else {
|
|
45
|
-
|
|
54
|
+
process.stdout.write(snapshotString);
|
|
46
55
|
}
|
|
47
|
-
logger_1.default.info(`Snapshot saved to ${filename}`);
|
|
48
56
|
database.destroy();
|
|
49
57
|
process.exit(0);
|
|
50
58
|
}
|
package/dist/cli/index.js
CHANGED
|
@@ -75,7 +75,7 @@ async function createCli() {
|
|
|
75
75
|
.description('Create a new Schema Snapshot')
|
|
76
76
|
.option('-y, --yes', `Assume "yes" as answer to all prompts and run non-interactively`, false)
|
|
77
77
|
.addOption(new commander_1.Option('--format <format>', 'JSON or YAML format').choices(['json', 'yaml']).default('yaml'))
|
|
78
|
-
.argument('
|
|
78
|
+
.argument('[path]', 'Path to snapshot file')
|
|
79
79
|
.action(snapshot_1.snapshot);
|
|
80
80
|
schemaCommands
|
|
81
81
|
.command('apply')
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
####################################################################################################
|
|
2
|
-
#
|
|
2
|
+
#
|
|
3
3
|
# These values set environment variables which modify core settings of Directus.
|
|
4
4
|
#
|
|
5
5
|
# Values in square brackets are the default values.
|
|
6
6
|
#
|
|
7
|
-
# The following options are not all possible options. For more, see
|
|
8
|
-
# https://docs.directus.io/
|
|
9
|
-
#
|
|
7
|
+
# The following options are not all possible options. For more, see
|
|
8
|
+
# https://docs.directus.io/self-hosted/config-options/
|
|
9
|
+
#
|
|
10
10
|
####################################################################################################
|
|
11
11
|
####################################################################################################
|
|
12
12
|
|
|
@@ -18,7 +18,7 @@ HOST="0.0.0.0"
|
|
|
18
18
|
# The port Directus will run on [8055]
|
|
19
19
|
PORT=8055
|
|
20
20
|
|
|
21
|
-
# The URL where your API can be reached on the web. It is also used for things like OAuth redirects,
|
|
21
|
+
# The URL where your API can be reached on the web. It is also used for things like OAuth redirects,
|
|
22
22
|
# forgot-password emails, and logos that needs to be publicly available on the internet. ["/"]
|
|
23
23
|
PUBLIC_URL="/"
|
|
24
24
|
# PUBLIC_URL="http://localhost:8055"
|
|
@@ -46,8 +46,8 @@ PUBLIC_URL="/"
|
|
|
46
46
|
####################################################################################################
|
|
47
47
|
### Database
|
|
48
48
|
|
|
49
|
-
# All DB_* environment variables are passed to the connection configuration of a Knex instance.
|
|
50
|
-
# Based on your project's needs, you can extend the DB_* environment variables with any config
|
|
49
|
+
# All DB_* environment variables are passed to the connection configuration of a Knex instance.
|
|
50
|
+
# Based on your project's needs, you can extend the DB_* environment variables with any config
|
|
51
51
|
# you need to pass to the database instance.
|
|
52
52
|
|
|
53
53
|
{{ database }}
|
|
@@ -177,7 +177,7 @@ STORAGE_LOCAL_ROOT="./uploads"
|
|
|
177
177
|
# STORAGE_GOOGLE_BUCKET="my-files"
|
|
178
178
|
|
|
179
179
|
|
|
180
|
-
## A comma-separated list of metadata keys to collect during file upload. Use * for all
|
|
180
|
+
## A comma-separated list of metadata keys to collect during file upload. Use * for all
|
|
181
181
|
# Extracting all metadata might cause memory issues when the file has an unusually large set of metadata
|
|
182
182
|
# [ifd0.Make,ifd0.Model,exif.FNumber,exif.ExposureTime,exif.FocalLength,exif.ISO]
|
|
183
183
|
# FILE_METADATA_ALLOW_LIST=
|
|
@@ -190,7 +190,7 @@ STORAGE_LOCAL_ROOT="./uploads"
|
|
|
190
190
|
# Unique identifier for the project
|
|
191
191
|
# KEY="xxxxxxx-xxxxxx-xxxxxxxx-xxxxxxxxxx"
|
|
192
192
|
|
|
193
|
-
# Secret string for the project
|
|
193
|
+
# Secret string for the project
|
|
194
194
|
# SECRET="abcdef"
|
|
195
195
|
|
|
196
196
|
# The duration that the access token is valid ["15m"]
|
|
@@ -250,7 +250,7 @@ CORS_MAX_AGE=18000
|
|
|
250
250
|
# The variant of the hash function (0: argon2d, 1: argon2i, or 2: argon2id) [1]
|
|
251
251
|
# HASH_TYPE=2
|
|
252
252
|
|
|
253
|
-
An extra and optional non-secret value. The value will be included B64 encoded in the parameters portion of the digest []
|
|
253
|
+
# An extra and optional non-secret value. The value will be included B64 encoded in the parameters portion of the digest []
|
|
254
254
|
# HASH_ASSOCIATED_DATA=foo
|
|
255
255
|
|
|
256
256
|
####################################################################################################
|
|
@@ -287,7 +287,7 @@ EXTENSIONS_AUTO_RELOAD=false
|
|
|
287
287
|
# Email address from which emails are sent ["no-reply@directus.io"]
|
|
288
288
|
EMAIL_FROM="no-reply@directus.io"
|
|
289
289
|
|
|
290
|
-
# What to use to send emails. One of
|
|
290
|
+
# What to use to send emails. One of
|
|
291
291
|
# sendmail, smtp, mailgun, ses.
|
|
292
292
|
EMAIL_TRANSPORT="sendmail"
|
|
293
293
|
EMAIL_SENDMAIL_NEW_LINE="unix"
|
|
@@ -3,6 +3,7 @@ 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
|
+
const utils_1 = require("@directus/shared/utils");
|
|
6
7
|
const express_1 = require("express");
|
|
7
8
|
const helmet_1 = __importDefault(require("helmet"));
|
|
8
9
|
const lodash_1 = require("lodash");
|
|
@@ -16,10 +17,9 @@ const services_1 = require("../services");
|
|
|
16
17
|
const assets_1 = require("../types/assets");
|
|
17
18
|
const async_handler_1 = __importDefault(require("../utils/async-handler"));
|
|
18
19
|
const get_config_from_env_1 = require("../utils/get-config-from-env");
|
|
19
|
-
const parse_json_1 = require("../utils/parse-json");
|
|
20
20
|
const router = (0, express_1.Router)();
|
|
21
21
|
router.use((0, use_collection_1.default)('directus_files'));
|
|
22
|
-
router.get('/:pk',
|
|
22
|
+
router.get('/:pk/:filename?',
|
|
23
23
|
// Validate query params
|
|
24
24
|
(0, async_handler_1.default)(async (req, res, next) => {
|
|
25
25
|
const payloadService = new services_1.PayloadService('directus_settings', { schema: req.schema });
|
|
@@ -41,7 +41,7 @@ router.get('/:pk',
|
|
|
41
41
|
let transforms;
|
|
42
42
|
// Try parse the JSON array
|
|
43
43
|
try {
|
|
44
|
-
transforms = (0,
|
|
44
|
+
transforms = (0, utils_1.parseJSON)(transformation['transforms']);
|
|
45
45
|
}
|
|
46
46
|
catch {
|
|
47
47
|
throw new exceptions_1.InvalidQueryException(`"transforms" Parameter needs to be a JSON array of allowed transformations.`);
|
|
@@ -99,7 +99,7 @@ router.get('/:pk',
|
|
|
99
99
|
}, (0, get_config_from_env_1.getConfigFromEnv)('ASSETS_CONTENT_SECURITY_POLICY'))),
|
|
100
100
|
// Return file
|
|
101
101
|
(0, async_handler_1.default)(async (req, res) => {
|
|
102
|
-
var _a, _b;
|
|
102
|
+
var _a, _b, _c;
|
|
103
103
|
const id = (_a = req.params.pk) === null || _a === void 0 ? void 0 : _a.substring(0, 36);
|
|
104
104
|
const service = new services_1.AssetsService({
|
|
105
105
|
accountability: req.accountability,
|
|
@@ -121,7 +121,7 @@ router.get('/:pk',
|
|
|
121
121
|
}
|
|
122
122
|
const { stream, file, stat } = await service.getAsset(id, transformation, range);
|
|
123
123
|
const access = ((_b = req.accountability) === null || _b === void 0 ? void 0 : _b.role) ? 'private' : 'public';
|
|
124
|
-
res.attachment(file.filename_download);
|
|
124
|
+
res.attachment((_c = req.params.filename) !== null && _c !== void 0 ? _c : file.filename_download);
|
|
125
125
|
res.setHeader('Content-Type', file.type);
|
|
126
126
|
res.setHeader('Accept-Ranges', 'bytes');
|
|
127
127
|
res.setHeader('Cache-Control', `${access}, max-age=${(0, ms_1.default)(env_1.default.ASSETS_CACHE_TTL) / 1000}`);
|
|
@@ -75,7 +75,10 @@ router.patch('/', (0, validate_batch_1.validateBatch)('update'), (0, async_handl
|
|
|
75
75
|
schema: req.schema,
|
|
76
76
|
});
|
|
77
77
|
let keys = [];
|
|
78
|
-
if (req.body
|
|
78
|
+
if (Array.isArray(req.body)) {
|
|
79
|
+
keys = await service.updateBatch(req.body);
|
|
80
|
+
}
|
|
81
|
+
else if (req.body.keys) {
|
|
79
82
|
keys = await service.updateMany(req.body.keys, req.body.data);
|
|
80
83
|
}
|
|
81
84
|
else {
|
|
@@ -32,7 +32,7 @@ const multipartHandler = (req, res, next) => {
|
|
|
32
32
|
'content-type': 'application/octet-stream',
|
|
33
33
|
};
|
|
34
34
|
}
|
|
35
|
-
const busboy =
|
|
35
|
+
const busboy = (0, busboy_1.default)({ headers });
|
|
36
36
|
const savedFiles = [];
|
|
37
37
|
const service = new services_1.FilesService({ accountability: req.accountability, schema: req.schema });
|
|
38
38
|
const existingPrimaryKey = req.params.pk || undefined;
|
|
@@ -57,7 +57,7 @@ const multipartHandler = (req, res, next) => {
|
|
|
57
57
|
}
|
|
58
58
|
payload[fieldname] = fieldValue;
|
|
59
59
|
});
|
|
60
|
-
busboy.on('file', async (
|
|
60
|
+
busboy.on('file', async (_fieldname, fileStream, { filename, mimeType }) => {
|
|
61
61
|
if (!filename) {
|
|
62
62
|
return busboy.emit('error', new exceptions_1.InvalidPayloadException(`File is missing filename`));
|
|
63
63
|
}
|
|
@@ -68,7 +68,7 @@ const multipartHandler = (req, res, next) => {
|
|
|
68
68
|
const payloadWithRequiredFields = {
|
|
69
69
|
...payload,
|
|
70
70
|
filename_download: filename,
|
|
71
|
-
type:
|
|
71
|
+
type: mimeType,
|
|
72
72
|
storage: payload.storage || disk,
|
|
73
73
|
};
|
|
74
74
|
// Clear the payload for the next to-be-uploaded file
|
|
@@ -85,7 +85,7 @@ const multipartHandler = (req, res, next) => {
|
|
|
85
85
|
busboy.on('error', (error) => {
|
|
86
86
|
next(error);
|
|
87
87
|
});
|
|
88
|
-
busboy.on('
|
|
88
|
+
busboy.on('close', () => {
|
|
89
89
|
tryDone();
|
|
90
90
|
});
|
|
91
91
|
req.pipe(busboy);
|
|
@@ -204,7 +204,10 @@ router.patch('/', (0, validate_batch_1.validateBatch)('update'), (0, async_handl
|
|
|
204
204
|
schema: req.schema,
|
|
205
205
|
});
|
|
206
206
|
let keys = [];
|
|
207
|
-
if (req.body
|
|
207
|
+
if (Array.isArray(req.body)) {
|
|
208
|
+
keys = await service.updateBatch(req.body);
|
|
209
|
+
}
|
|
210
|
+
else if (req.body.keys) {
|
|
208
211
|
keys = await service.updateMany(req.body.keys, req.body.data);
|
|
209
212
|
}
|
|
210
213
|
else {
|
|
@@ -94,7 +94,10 @@ router.patch('/', (0, validate_batch_1.validateBatch)('update'), (0, async_handl
|
|
|
94
94
|
schema: req.schema,
|
|
95
95
|
});
|
|
96
96
|
let keys = [];
|
|
97
|
-
if (req.body
|
|
97
|
+
if (Array.isArray(req.body)) {
|
|
98
|
+
keys = await service.updateBatch(req.body);
|
|
99
|
+
}
|
|
100
|
+
else if (req.body.keys) {
|
|
98
101
|
keys = await service.updateMany(req.body.keys, req.body.data);
|
|
99
102
|
}
|
|
100
103
|
else {
|
|
@@ -84,7 +84,10 @@ router.patch('/', (0, validate_batch_1.validateBatch)('update'), (0, async_handl
|
|
|
84
84
|
schema: req.schema,
|
|
85
85
|
});
|
|
86
86
|
let keys = [];
|
|
87
|
-
if (req.body
|
|
87
|
+
if (Array.isArray(req.body)) {
|
|
88
|
+
keys = await service.updateBatch(req.body);
|
|
89
|
+
}
|
|
90
|
+
else if (req.body.keys) {
|
|
88
91
|
keys = await service.updateMany(req.body.keys, req.body.data);
|
|
89
92
|
}
|
|
90
93
|
else {
|