directus 9.12.2 → 9.14.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/app.js +14 -5
- 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 +20 -25
- 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/emitter.js +12 -7
- 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.d.ts +1 -0
- package/dist/operations/item-read/index.js +8 -7
- 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 +12 -8
- package/dist/services/index.js +5 -1
- package/dist/services/items.d.ts +6 -1
- package/dist/services/items.js +43 -19
- package/dist/services/mail/index.js +8 -6
- package/dist/services/notifications.js +22 -11
- package/dist/services/operations.d.ts +1 -0
- package/dist/services/operations.js +6 -0
- package/dist/services/payload.js +13 -11
- 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];
|
|
@@ -169,13 +173,18 @@ async function createApp() {
|
|
|
169
173
|
// Set the App's base path according to the APIs public URL
|
|
170
174
|
const html = await fs_extra_1.default.readFile(adminPath, 'utf8');
|
|
171
175
|
const htmlWithBase = html.replace(/<base \/>/, `<base href="${adminUrl.toString({ rootRelative: true })}/" />`);
|
|
172
|
-
const
|
|
176
|
+
const sendHtml = (_req, res) => {
|
|
173
177
|
res.setHeader('Cache-Control', 'no-cache');
|
|
178
|
+
res.setHeader('Vary', 'Origin, Cache-Control');
|
|
174
179
|
res.send(htmlWithBase);
|
|
175
180
|
};
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
181
|
+
const setStaticHeaders = (res) => {
|
|
182
|
+
res.setHeader('Cache-Control', 'max-age=31536000, immutable');
|
|
183
|
+
res.setHeader('Vary', 'Origin, Cache-Control');
|
|
184
|
+
};
|
|
185
|
+
app.get('/admin', sendHtml);
|
|
186
|
+
app.use('/admin', express_1.default.static(path_1.default.join(adminPath, '..'), { setHeaders: setStaticHeaders }));
|
|
187
|
+
app.use('/admin/*', sendHtml);
|
|
179
188
|
}
|
|
180
189
|
// use the rate limiter - all routes for now
|
|
181
190
|
if (env_1.default.RATE_LIMITER_ENABLED === true) {
|
|
@@ -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
|
}
|
|
@@ -50,7 +51,10 @@ class OpenIDAuthDriver extends local_1.LocalAuthDriver {
|
|
|
50
51
|
...clientOptionsOverrides,
|
|
51
52
|
}));
|
|
52
53
|
})
|
|
53
|
-
.catch(
|
|
54
|
+
.catch((e) => {
|
|
55
|
+
logger_1.default.error(e, '[OpenID] Failed to fetch provider config');
|
|
56
|
+
process.exit(1);
|
|
57
|
+
});
|
|
54
58
|
});
|
|
55
59
|
}
|
|
56
60
|
generateCodeVerifier() {
|
|
@@ -88,7 +92,7 @@ class OpenIDAuthDriver extends local_1.LocalAuthDriver {
|
|
|
88
92
|
async getUserID(payload) {
|
|
89
93
|
if (!payload.code || !payload.codeVerifier) {
|
|
90
94
|
logger_1.default.trace('[OpenID] No code or codeVerifier in payload');
|
|
91
|
-
throw new
|
|
95
|
+
throw new exceptions_2.InvalidCredentialsException();
|
|
92
96
|
}
|
|
93
97
|
let tokenSet;
|
|
94
98
|
let userInfo;
|
|
@@ -114,7 +118,7 @@ class OpenIDAuthDriver extends local_1.LocalAuthDriver {
|
|
|
114
118
|
const identifier = userInfo[identifierKey !== null && identifierKey !== void 0 ? identifierKey : 'sub'] ? String(userInfo[identifierKey !== null && identifierKey !== void 0 ? identifierKey : 'sub']) : email;
|
|
115
119
|
if (!identifier) {
|
|
116
120
|
logger_1.default.warn(`[OpenID] Failed to find user identifier for provider "${provider}"`);
|
|
117
|
-
throw new
|
|
121
|
+
throw new exceptions_2.InvalidCredentialsException();
|
|
118
122
|
}
|
|
119
123
|
const userId = await this.fetchUserId(identifier);
|
|
120
124
|
if (userId) {
|
|
@@ -130,7 +134,7 @@ class OpenIDAuthDriver extends local_1.LocalAuthDriver {
|
|
|
130
134
|
// Is public registration allowed?
|
|
131
135
|
if (!allowPublicRegistration || !isEmailVerified) {
|
|
132
136
|
logger_1.default.trace(`[OpenID] User doesn't exist, and public registration not allowed for provider "${provider}"`);
|
|
133
|
-
throw new
|
|
137
|
+
throw new exceptions_2.InvalidCredentialsException();
|
|
134
138
|
}
|
|
135
139
|
await this.usersService.createOne({
|
|
136
140
|
provider,
|
|
@@ -150,7 +154,7 @@ class OpenIDAuthDriver extends local_1.LocalAuthDriver {
|
|
|
150
154
|
let authData = user.auth_data;
|
|
151
155
|
if (typeof authData === 'string') {
|
|
152
156
|
try {
|
|
153
|
-
authData = (0,
|
|
157
|
+
authData = (0, utils_1.parseJSON)(authData);
|
|
154
158
|
}
|
|
155
159
|
catch {
|
|
156
160
|
logger_1.default.warn(`[OpenID] Session data isn't valid JSON: ${authData}`);
|
|
@@ -179,11 +183,11 @@ const handleError = (e) => {
|
|
|
179
183
|
if (e.error === 'invalid_grant') {
|
|
180
184
|
// Invalid token
|
|
181
185
|
logger_1.default.trace(e, `[OpenID] Invalid grant`);
|
|
182
|
-
return new
|
|
186
|
+
return new exceptions_2.InvalidTokenException();
|
|
183
187
|
}
|
|
184
188
|
// Server response error
|
|
185
189
|
logger_1.default.trace(e, `[OpenID] Unknown OP error`);
|
|
186
|
-
return new
|
|
190
|
+
return new exceptions_2.ServiceUnavailableException('Service returned unexpected response', {
|
|
187
191
|
service: 'openid',
|
|
188
192
|
message: e.error_description,
|
|
189
193
|
});
|
|
@@ -191,7 +195,7 @@ const handleError = (e) => {
|
|
|
191
195
|
else if (e instanceof openid_client_1.errors.RPError) {
|
|
192
196
|
// Internal client error
|
|
193
197
|
logger_1.default.trace(e, `[OpenID] Unknown RP error`);
|
|
194
|
-
return new
|
|
198
|
+
return new exceptions_2.InvalidCredentialsException();
|
|
195
199
|
}
|
|
196
200
|
logger_1.default.trace(e, `[OpenID] Unknown error`);
|
|
197
201
|
return e;
|
|
@@ -220,7 +224,7 @@ function createOpenIDAuthRouter(providerName) {
|
|
|
220
224
|
}
|
|
221
225
|
catch (e) {
|
|
222
226
|
logger_1.default.warn(e, `[OpenID] Couldn't verify OpenID cookie`);
|
|
223
|
-
throw new
|
|
227
|
+
throw new exceptions_2.InvalidCredentialsException();
|
|
224
228
|
}
|
|
225
229
|
const { verifier, redirect, prompt } = tokenData;
|
|
226
230
|
const authenticationService = new services_1.AuthenticationService({
|
|
@@ -245,23 +249,14 @@ function createOpenIDAuthRouter(providerName) {
|
|
|
245
249
|
}
|
|
246
250
|
catch (error) {
|
|
247
251
|
// Prompt user for a new refresh_token if invalidated
|
|
248
|
-
if (error instanceof
|
|
252
|
+
if (error instanceof exceptions_2.InvalidTokenException && !prompt) {
|
|
249
253
|
return res.redirect(`./?${redirect ? `redirect=${redirect}&` : ''}prompt=true`);
|
|
250
254
|
}
|
|
251
255
|
logger_1.default.warn(error);
|
|
252
256
|
if (redirect) {
|
|
253
257
|
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';
|
|
258
|
+
if (error instanceof exceptions_1.BaseException) {
|
|
259
|
+
reason = error.code;
|
|
265
260
|
}
|
|
266
261
|
else {
|
|
267
262
|
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 {
|