@directus/api 13.1.0 → 13.2.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 +4 -4
- package/dist/auth/drivers/ldap.js +3 -2
- package/dist/auth/drivers/local.js +1 -1
- package/dist/auth/drivers/oauth2.js +1 -1
- package/dist/auth/drivers/openid.js +1 -1
- package/dist/auth/drivers/saml.js +1 -1
- package/dist/auth.js +1 -1
- package/dist/cli/index.js +1 -1
- package/dist/controllers/activity.js +1 -1
- package/dist/controllers/assets.js +2 -2
- package/dist/controllers/auth.js +1 -1
- package/dist/controllers/collections.js +1 -1
- package/dist/controllers/dashboards.js +1 -1
- package/dist/controllers/extensions.js +11 -7
- package/dist/controllers/fields.js +1 -1
- package/dist/controllers/files.js +2 -2
- package/dist/controllers/flows.js +1 -1
- package/dist/controllers/folders.js +1 -1
- package/dist/controllers/items.js +1 -1
- package/dist/controllers/not-found.js +1 -1
- package/dist/controllers/notifications.js +1 -1
- package/dist/controllers/operations.js +1 -1
- package/dist/controllers/panels.js +1 -1
- package/dist/controllers/permissions.js +1 -1
- package/dist/controllers/presets.js +1 -1
- package/dist/controllers/relations.js +1 -1
- package/dist/controllers/roles.js +1 -1
- package/dist/controllers/schema.js +1 -1
- package/dist/controllers/server.js +1 -1
- package/dist/controllers/settings.js +1 -1
- package/dist/controllers/shares.js +1 -1
- package/dist/controllers/translations.js +1 -1
- package/dist/controllers/users.js +1 -1
- package/dist/controllers/utils.js +37 -18
- package/dist/controllers/webhooks.js +1 -1
- package/dist/database/errors/dialects/mssql.js +1 -1
- package/dist/database/errors/dialects/mysql.js +1 -1
- package/dist/database/errors/dialects/oracle.js +1 -1
- package/dist/database/errors/dialects/postgres.js +1 -1
- package/dist/database/errors/dialects/sqlite.js +1 -1
- package/dist/database/helpers/schema/dialects/mysql.js +1 -1
- package/dist/database/helpers/sequence/dialects/postgres.d.ts +5 -2
- package/dist/database/helpers/sequence/dialects/postgres.js +6 -3
- package/dist/database/migrations/20231009A-update-csv-fields-to-text.d.ts +3 -0
- package/dist/database/migrations/20231009A-update-csv-fields-to-text.js +44 -0
- package/dist/database/run-ast.js +1 -1
- package/dist/database/seeds/run.js +1 -1
- package/dist/env.js +2 -2
- package/dist/extensions/get-extensions.d.ts +47 -0
- package/dist/extensions/get-extensions.js +9 -0
- package/dist/extensions/get-shared-deps-mapping.d.ts +1 -0
- package/dist/extensions/get-shared-deps-mapping.js +26 -0
- package/dist/extensions/index.d.ts +2 -0
- package/dist/extensions/index.js +9 -0
- package/dist/{extensions.d.ts → extensions/manager.d.ts} +4 -11
- package/dist/{extensions.js → extensions/manager.js} +28 -86
- package/dist/extensions/normalize-extension-info.d.ts +5 -0
- package/dist/extensions/normalize-extension-info.js +30 -0
- package/dist/extensions/types.d.ts +23 -0
- package/dist/extensions/wrap-embeds.d.ts +4 -0
- package/dist/extensions/wrap-embeds.js +8 -0
- package/dist/flows.d.ts +1 -1
- package/dist/flows.js +1 -1
- package/dist/middleware/check-ip.js +1 -1
- package/dist/middleware/collection-exists.js +1 -1
- package/dist/middleware/error-handler.js +1 -1
- package/dist/middleware/graphql.js +1 -1
- package/dist/middleware/rate-limiter-global.js +1 -1
- package/dist/middleware/rate-limiter-ip.js +1 -1
- package/dist/middleware/respond.js +1 -1
- package/dist/middleware/validate-batch.js +1 -1
- package/dist/operations/condition/index.d.ts +1 -1
- package/dist/operations/condition/index.js +2 -1
- package/dist/operations/exec/index.d.ts +1 -1
- package/dist/operations/exec/index.js +1 -1
- package/dist/operations/item-create/index.d.ts +1 -1
- package/dist/operations/item-create/index.js +2 -1
- package/dist/operations/item-delete/index.d.ts +1 -1
- package/dist/operations/item-delete/index.js +2 -1
- package/dist/operations/item-read/index.d.ts +1 -1
- package/dist/operations/item-read/index.js +2 -1
- package/dist/operations/item-update/index.d.ts +1 -1
- package/dist/operations/item-update/index.js +2 -1
- package/dist/operations/json-web-token/index.d.ts +1 -1
- package/dist/operations/json-web-token/index.js +2 -1
- package/dist/operations/log/index.d.ts +1 -1
- package/dist/operations/log/index.js +2 -1
- package/dist/operations/mail/index.d.ts +1 -1
- package/dist/operations/mail/index.js +1 -1
- package/dist/operations/notification/index.d.ts +1 -1
- package/dist/operations/notification/index.js +2 -1
- package/dist/operations/request/index.d.ts +1 -1
- package/dist/operations/request/index.js +3 -2
- package/dist/operations/sleep/index.d.ts +1 -1
- package/dist/operations/sleep/index.js +1 -1
- package/dist/operations/transform/index.d.ts +1 -1
- package/dist/operations/transform/index.js +2 -1
- package/dist/operations/trigger/index.d.ts +1 -1
- package/dist/operations/trigger/index.js +2 -1
- package/dist/services/activity.js +1 -1
- package/dist/services/assets.d.ts +1 -1
- package/dist/services/assets.js +2 -2
- package/dist/services/authentication.js +2 -2
- package/dist/services/authorization.js +1 -1
- package/dist/services/collections.js +3 -3
- package/dist/services/fields.d.ts +2 -2
- package/dist/services/fields.js +4 -4
- package/dist/services/files.d.ts +4 -1
- package/dist/services/files.js +6 -6
- package/dist/services/graphql/index.js +2 -2
- package/dist/services/graphql/subscription.js +3 -3
- package/dist/services/import-export/import-worker.d.ts +9 -0
- package/dist/services/import-export/import-worker.js +9 -0
- package/dist/services/{import-export.d.ts → import-export/index.d.ts} +2 -2
- package/dist/services/{import-export.js → import-export/index.js} +51 -42
- package/dist/services/index.d.ts +1 -1
- package/dist/services/index.js +1 -1
- package/dist/services/items.js +2 -2
- package/dist/services/mail/index.js +1 -1
- package/dist/services/meta.js +1 -1
- package/dist/services/payload.js +1 -1
- package/dist/services/permissions.d.ts +2 -2
- package/dist/services/permissions.js +1 -1
- package/dist/services/relations.js +1 -1
- package/dist/services/revisions.js +1 -1
- package/dist/services/roles.js +1 -1
- package/dist/services/schema.js +1 -1
- package/dist/services/shares.js +1 -1
- package/dist/services/tfa.js +1 -1
- package/dist/services/translations.js +1 -1
- package/dist/services/users.d.ts +4 -0
- package/dist/services/users.js +21 -2
- package/dist/services/utils.d.ts +1 -0
- package/dist/services/utils.js +8 -2
- package/dist/services/websocket.js +11 -1
- package/dist/types/index.d.ts +0 -1
- package/dist/types/index.js +0 -1
- package/dist/utils/apply-query.js +1 -1
- package/dist/utils/get-accountability-for-token.js +1 -1
- package/dist/utils/get-ast-from-query.js +1 -1
- package/dist/utils/get-column-path.js +1 -1
- package/dist/utils/get-column.js +1 -1
- package/dist/utils/get-default-value.d.ts +1 -2
- package/dist/utils/get-permissions.js +1 -1
- package/dist/utils/jwt.js +1 -1
- package/dist/utils/redact-object.js +9 -3
- package/dist/utils/transformations.d.ts +2 -1
- package/dist/utils/validate-diff.js +1 -1
- package/dist/utils/validate-keys.js +1 -1
- package/dist/utils/validate-query.js +1 -1
- package/dist/utils/validate-snapshot.js +1 -1
- package/dist/websocket/controllers/base.js +1 -1
- package/dist/websocket/controllers/index.d.ts +1 -1
- package/dist/websocket/controllers/index.js +0 -7
- package/dist/websocket/handlers/heartbeat.js +6 -1
- package/dist/websocket/handlers/subscribe.js +11 -16
- package/dist/websocket/utils/items.d.ts +4 -14
- package/dist/websocket/utils/items.js +59 -64
- package/dist/worker-pool.d.ts +2 -0
- package/dist/worker-pool.js +11 -0
- package/package.json +24 -22
- package/dist/errors/codes.d.ts +0 -29
- package/dist/errors/codes.js +0 -30
- package/dist/errors/contains-null-values.d.ts +0 -7
- package/dist/errors/contains-null-values.js +0 -4
- package/dist/errors/content-too-large.d.ts +0 -1
- package/dist/errors/content-too-large.js +0 -3
- package/dist/errors/forbidden.d.ts +0 -1
- package/dist/errors/forbidden.js +0 -3
- package/dist/errors/hit-rate-limit.d.ts +0 -6
- package/dist/errors/hit-rate-limit.js +0 -8
- package/dist/errors/illegal-asset-transformation.d.ts +0 -4
- package/dist/errors/illegal-asset-transformation.js +0 -3
- package/dist/errors/index.d.ts +0 -28
- package/dist/errors/index.js +0 -28
- package/dist/errors/invalid-credentials.d.ts +0 -1
- package/dist/errors/invalid-credentials.js +0 -3
- package/dist/errors/invalid-foreign-key.d.ts +0 -6
- package/dist/errors/invalid-foreign-key.js +0 -14
- package/dist/errors/invalid-ip.d.ts +0 -1
- package/dist/errors/invalid-ip.js +0 -3
- package/dist/errors/invalid-otp.d.ts +0 -1
- package/dist/errors/invalid-otp.js +0 -3
- package/dist/errors/invalid-payload.d.ts +0 -5
- package/dist/errors/invalid-payload.js +0 -4
- package/dist/errors/invalid-provider-config.d.ts +0 -5
- package/dist/errors/invalid-provider-config.js +0 -3
- package/dist/errors/invalid-provider.d.ts +0 -1
- package/dist/errors/invalid-provider.js +0 -3
- package/dist/errors/invalid-query.d.ts +0 -5
- package/dist/errors/invalid-query.js +0 -4
- package/dist/errors/invalid-token.d.ts +0 -1
- package/dist/errors/invalid-token.js +0 -3
- package/dist/errors/method-not-allowed.d.ts +0 -6
- package/dist/errors/method-not-allowed.js +0 -6
- package/dist/errors/not-null-violation.d.ts +0 -6
- package/dist/errors/not-null-violation.js +0 -14
- package/dist/errors/range-not-satisfiable.d.ts +0 -7
- package/dist/errors/range-not-satisfiable.js +0 -7
- package/dist/errors/record-not-unique.d.ts +0 -6
- package/dist/errors/record-not-unique.js +0 -14
- package/dist/errors/route-not-found.d.ts +0 -5
- package/dist/errors/route-not-found.js +0 -4
- package/dist/errors/service-unavailable.d.ts +0 -7
- package/dist/errors/service-unavailable.js +0 -4
- package/dist/errors/token-expired.d.ts +0 -1
- package/dist/errors/token-expired.js +0 -3
- package/dist/errors/unexpected-response.d.ts +0 -1
- package/dist/errors/unexpected-response.js +0 -3
- package/dist/errors/unprocessable-content.d.ts +0 -5
- package/dist/errors/unprocessable-content.js +0 -4
- package/dist/errors/unsupported-media-type.d.ts +0 -6
- package/dist/errors/unsupported-media-type.js +0 -4
- package/dist/errors/user-suspended.d.ts +0 -1
- package/dist/errors/user-suspended.js +0 -3
- package/dist/errors/value-out-of-range.d.ts +0 -6
- package/dist/errors/value-out-of-range.js +0 -14
- package/dist/errors/value-too-long.d.ts +0 -6
- package/dist/errors/value-too-long.js +0 -14
- package/dist/types/files.d.ts +0 -29
- /package/dist/{types/files.js → extensions/types.js} +0 -0
package/dist/services/roles.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ForbiddenError, UnprocessableContentError } from '
|
|
1
|
+
import { ForbiddenError, UnprocessableContentError } from '@directus/errors';
|
|
2
2
|
import { ItemsService } from './items.js';
|
|
3
3
|
import { PermissionsService } from './permissions.js';
|
|
4
4
|
import { PresetsService } from './presets.js';
|
package/dist/services/schema.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import getDatabase from '../database/index.js';
|
|
2
|
-
import { ForbiddenError } from '
|
|
2
|
+
import { ForbiddenError } from '@directus/errors';
|
|
3
3
|
import { applyDiff } from '../utils/apply-diff.js';
|
|
4
4
|
import { getSnapshotDiff } from '../utils/get-snapshot-diff.js';
|
|
5
5
|
import { getSnapshot } from '../utils/get-snapshot.js';
|
package/dist/services/shares.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import argon2 from 'argon2';
|
|
2
2
|
import jwt from 'jsonwebtoken';
|
|
3
3
|
import env from '../env.js';
|
|
4
|
-
import { ForbiddenError, InvalidCredentialsError } from '
|
|
4
|
+
import { ForbiddenError, InvalidCredentialsError } from '@directus/errors';
|
|
5
5
|
import { getMilliseconds } from '../utils/get-milliseconds.js';
|
|
6
6
|
import { md } from '../utils/md.js';
|
|
7
7
|
import { Url } from '../utils/url.js';
|
package/dist/services/tfa.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { authenticator } from 'otplib';
|
|
2
2
|
import getDatabase from '../database/index.js';
|
|
3
|
-
import { InvalidPayloadError } from '
|
|
3
|
+
import { InvalidPayloadError } from '@directus/errors';
|
|
4
4
|
import { ItemsService } from './items.js';
|
|
5
5
|
export class TFAService {
|
|
6
6
|
knex;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import getDatabase from '../database/index.js';
|
|
2
|
-
import { InvalidPayloadError } from '
|
|
2
|
+
import { InvalidPayloadError } from '@directus/errors';
|
|
3
3
|
import { ItemsService } from './items.js';
|
|
4
4
|
export class TranslationsService extends ItemsService {
|
|
5
5
|
constructor(options) {
|
package/dist/services/users.d.ts
CHANGED
|
@@ -26,6 +26,10 @@ export declare class UsersService extends ItemsService {
|
|
|
26
26
|
* Create url for inviting users
|
|
27
27
|
*/
|
|
28
28
|
private inviteUrl;
|
|
29
|
+
/**
|
|
30
|
+
* Validate array of emails. Intended to be used with create/update users
|
|
31
|
+
*/
|
|
32
|
+
private validateEmail;
|
|
29
33
|
/**
|
|
30
34
|
* Create a new user
|
|
31
35
|
*/
|
package/dist/services/users.js
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import { getSimpleHash, toArray } from '@directus/utils';
|
|
2
2
|
import { FailedValidationError, joiValidationErrorItemToErrorExtensions } from '@directus/validation';
|
|
3
|
+
import Joi from 'joi';
|
|
3
4
|
import jwt from 'jsonwebtoken';
|
|
4
5
|
import { cloneDeep, isEmpty } from 'lodash-es';
|
|
5
6
|
import { performance } from 'perf_hooks';
|
|
6
7
|
import getDatabase from '../database/index.js';
|
|
7
8
|
import env from '../env.js';
|
|
8
|
-
import { ForbiddenError } from '
|
|
9
|
-
import { InvalidPayloadError, RecordNotUniqueError, UnprocessableContentError } from '
|
|
9
|
+
import { ForbiddenError } from '@directus/errors';
|
|
10
|
+
import { InvalidPayloadError, RecordNotUniqueError, UnprocessableContentError } from '@directus/errors';
|
|
10
11
|
import isUrlAllowed from '../utils/is-url-allowed.js';
|
|
11
12
|
import { verifyJWT } from '../utils/jwt.js';
|
|
12
13
|
import { stall } from '../utils/stall.js';
|
|
@@ -130,6 +131,22 @@ export class UsersService extends ItemsService {
|
|
|
130
131
|
inviteURL.setQuery('token', token);
|
|
131
132
|
return inviteURL.toString();
|
|
132
133
|
}
|
|
134
|
+
/**
|
|
135
|
+
* Validate array of emails. Intended to be used with create/update users
|
|
136
|
+
*/
|
|
137
|
+
validateEmail(input) {
|
|
138
|
+
const emails = Array.isArray(input) ? input : [input];
|
|
139
|
+
const schema = Joi.string().email().required();
|
|
140
|
+
for (const email of emails) {
|
|
141
|
+
const { error } = schema.validate(email);
|
|
142
|
+
if (error) {
|
|
143
|
+
throw new FailedValidationError({
|
|
144
|
+
field: 'email',
|
|
145
|
+
type: 'email',
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
}
|
|
133
150
|
/**
|
|
134
151
|
* Create a new user
|
|
135
152
|
*/
|
|
@@ -145,6 +162,7 @@ export class UsersService extends ItemsService {
|
|
|
145
162
|
const passwords = data['map']((payload) => payload['password']).filter((password) => password);
|
|
146
163
|
try {
|
|
147
164
|
if (emails.length) {
|
|
165
|
+
this.validateEmail(emails);
|
|
148
166
|
await this.checkUniqueEmails(emails);
|
|
149
167
|
}
|
|
150
168
|
if (passwords.length) {
|
|
@@ -212,6 +230,7 @@ export class UsersService extends ItemsService {
|
|
|
212
230
|
field: 'email',
|
|
213
231
|
});
|
|
214
232
|
}
|
|
233
|
+
this.validateEmail(data['email']);
|
|
215
234
|
await this.checkUniqueEmails([data['email']], keys[0]);
|
|
216
235
|
}
|
|
217
236
|
if (data['password']) {
|
package/dist/services/utils.d.ts
CHANGED
package/dist/services/utils.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
+
import { flushCaches, getCache } from '../cache.js';
|
|
1
2
|
import getDatabase from '../database/index.js';
|
|
2
3
|
import { systemCollectionRows } from '../database/system-data/collections/index.js';
|
|
3
4
|
import emitter from '../emitter.js';
|
|
4
|
-
import { ForbiddenError, InvalidPayloadError } from '
|
|
5
|
-
import { getCache } from '../cache.js';
|
|
5
|
+
import { ForbiddenError, InvalidPayloadError } from '@directus/errors';
|
|
6
6
|
import { shouldClearCache } from '../utils/should-clear-cache.js';
|
|
7
7
|
export class UtilsService {
|
|
8
8
|
knex;
|
|
@@ -112,4 +112,10 @@ export class UtilsService {
|
|
|
112
112
|
accountability: this.accountability,
|
|
113
113
|
});
|
|
114
114
|
}
|
|
115
|
+
async clearCache() {
|
|
116
|
+
if (this.accountability?.admin !== true) {
|
|
117
|
+
throw new ForbiddenError();
|
|
118
|
+
}
|
|
119
|
+
return flushCaches(true);
|
|
120
|
+
}
|
|
115
121
|
}
|
|
@@ -1,9 +1,19 @@
|
|
|
1
1
|
import { getWebSocketController } from '../websocket/controllers/index.js';
|
|
2
|
+
import { ServiceUnavailableError } from '@directus/errors';
|
|
3
|
+
import { toBoolean } from '../utils/to-boolean.js';
|
|
2
4
|
import emitter from '../emitter.js';
|
|
5
|
+
import env from '../env.js';
|
|
3
6
|
export class WebSocketService {
|
|
4
7
|
controller;
|
|
5
8
|
constructor() {
|
|
6
|
-
|
|
9
|
+
if (!toBoolean(env['WEBSOCKETS_ENABLED']) || !toBoolean(env['WEBSOCKETS_REST_ENABLED'])) {
|
|
10
|
+
throw new ServiceUnavailableError({ service: 'ws', reason: 'WebSocket server is disabled' });
|
|
11
|
+
}
|
|
12
|
+
const controller = getWebSocketController();
|
|
13
|
+
if (!controller) {
|
|
14
|
+
throw new ServiceUnavailableError({ service: 'ws', reason: 'WebSocket server is not initialized' });
|
|
15
|
+
}
|
|
16
|
+
this.controller = controller;
|
|
7
17
|
}
|
|
8
18
|
on(event, callback) {
|
|
9
19
|
emitter.onAction('websocket.' + event, callback);
|
package/dist/types/index.d.ts
CHANGED
package/dist/types/index.js
CHANGED
|
@@ -3,7 +3,7 @@ import { clone, isPlainObject } from 'lodash-es';
|
|
|
3
3
|
import { customAlphabet } from 'nanoid/non-secure';
|
|
4
4
|
import validate from 'uuid-validate';
|
|
5
5
|
import { getHelpers } from '../database/helpers/index.js';
|
|
6
|
-
import { InvalidQueryError } from '
|
|
6
|
+
import { InvalidQueryError } from '@directus/errors';
|
|
7
7
|
import { getColumnPath } from './get-column-path.js';
|
|
8
8
|
import { getColumn } from './get-column.js';
|
|
9
9
|
import { getRelationInfo } from './get-relation-info.js';
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import getDatabase from '../database/index.js';
|
|
2
2
|
import env from '../env.js';
|
|
3
|
-
import { InvalidCredentialsError } from '
|
|
3
|
+
import { InvalidCredentialsError } from '@directus/errors';
|
|
4
4
|
import isDirectusJWT from './is-directus-jwt.js';
|
|
5
5
|
import { verifyAccessJWT } from './jwt.js';
|
|
6
6
|
export async function getAccountabilityForToken(token, accountability) {
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
*/
|
|
4
4
|
import { REGEX_BETWEEN_PARENS } from '@directus/constants';
|
|
5
5
|
import { cloneDeep, isEmpty, mapKeys, omitBy, uniq } from 'lodash-es';
|
|
6
|
-
import { getRelationType } from '
|
|
6
|
+
import { getRelationType } from './get-relation-type.js';
|
|
7
7
|
export default async function getASTFromQuery(collection, query, schema, options) {
|
|
8
8
|
query = cloneDeep(query);
|
|
9
9
|
const accountability = options?.accountability;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { InvalidQueryError } from '
|
|
1
|
+
import { InvalidQueryError } from '@directus/errors';
|
|
2
2
|
import { getRelationInfo } from './get-relation-info.js';
|
|
3
3
|
/**
|
|
4
4
|
* Converts a Directus field list path to the correct SQL names based on the constructed alias map.
|
package/dist/utils/get-column.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { REGEX_BETWEEN_PARENS } from '@directus/constants';
|
|
2
2
|
import { getFunctionsForType } from '@directus/utils';
|
|
3
3
|
import { getFunctions } from '../database/helpers/index.js';
|
|
4
|
-
import { InvalidQueryError } from '
|
|
4
|
+
import { InvalidQueryError } from '@directus/errors';
|
|
5
5
|
import { applyFunctionToColumnName } from './apply-function-to-column-name.js';
|
|
6
6
|
/**
|
|
7
7
|
* Return column prefixed by table. If column includes functions (like `year(date_created)`), the
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import type { SchemaOverview } from '@directus/schema
|
|
2
|
-
import type { Column } from '@directus/schema';
|
|
1
|
+
import type { Column, SchemaOverview } from '@directus/schema';
|
|
3
2
|
import type { FieldMeta } from '@directus/types';
|
|
4
3
|
export default function getDefaultValue(column: SchemaOverview[string]['columns'][string] | Column, field?: {
|
|
5
4
|
special?: FieldMeta['special'];
|
|
@@ -8,7 +8,7 @@ import env from '../env.js';
|
|
|
8
8
|
import logger from '../logger.js';
|
|
9
9
|
import { RolesService } from '../services/roles.js';
|
|
10
10
|
import { UsersService } from '../services/users.js';
|
|
11
|
-
import { mergePermissions } from '
|
|
11
|
+
import { mergePermissions } from './merge-permissions.js';
|
|
12
12
|
import { mergePermissionsForShare } from './merge-permissions-for-share.js';
|
|
13
13
|
export async function getPermissions(accountability, schema) {
|
|
14
14
|
const database = getDatabase();
|
package/dist/utils/jwt.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import jwt from 'jsonwebtoken';
|
|
2
|
-
import { InvalidTokenError, ServiceUnavailableError, TokenExpiredError } from '
|
|
2
|
+
import { InvalidTokenError, ServiceUnavailableError, TokenExpiredError } from '@directus/errors';
|
|
3
3
|
export function verifyJWT(token, secret) {
|
|
4
4
|
let payload;
|
|
5
5
|
try {
|
|
@@ -12,7 +12,6 @@ import { isObject } from '@directus/utils';
|
|
|
12
12
|
export function redactObject(input, redact, replacement) {
|
|
13
13
|
const wildcardChars = ['*', '**'];
|
|
14
14
|
const clone = JSON.parse(JSON.stringify(input, getReplacer(replacement, redact.values)));
|
|
15
|
-
const visited = new WeakSet();
|
|
16
15
|
if (redact.keys) {
|
|
17
16
|
traverse(clone, redact.keys);
|
|
18
17
|
}
|
|
@@ -21,7 +20,6 @@ export function redactObject(input, redact, replacement) {
|
|
|
21
20
|
if (checkKeyPaths.length === 0) {
|
|
22
21
|
return;
|
|
23
22
|
}
|
|
24
|
-
visited.add(object);
|
|
25
23
|
const REDACTED_TEXT = replacement();
|
|
26
24
|
const globalCheckPaths = [];
|
|
27
25
|
for (const key of Object.keys(object)) {
|
|
@@ -73,7 +71,7 @@ export function redactObject(input, redact, replacement) {
|
|
|
73
71
|
}
|
|
74
72
|
}
|
|
75
73
|
const value = object[key];
|
|
76
|
-
if (isObject(value)
|
|
74
|
+
if (isObject(value)) {
|
|
77
75
|
traverse(value, [...globalCheckPaths, ...localCheckPaths]);
|
|
78
76
|
}
|
|
79
77
|
}
|
|
@@ -86,7 +84,15 @@ export function getReplacer(replacement, values) {
|
|
|
86
84
|
const filteredValues = values
|
|
87
85
|
? Object.entries(values).filter(([_k, v]) => typeof v === 'string' && v.length > 0)
|
|
88
86
|
: [];
|
|
87
|
+
const seen = new WeakSet();
|
|
89
88
|
return (_key, value) => {
|
|
89
|
+
// Skip circular values
|
|
90
|
+
if (isObject(value)) {
|
|
91
|
+
if (seen.has(value)) {
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
seen.add(value);
|
|
95
|
+
}
|
|
90
96
|
if (value instanceof Error) {
|
|
91
97
|
return {
|
|
92
98
|
name: value.name,
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import type { File
|
|
1
|
+
import type { File } from '@directus/types';
|
|
2
|
+
import type { Transformation, TransformationSet } from '../types/index.js';
|
|
2
3
|
export declare function resolvePreset({ transformationParams, acceptFormat }: TransformationSet, file: File): Transformation[];
|
|
3
4
|
/**
|
|
4
5
|
* Try to extract a file format from an array of `Transformation`'s.
|
|
@@ -2,7 +2,7 @@ import Joi from 'joi';
|
|
|
2
2
|
import { isPlainObject, uniq } from 'lodash-es';
|
|
3
3
|
import { stringify } from 'wellknown';
|
|
4
4
|
import env from '../env.js';
|
|
5
|
-
import { InvalidQueryError } from '
|
|
5
|
+
import { InvalidQueryError } from '@directus/errors';
|
|
6
6
|
import { calculateFieldDepth } from './calculate-field-depth.js';
|
|
7
7
|
const querySchema = Joi.object({
|
|
8
8
|
fields: Joi.array().items(Joi.string()),
|
|
@@ -2,7 +2,7 @@ import { TYPES } from '@directus/constants';
|
|
|
2
2
|
import Joi from 'joi';
|
|
3
3
|
import { ALIAS_TYPES } from '../constants.js';
|
|
4
4
|
import { getDatabaseClient } from '../database/index.js';
|
|
5
|
-
import { InvalidPayloadError } from '
|
|
5
|
+
import { InvalidPayloadError } from '@directus/errors';
|
|
6
6
|
import { DatabaseClients } from '../types/index.js';
|
|
7
7
|
import { version as currentDirectusVersion } from './package.js';
|
|
8
8
|
const snapshotJoiSchema = Joi.object({
|
|
@@ -5,7 +5,7 @@ import WebSocket, { WebSocketServer } from 'ws';
|
|
|
5
5
|
import { fromZodError } from 'zod-validation-error';
|
|
6
6
|
import emitter from '../../emitter.js';
|
|
7
7
|
import env from '../../env.js';
|
|
8
|
-
import { InvalidProviderConfigError, TokenExpiredError } from '
|
|
8
|
+
import { InvalidProviderConfigError, TokenExpiredError } from '@directus/errors';
|
|
9
9
|
import logger from '../../logger.js';
|
|
10
10
|
import { createRateLimiter } from '../../rate-limiter.js';
|
|
11
11
|
import { getAccountabilityForToken } from '../../utils/get-accountability-for-token.js';
|
|
@@ -3,7 +3,7 @@ import type { Server as httpServer } from 'http';
|
|
|
3
3
|
import { GraphQLSubscriptionController } from './graphql.js';
|
|
4
4
|
import { WebSocketController } from './rest.js';
|
|
5
5
|
export declare function createWebSocketController(server: httpServer): void;
|
|
6
|
-
export declare function getWebSocketController(): WebSocketController;
|
|
6
|
+
export declare function getWebSocketController(): WebSocketController | undefined;
|
|
7
7
|
export declare function createSubscriptionController(server: httpServer): void;
|
|
8
8
|
export declare function getSubscriptionController(): GraphQLSubscriptionController | undefined;
|
|
9
9
|
export * from './graphql.js';
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import env from '../../env.js';
|
|
2
|
-
import { ServiceUnavailableError } from '../../errors/index.js';
|
|
3
2
|
import { toBoolean } from '../../utils/to-boolean.js';
|
|
4
3
|
import { GraphQLSubscriptionController } from './graphql.js';
|
|
5
4
|
import { WebSocketController } from './rest.js';
|
|
@@ -11,12 +10,6 @@ export function createWebSocketController(server) {
|
|
|
11
10
|
}
|
|
12
11
|
}
|
|
13
12
|
export function getWebSocketController() {
|
|
14
|
-
if (!toBoolean(env['WEBSOCKETS_ENABLED']) || !toBoolean(env['WEBSOCKETS_REST_ENABLED'])) {
|
|
15
|
-
throw new ServiceUnavailableError({ service: 'ws', reason: 'WebSocket server is disabled' });
|
|
16
|
-
}
|
|
17
|
-
if (!websocketController) {
|
|
18
|
-
throw new ServiceUnavailableError({ service: 'ws', reason: 'WebSocket server is not initialized' });
|
|
19
|
-
}
|
|
20
13
|
return websocketController;
|
|
21
14
|
}
|
|
22
15
|
export function createSubscriptionController(server) {
|
|
@@ -4,12 +4,17 @@ import { toBoolean } from '../../utils/to-boolean.js';
|
|
|
4
4
|
import { WebSocketController, getWebSocketController } from '../controllers/index.js';
|
|
5
5
|
import { WebSocketMessage } from '../messages.js';
|
|
6
6
|
import { fmtMessage, getMessageType } from '../utils/message.js';
|
|
7
|
+
import { ServiceUnavailableError } from '@directus/errors';
|
|
7
8
|
const HEARTBEAT_FREQUENCY = Number(env['WEBSOCKETS_HEARTBEAT_PERIOD']) * 1000;
|
|
8
9
|
export class HeartbeatHandler {
|
|
9
10
|
pulse;
|
|
10
11
|
controller;
|
|
11
12
|
constructor(controller) {
|
|
12
|
-
|
|
13
|
+
controller = controller ?? getWebSocketController();
|
|
14
|
+
if (!controller) {
|
|
15
|
+
throw new ServiceUnavailableError({ service: 'ws', reason: 'WebSocket server is not initialized' });
|
|
16
|
+
}
|
|
17
|
+
this.controller = controller;
|
|
13
18
|
emitter.onAction('websocket.message', ({ client, message }) => {
|
|
14
19
|
try {
|
|
15
20
|
this.onMessage(client, WebSocketMessage.parse(message));
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import emitter from '../../emitter.js';
|
|
2
|
-
import { InvalidPayloadError } from '
|
|
2
|
+
import { InvalidPayloadError } from '@directus/errors';
|
|
3
3
|
import { getMessenger } from '../../messenger.js';
|
|
4
4
|
import { getSchema } from '../../utils/get-schema.js';
|
|
5
5
|
import { sanitizeQuery } from '../../utils/sanitize-query.js';
|
|
@@ -7,7 +7,7 @@ import { refreshAccountability } from '../authenticate.js';
|
|
|
7
7
|
import { WebSocketError, handleWebSocketError } from '../errors.js';
|
|
8
8
|
import { WebSocketSubscribeMessage } from '../messages.js';
|
|
9
9
|
import { fmtMessage, getMessageType } from '../utils/message.js';
|
|
10
|
-
import {
|
|
10
|
+
import { getPayload } from '../utils/items.js';
|
|
11
11
|
/**
|
|
12
12
|
* Handler responsible for subscriptions
|
|
13
13
|
*/
|
|
@@ -104,13 +104,17 @@ export class SubscribeHandler {
|
|
|
104
104
|
if (subscription.event !== undefined && event.action !== subscription.event) {
|
|
105
105
|
continue; // skip filtered events
|
|
106
106
|
}
|
|
107
|
+
if ('item' in subscription) {
|
|
108
|
+
if ('keys' in event && !event.keys.includes(subscription.item))
|
|
109
|
+
continue;
|
|
110
|
+
if ('key' in event && event.key !== subscription.item)
|
|
111
|
+
continue;
|
|
112
|
+
}
|
|
107
113
|
try {
|
|
108
114
|
client.accountability = await refreshAccountability(client.accountability);
|
|
109
|
-
const result =
|
|
110
|
-
? await getSinglePayload(subscription, client.accountability, schema, event)
|
|
111
|
-
: await getMultiPayload(subscription, client.accountability, schema, event);
|
|
115
|
+
const result = await getPayload(subscription, client.accountability, schema, event);
|
|
112
116
|
if (Array.isArray(result?.['data']) && result?.['data']?.length === 0)
|
|
113
|
-
|
|
117
|
+
continue;
|
|
114
118
|
client.send(fmtMessage('subscription', result, subscription.uid));
|
|
115
119
|
}
|
|
116
120
|
catch (err) {
|
|
@@ -147,16 +151,7 @@ export class SubscribeHandler {
|
|
|
147
151
|
// remove the subscription if it already exists
|
|
148
152
|
this.unsubscribe(client, subscription.uid);
|
|
149
153
|
}
|
|
150
|
-
|
|
151
|
-
if (subscription.event === undefined) {
|
|
152
|
-
data =
|
|
153
|
-
'item' in subscription
|
|
154
|
-
? await getSinglePayload(subscription, accountability, schema)
|
|
155
|
-
: await getMultiPayload(subscription, accountability, schema);
|
|
156
|
-
}
|
|
157
|
-
else {
|
|
158
|
-
data = { event: 'init' };
|
|
159
|
-
}
|
|
154
|
+
const data = subscription.event === undefined ? await getPayload(subscription, accountability, schema) : { event: 'init' };
|
|
160
155
|
// if no errors were thrown register the subscription
|
|
161
156
|
this.subscribe(subscription);
|
|
162
157
|
// send an initial response
|
|
@@ -2,16 +2,6 @@ import type { Accountability, SchemaOverview } from '@directus/types';
|
|
|
2
2
|
import type { WebSocketEvent } from '../messages.js';
|
|
3
3
|
import type { Subscription } from '../types.js';
|
|
4
4
|
type PSubscription = Omit<Subscription, 'client'>;
|
|
5
|
-
/**
|
|
6
|
-
* Get a single item from a collection using the appropriate service
|
|
7
|
-
*
|
|
8
|
-
* @param subscription Subscription object
|
|
9
|
-
* @param accountability Accountability object
|
|
10
|
-
* @param schema Schema object
|
|
11
|
-
* @param event Event data
|
|
12
|
-
* @returns the fetched item
|
|
13
|
-
*/
|
|
14
|
-
export declare function getSinglePayload(subscription: PSubscription, accountability: Accountability | null, schema: SchemaOverview, event?: WebSocketEvent): Promise<Record<string, any>>;
|
|
15
5
|
/**
|
|
16
6
|
* Get items from a collection using the appropriate service
|
|
17
7
|
*
|
|
@@ -21,7 +11,7 @@ export declare function getSinglePayload(subscription: PSubscription, accountabi
|
|
|
21
11
|
* @param event Event data
|
|
22
12
|
* @returns the fetched items
|
|
23
13
|
*/
|
|
24
|
-
export declare function
|
|
14
|
+
export declare function getPayload(subscription: PSubscription, accountability: Accountability | null, schema: SchemaOverview, event?: WebSocketEvent): Promise<Record<string, any>>;
|
|
25
15
|
/**
|
|
26
16
|
* Get collection items
|
|
27
17
|
*
|
|
@@ -30,7 +20,7 @@ export declare function getMultiPayload(subscription: PSubscription, accountabil
|
|
|
30
20
|
* @param event Event data
|
|
31
21
|
* @returns the fetched collection data
|
|
32
22
|
*/
|
|
33
|
-
export declare function getCollectionPayload(accountability: Accountability | null, schema: SchemaOverview, event?: WebSocketEvent): Promise<(string | number)[] | import("../../types/collection.js").Collection[]>;
|
|
23
|
+
export declare function getCollectionPayload(subscription: PSubscription, accountability: Accountability | null, schema: SchemaOverview, event?: WebSocketEvent): Promise<string | number | import("../../types/collection.js").Collection | (string | number)[] | import("../../types/collection.js").Collection[]>;
|
|
34
24
|
/**
|
|
35
25
|
* Get fields items
|
|
36
26
|
*
|
|
@@ -39,7 +29,7 @@ export declare function getCollectionPayload(accountability: Accountability | nu
|
|
|
39
29
|
* @param event Event data
|
|
40
30
|
* @returns the fetched field data
|
|
41
31
|
*/
|
|
42
|
-
export declare function getFieldsPayload(accountability: Accountability | null, schema: SchemaOverview, event?: WebSocketEvent): Promise<Record<string, any> | import("@directus/types").Field[] | (string | number)[]>;
|
|
32
|
+
export declare function getFieldsPayload(subscription: PSubscription, accountability: Accountability | null, schema: SchemaOverview, event?: WebSocketEvent): Promise<string | number | Record<string, any> | import("@directus/types").Field[] | (string | number)[]>;
|
|
43
33
|
/**
|
|
44
34
|
* Get items from a collection using the appropriate service
|
|
45
35
|
*
|
|
@@ -49,5 +39,5 @@ export declare function getFieldsPayload(accountability: Accountability | null,
|
|
|
49
39
|
* @param event Event data
|
|
50
40
|
* @returns the fetched data
|
|
51
41
|
*/
|
|
52
|
-
export declare function getItemsPayload(subscription: PSubscription, accountability: Accountability | null, schema: SchemaOverview, event?: WebSocketEvent): Promise<(string | number)[] | import("../../types/items.js").Item[]>;
|
|
42
|
+
export declare function getItemsPayload(subscription: PSubscription, accountability: Accountability | null, schema: SchemaOverview, event?: WebSocketEvent): Promise<string | number | import("../../types/items.js").Item | (string | number)[] | import("../../types/items.js").Item[]>;
|
|
53
43
|
export {};
|