kuzzle 2.16.11 → 2.17.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/api/controllers/adminController.js +3 -3
- package/lib/api/controllers/authController.js +12 -12
- package/lib/api/controllers/baseController.js +60 -3
- package/lib/api/controllers/clusterController.js +1 -1
- package/lib/api/controllers/collectionController.js +7 -5
- package/lib/api/controllers/documentController.js +130 -17
- package/lib/api/controllers/indexController.js +1 -1
- package/lib/api/controllers/memoryStorageController.js +39 -38
- package/lib/api/controllers/realtimeController.js +1 -1
- package/lib/api/controllers/securityController.js +50 -50
- package/lib/api/controllers/serverController.js +73 -27
- package/lib/api/documentExtractor.js +3 -3
- package/lib/api/funnel.js +44 -21
- package/lib/api/httpRoutes.js +9 -4
- package/lib/api/openapi/OpenApiManager.d.ts +11 -0
- package/lib/api/openapi/OpenApiManager.js +96 -0
- package/lib/api/openapi/{document → components/document}/count.yaml +2 -2
- package/lib/api/openapi/{document → components/document}/create.yaml +2 -2
- package/lib/api/openapi/{document → components/document}/createOrReplace.yaml +2 -2
- package/lib/api/openapi/{document → components/document}/delete.yaml +1 -1
- package/lib/api/openapi/{document → components/document}/deleteByQuery.yaml +2 -2
- package/lib/api/openapi/{document → components/document}/exists.yaml +1 -1
- package/lib/api/openapi/{document → components/document}/get.yaml +1 -1
- package/lib/api/openapi/{document → components/document}/index.d.ts +2 -0
- package/lib/api/openapi/{document → components/document}/index.js +7 -2
- package/lib/api/openapi/{document → components/document}/replace.yaml +2 -2
- package/lib/api/openapi/{document → components/document}/scroll.yaml +1 -1
- package/lib/api/openapi/{document → components/document}/update.yaml +2 -2
- package/lib/api/openapi/components/document/validate.yaml +42 -0
- package/lib/api/openapi/components/index.d.ts +2 -0
- package/lib/api/openapi/components/index.js +18 -0
- package/lib/api/openapi/{payloads.yaml → components/payloads.yaml} +0 -0
- package/lib/api/openapi/index.d.ts +1 -2
- package/lib/api/openapi/index.js +1 -5
- package/lib/api/openapi/openApiGenerator.d.ts +7 -0
- package/lib/api/openapi/openApiGenerator.js +133 -0
- package/lib/api/request/kuzzleRequest.js +8 -6
- package/lib/cluster/node.js +9 -9
- package/lib/cluster/publisher.js +1 -1
- package/lib/cluster/state.js +20 -4
- package/lib/cluster/subscriber.js +1 -1
- package/lib/cluster/workers/IDCardRenewer.js +2 -2
- package/lib/config/default.config.js +1 -0
- package/lib/config/index.js +6 -6
- package/lib/core/auth/passportResponse.js +6 -6
- package/lib/core/auth/passportWrapper.js +5 -5
- package/lib/core/backend/backend.d.ts +11 -3
- package/lib/core/backend/backend.js +22 -17
- package/lib/core/backend/backendConfig.d.ts +5 -1
- package/lib/core/backend/backendConfig.js +25 -2
- package/lib/core/backend/backendController.js +21 -5
- package/lib/core/backend/backendErrors.d.ts +58 -0
- package/lib/core/backend/backendErrors.js +121 -0
- package/lib/core/backend/backendHook.js +21 -5
- package/lib/core/backend/backendImport.js +21 -5
- package/lib/core/backend/backendOpenApi.d.ts +9 -0
- package/lib/core/backend/backendOpenApi.js +69 -0
- package/lib/core/backend/backendPipe.js +21 -5
- package/lib/core/backend/backendPlugin.js +22 -3
- package/lib/core/backend/backendVault.js +21 -2
- package/lib/core/backend/index.d.ts +2 -0
- package/lib/core/backend/index.js +2 -0
- package/lib/core/network/accessLogger.js +6 -6
- package/lib/core/network/clientConnection.js +1 -1
- package/lib/core/network/entryPoint.js +5 -5
- package/lib/core/network/httpRouter/index.js +5 -5
- package/lib/core/network/httpRouter/routeHandler.js +3 -3
- package/lib/core/network/httpRouter/routePart.js +5 -5
- package/lib/core/network/protocolManifest.js +1 -1
- package/lib/core/network/protocols/httpMessage.js +2 -2
- package/lib/core/network/protocols/httpwsProtocol.js +228 -50
- package/lib/core/network/protocols/mqttProtocol.js +3 -3
- package/lib/core/network/protocols/protocol.js +3 -3
- package/lib/core/network/router.js +7 -6
- package/lib/core/plugin/plugin.js +38 -64
- package/lib/core/plugin/pluginContext.js +22 -3
- package/lib/core/plugin/pluginManifest.js +3 -3
- package/lib/core/plugin/pluginRepository.js +5 -5
- package/lib/core/plugin/pluginsManager.js +29 -28
- package/lib/core/realtime/channel.js +20 -4
- package/lib/core/realtime/hotelClerk.js +24 -5
- package/lib/core/realtime/notification/server.js +1 -1
- package/lib/core/realtime/notification/user.js +1 -1
- package/lib/core/realtime/notifier.js +5 -5
- package/lib/core/security/index.js +1 -1
- package/lib/core/security/profileRepository.d.ts +176 -0
- package/lib/core/security/profileRepository.js +445 -443
- package/lib/core/security/roleRepository.js +16 -16
- package/lib/core/security/securityLoader.js +2 -2
- package/lib/core/security/tokenRepository.js +11 -11
- package/lib/core/security/userRepository.js +8 -8
- package/lib/core/shared/abstractManifest.js +4 -4
- package/lib/core/shared/repository.js +5 -5
- package/lib/core/shared/sdk/embeddedSdk.js +21 -2
- package/lib/core/shared/sdk/funnelProtocol.js +1 -1
- package/lib/core/shared/sdk/impersonatedSdk.js +1 -1
- package/lib/core/shared/store.js +30 -23
- package/lib/core/statistics/statistics.js +17 -17
- package/lib/core/storage/clientAdapter.js +45 -10
- package/lib/core/storage/indexCache.js +20 -4
- package/lib/core/validation/baseType.js +5 -5
- package/lib/core/validation/types/anything.js +1 -1
- package/lib/core/validation/types/boolean.js +2 -2
- package/lib/core/validation/types/date.js +9 -9
- package/lib/core/validation/types/email.js +5 -5
- package/lib/core/validation/types/enum.js +6 -6
- package/lib/core/validation/types/geoPoint.js +2 -2
- package/lib/core/validation/types/geoShape.js +28 -25
- package/lib/core/validation/types/integer.js +4 -4
- package/lib/core/validation/types/ipAddress.js +7 -6
- package/lib/core/validation/types/numeric.js +4 -4
- package/lib/core/validation/types/object.js +5 -5
- package/lib/core/validation/types/string.js +5 -5
- package/lib/core/validation/types/url.js +7 -6
- package/lib/core/validation/validation.js +95 -84
- package/lib/kerror/codes/1-services.json +12 -0
- package/lib/kerror/codes/2-api.json +12 -0
- package/lib/kerror/codes/3-network.json +12 -0
- package/lib/kerror/codes/4-plugin.json +6 -0
- package/lib/kerror/codes/index.js +11 -11
- package/lib/kerror/errors/multipleErrorsError.d.ts +1 -1
- package/lib/kerror/errors/multipleErrorsError.js +3 -3
- package/lib/kerror/index.d.ts +82 -0
- package/lib/kerror/index.js +176 -143
- package/lib/kuzzle/dumpGenerator.js +3 -3
- package/lib/kuzzle/event/kuzzleEventEmitter.js +4 -4
- package/lib/kuzzle/event/pipeRunner.js +1 -1
- package/lib/kuzzle/event/waterfall.js +6 -6
- package/lib/kuzzle/kuzzle.js +59 -9
- package/lib/kuzzle/log.js +3 -3
- package/lib/kuzzle/vault.js +3 -3
- package/lib/model/security/profile.d.ts +54 -0
- package/lib/model/security/profile.js +192 -232
- package/lib/model/security/rights.js +1 -1
- package/lib/model/security/role.d.ts +40 -0
- package/lib/model/security/role.js +174 -190
- package/lib/model/security/user.d.ts +29 -0
- package/lib/model/security/user.js +103 -52
- package/lib/model/storage/apiKey.js +2 -2
- package/lib/model/storage/baseModel.js +3 -3
- package/lib/service/cache/redis.js +7 -7
- package/lib/service/storage/elasticsearch.js +152 -90
- package/lib/service/storage/esWrapper.js +2 -3
- package/lib/types/ControllerDefinition.d.ts +3 -3
- package/lib/types/ControllerRights.d.ts +22 -0
- package/lib/types/ControllerRights.js +23 -0
- package/lib/types/HttpStream.d.ts +32 -0
- package/lib/types/HttpStream.js +70 -0
- package/lib/types/OpenApiDefinition.d.ts +43 -0
- package/lib/types/{config/StorageService/StorageServiceElasticsearchConfiguration.js → OpenApiDefinition.js} +1 -1
- package/lib/types/Plugin.js +20 -4
- package/lib/types/Policy.d.ts +25 -0
- package/lib/types/{InternalLogger.js → Policy.js} +2 -2
- package/lib/types/PolicyRestrictions.d.ts +21 -0
- package/lib/types/PolicyRestrictions.js +23 -0
- package/lib/types/Target.d.ts +15 -0
- package/lib/types/Target.js +23 -0
- package/lib/types/config/KuzzleConfiguration.d.ts +4 -0
- package/lib/types/config/ServicesConfiguration.d.ts +2 -2
- package/lib/types/config/{StorageService/StorageServiceElasticsearchConfiguration.d.ts → storageEngine/StorageEngineElasticsearchConfiguration.d.ts} +10 -3
- package/lib/types/config/storageEngine/StorageEngineElasticsearchConfiguration.js +3 -0
- package/lib/types/errors/ErrorDefinition.d.ts +27 -0
- package/lib/types/errors/ErrorDefinition.js +3 -0
- package/lib/types/errors/ErrorDomains.d.ts +17 -0
- package/lib/types/errors/ErrorDomains.js +3 -0
- package/lib/types/index.d.ts +9 -1
- package/lib/types/index.js +9 -1
- package/lib/util/array.d.ts +11 -0
- package/lib/util/array.js +57 -0
- package/lib/util/assertType.js +6 -6
- package/lib/util/bufferedPassThrough.d.ts +76 -0
- package/lib/util/bufferedPassThrough.js +161 -0
- package/lib/util/deprecate.js +7 -5
- package/lib/util/didYouMean.js +1 -1
- package/lib/util/dump-collection.d.ts +3 -0
- package/lib/util/dump-collection.js +284 -0
- package/lib/util/extractFields.js +2 -2
- package/lib/util/inflector.d.ts +8 -0
- package/lib/util/inflector.js +16 -0
- package/lib/util/mutex.js +21 -2
- package/lib/util/requestAssertions.js +7 -7
- package/lib/util/wildcard.js +55 -0
- package/package-lock.json +535 -75
- package/package.json +5 -3
- package/lib/api/openApiGenerator.d.ts +0 -7
- package/lib/api/openApiGenerator.js +0 -197
- package/lib/types/InternalLogger.d.ts +0 -25
|
@@ -36,7 +36,7 @@ const assertionError = kerror.wrap('validation', 'assert');
|
|
|
36
36
|
* @class Validation
|
|
37
37
|
*/
|
|
38
38
|
class Validation {
|
|
39
|
-
constructor() {
|
|
39
|
+
constructor () {
|
|
40
40
|
/** @type {...ValidationType} */
|
|
41
41
|
this.types = {};
|
|
42
42
|
|
|
@@ -55,7 +55,7 @@ class Validation {
|
|
|
55
55
|
/**
|
|
56
56
|
* Walks through all types in "defaultTypesFiles" initializes all types
|
|
57
57
|
*/
|
|
58
|
-
init() {
|
|
58
|
+
init () {
|
|
59
59
|
[
|
|
60
60
|
'anything',
|
|
61
61
|
'boolean',
|
|
@@ -123,7 +123,8 @@ class Validation {
|
|
|
123
123
|
collectionSpec.strict,
|
|
124
124
|
errorMessages,
|
|
125
125
|
verbose);
|
|
126
|
-
}
|
|
126
|
+
}
|
|
127
|
+
catch (error) {
|
|
127
128
|
// The strictness message can be received here only if it happens at
|
|
128
129
|
// the validation of the document's root
|
|
129
130
|
if (error.message !== 'strictness') {
|
|
@@ -153,7 +154,7 @@ class Validation {
|
|
|
153
154
|
}
|
|
154
155
|
}
|
|
155
156
|
|
|
156
|
-
if (!verbose) {
|
|
157
|
+
if (! verbose) {
|
|
157
158
|
// We only modify the request if the validation succeeds
|
|
158
159
|
if (collectionSpec.fields && collectionSpec.fields.children) {
|
|
159
160
|
request.input.body = this.recurseApplyDefault(
|
|
@@ -165,7 +166,7 @@ class Validation {
|
|
|
165
166
|
return request;
|
|
166
167
|
}
|
|
167
168
|
|
|
168
|
-
return {errorMessages, valid: isValid};
|
|
169
|
+
return { errorMessages, valid: isValid };
|
|
169
170
|
}
|
|
170
171
|
|
|
171
172
|
/**
|
|
@@ -173,7 +174,7 @@ class Validation {
|
|
|
173
174
|
* @param {*} documentSubset
|
|
174
175
|
* @param {...StructuredFieldSpecification} collectionSpecSubset
|
|
175
176
|
*/
|
|
176
|
-
recurseApplyDefault(isUpdate, documentSubset, collectionSpecSubset) {
|
|
177
|
+
recurseApplyDefault (isUpdate, documentSubset, collectionSpecSubset) {
|
|
177
178
|
Object.keys(collectionSpecSubset).forEach(fieldName => {
|
|
178
179
|
const
|
|
179
180
|
specSubset = collectionSpecSubset[fieldName],
|
|
@@ -189,14 +190,16 @@ class Validation {
|
|
|
189
190
|
field[i],
|
|
190
191
|
specSubset.children);
|
|
191
192
|
}
|
|
192
|
-
}
|
|
193
|
+
}
|
|
194
|
+
else {
|
|
193
195
|
documentSubset[fieldName] = this.recurseApplyDefault(
|
|
194
196
|
isUpdate,
|
|
195
197
|
field,
|
|
196
198
|
specSubset.children);
|
|
197
199
|
}
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
+
}
|
|
201
|
+
else if (specSubset.defaultValue
|
|
202
|
+
&& (field === null || (! isUpdate && ! has(documentSubset, fieldName)))
|
|
200
203
|
) {
|
|
201
204
|
documentSubset[fieldName] = specSubset.defaultValue;
|
|
202
205
|
}
|
|
@@ -212,7 +215,7 @@ class Validation {
|
|
|
212
215
|
* @param {string[]} errorMessages
|
|
213
216
|
* @param {boolean} verbose
|
|
214
217
|
*/
|
|
215
|
-
recurseFieldValidation(
|
|
218
|
+
recurseFieldValidation (
|
|
216
219
|
documentSubset,
|
|
217
220
|
collectionSpecSubset,
|
|
218
221
|
strictness,
|
|
@@ -221,7 +224,7 @@ class Validation {
|
|
|
221
224
|
) {
|
|
222
225
|
if (strictness) {
|
|
223
226
|
for (const field of Object.keys(documentSubset)) {
|
|
224
|
-
if (!collectionSpecSubset[field]) {
|
|
227
|
+
if (! collectionSpecSubset[field]) {
|
|
225
228
|
const error = new Error('strictness');
|
|
226
229
|
error.details = { field };
|
|
227
230
|
throw error;
|
|
@@ -229,7 +232,7 @@ class Validation {
|
|
|
229
232
|
}
|
|
230
233
|
}
|
|
231
234
|
|
|
232
|
-
if (!verbose) {
|
|
235
|
+
if (! verbose) {
|
|
233
236
|
// We stop as soon as one field is not valid
|
|
234
237
|
return Object.keys(collectionSpecSubset).every(fieldName =>
|
|
235
238
|
this.isValidField(
|
|
@@ -262,7 +265,7 @@ class Validation {
|
|
|
262
265
|
* @param {boolean} verbose
|
|
263
266
|
* @returns {boolean}
|
|
264
267
|
*/
|
|
265
|
-
isValidField(
|
|
268
|
+
isValidField (
|
|
266
269
|
fieldName,
|
|
267
270
|
documentSubset,
|
|
268
271
|
collectionSpecSubset,
|
|
@@ -275,7 +278,7 @@ class Validation {
|
|
|
275
278
|
let result = true;
|
|
276
279
|
|
|
277
280
|
if (field.mandatory
|
|
278
|
-
&& !has(field, 'defaultValue')
|
|
281
|
+
&& ! has(field, 'defaultValue')
|
|
279
282
|
&& _.isNil(documentSubset[fieldName])
|
|
280
283
|
) {
|
|
281
284
|
manageErrorMessage(
|
|
@@ -286,13 +289,13 @@ class Validation {
|
|
|
286
289
|
return false;
|
|
287
290
|
}
|
|
288
291
|
|
|
289
|
-
if (!_.isNil(documentSubset[fieldName])) {
|
|
292
|
+
if (! _.isNil(documentSubset[fieldName])) {
|
|
290
293
|
let
|
|
291
294
|
nestedStrictness = false,
|
|
292
295
|
fieldValues;
|
|
293
296
|
|
|
294
297
|
if (field.multivalued.value) {
|
|
295
|
-
if (!Array.isArray(documentSubset[fieldName])) {
|
|
298
|
+
if (! Array.isArray(documentSubset[fieldName])) {
|
|
296
299
|
manageErrorMessage(
|
|
297
300
|
field.path,
|
|
298
301
|
errorMessages,
|
|
@@ -324,7 +327,8 @@ class Validation {
|
|
|
324
327
|
}
|
|
325
328
|
|
|
326
329
|
fieldValues = documentSubset[fieldName];
|
|
327
|
-
}
|
|
330
|
+
}
|
|
331
|
+
else {
|
|
328
332
|
if (Array.isArray(documentSubset[fieldName])) {
|
|
329
333
|
manageErrorMessage(
|
|
330
334
|
field.path,
|
|
@@ -346,7 +350,7 @@ class Validation {
|
|
|
346
350
|
for (const val of fieldValues) {
|
|
347
351
|
const fieldErrors = [];
|
|
348
352
|
|
|
349
|
-
if (!this.types[field.type].validate(
|
|
353
|
+
if (! this.types[field.type].validate(
|
|
350
354
|
field.typeOptions,
|
|
351
355
|
val,
|
|
352
356
|
fieldErrors)
|
|
@@ -358,7 +362,8 @@ class Validation {
|
|
|
358
362
|
errorMessages,
|
|
359
363
|
'An error has occurred during validation.',
|
|
360
364
|
verbose);
|
|
361
|
-
}
|
|
365
|
+
}
|
|
366
|
+
else {
|
|
362
367
|
fieldErrors.forEach(
|
|
363
368
|
message => manageErrorMessage(
|
|
364
369
|
field.path,
|
|
@@ -371,7 +376,7 @@ class Validation {
|
|
|
371
376
|
|
|
372
377
|
if (this.types[field.type].allowChildren && field.children) {
|
|
373
378
|
try {
|
|
374
|
-
if (!this.recurseFieldValidation(
|
|
379
|
+
if (! this.recurseFieldValidation(
|
|
375
380
|
val,
|
|
376
381
|
field.children,
|
|
377
382
|
nestedStrictness,
|
|
@@ -380,20 +385,23 @@ class Validation {
|
|
|
380
385
|
)) {
|
|
381
386
|
result = false;
|
|
382
387
|
}
|
|
383
|
-
}
|
|
388
|
+
}
|
|
389
|
+
catch (error) {
|
|
384
390
|
if (error.message === 'strictness') {
|
|
385
391
|
manageErrorMessage(
|
|
386
392
|
field.path,
|
|
387
393
|
errorMessages,
|
|
388
394
|
`The field is set to "strict"; cannot add unspecified sub-field "${error.details.field}".`,
|
|
389
395
|
verbose);
|
|
390
|
-
}
|
|
396
|
+
}
|
|
397
|
+
else if (verbose) {
|
|
391
398
|
manageErrorMessage(
|
|
392
399
|
field.path,
|
|
393
400
|
errorMessages,
|
|
394
401
|
error.message,
|
|
395
402
|
verbose);
|
|
396
|
-
}
|
|
403
|
+
}
|
|
404
|
+
else {
|
|
397
405
|
throw error;
|
|
398
406
|
}
|
|
399
407
|
|
|
@@ -408,7 +416,7 @@ class Validation {
|
|
|
408
416
|
/**
|
|
409
417
|
* @returns {Promise.<T>}
|
|
410
418
|
*/
|
|
411
|
-
curateSpecification() {
|
|
419
|
+
curateSpecification () {
|
|
412
420
|
const
|
|
413
421
|
promises = [],
|
|
414
422
|
specification = {};
|
|
@@ -428,7 +436,7 @@ class Validation {
|
|
|
428
436
|
)
|
|
429
437
|
.then(curatedSpec => {
|
|
430
438
|
|
|
431
|
-
if (!has(specification, indexName)) {
|
|
439
|
+
if (! has(specification, indexName)) {
|
|
432
440
|
specification[indexName] = {};
|
|
433
441
|
}
|
|
434
442
|
|
|
@@ -462,7 +470,7 @@ class Validation {
|
|
|
462
470
|
* @param {boolean} [verboseErrors]
|
|
463
471
|
* @returns {Promise<object>}
|
|
464
472
|
*/
|
|
465
|
-
validateFormat(
|
|
473
|
+
validateFormat (
|
|
466
474
|
indexName,
|
|
467
475
|
collectionName,
|
|
468
476
|
collectionSpec,
|
|
@@ -481,11 +489,11 @@ class Validation {
|
|
|
481
489
|
if (verboseErrors && result.isValid === false) {
|
|
482
490
|
return result;
|
|
483
491
|
}
|
|
484
|
-
return {isValid: true};
|
|
492
|
+
return { isValid: true };
|
|
485
493
|
})
|
|
486
494
|
// we do not want to reject since this method goal is
|
|
487
495
|
// to know what is going wrong with the given spec
|
|
488
|
-
.catch(error => ({errors: [error], isValid: false}));
|
|
496
|
+
.catch(error => ({ errors: [error], isValid: false }));
|
|
489
497
|
}
|
|
490
498
|
|
|
491
499
|
/**
|
|
@@ -497,7 +505,7 @@ class Validation {
|
|
|
497
505
|
* @returns {Promise<CollectionSpecification>}
|
|
498
506
|
* @rejects PreconditionError
|
|
499
507
|
*/
|
|
500
|
-
async curateCollectionSpecification(
|
|
508
|
+
async curateCollectionSpecification (
|
|
501
509
|
index,
|
|
502
510
|
collection,
|
|
503
511
|
spec,
|
|
@@ -512,14 +520,14 @@ class Validation {
|
|
|
512
520
|
};
|
|
513
521
|
const allowed = ['strict', 'fields', 'validators'];
|
|
514
522
|
|
|
515
|
-
if (!checkAllowedProperties(spec, allowed)) {
|
|
523
|
+
if (! checkAllowedProperties(spec, allowed)) {
|
|
516
524
|
error = assertionError.get(
|
|
517
525
|
'unexpected_properties',
|
|
518
526
|
`${index}.${collection}`,
|
|
519
527
|
allowed.join(', '));
|
|
520
528
|
|
|
521
529
|
if (verbose) {
|
|
522
|
-
return {errors: [error.message], isValid: false};
|
|
530
|
+
return { errors: [error.message], isValid: false };
|
|
523
531
|
}
|
|
524
532
|
|
|
525
533
|
throw error;
|
|
@@ -553,7 +561,7 @@ class Validation {
|
|
|
553
561
|
|
|
554
562
|
processed.validators = filterId;
|
|
555
563
|
}
|
|
556
|
-
catch(e) {
|
|
564
|
+
catch (e) {
|
|
557
565
|
global.kuzzle.log.error(e);
|
|
558
566
|
throw assertionError.getFrom(e, 'invalid_filters', e.message);
|
|
559
567
|
}
|
|
@@ -562,7 +570,7 @@ class Validation {
|
|
|
562
570
|
return processed;
|
|
563
571
|
}
|
|
564
572
|
|
|
565
|
-
structureCollectionValidation(
|
|
573
|
+
structureCollectionValidation (
|
|
566
574
|
collectionSpec,
|
|
567
575
|
indexName,
|
|
568
576
|
collectionName,
|
|
@@ -600,20 +608,21 @@ class Validation {
|
|
|
600
608
|
maxDepth = field.depth;
|
|
601
609
|
}
|
|
602
610
|
|
|
603
|
-
if (!fields[field.depth]) {
|
|
611
|
+
if (! fields[field.depth]) {
|
|
604
612
|
fields[field.depth] = [];
|
|
605
613
|
}
|
|
606
614
|
|
|
607
615
|
fields[field.depth].push(field);
|
|
608
616
|
}
|
|
609
|
-
}
|
|
617
|
+
}
|
|
618
|
+
catch (error) {
|
|
610
619
|
global.kuzzle.log.error(error);
|
|
611
620
|
throwOrStoreError(error, verboseErrors, errors);
|
|
612
621
|
}
|
|
613
622
|
}
|
|
614
623
|
|
|
615
624
|
if (errors.length > 0) {
|
|
616
|
-
return {errors, isValid: false};
|
|
625
|
+
return { errors, isValid: false };
|
|
617
626
|
}
|
|
618
627
|
|
|
619
628
|
if (Object.keys(fields).length > 0) {
|
|
@@ -631,7 +640,7 @@ class Validation {
|
|
|
631
640
|
* @returns {object}
|
|
632
641
|
* @throws PreconditionError
|
|
633
642
|
*/
|
|
634
|
-
curateFieldSpecification(
|
|
643
|
+
curateFieldSpecification (
|
|
635
644
|
fieldSpec,
|
|
636
645
|
indexName,
|
|
637
646
|
collectionName,
|
|
@@ -659,13 +668,13 @@ class Validation {
|
|
|
659
668
|
}
|
|
660
669
|
});
|
|
661
670
|
|
|
662
|
-
if (!has(fieldSpec, 'typeOptions')) {
|
|
671
|
+
if (! has(fieldSpec, 'typeOptions')) {
|
|
663
672
|
fieldSpec.typeOptions = {};
|
|
664
673
|
}
|
|
665
674
|
|
|
666
675
|
const allowed = this.types[fieldSpec.type].allowedTypeOptions || [];
|
|
667
676
|
|
|
668
|
-
if (!checkAllowedProperties(fieldSpec.typeOptions, allowed)) {
|
|
677
|
+
if (! checkAllowedProperties(fieldSpec.typeOptions, allowed)) {
|
|
669
678
|
throwOrStoreError(
|
|
670
679
|
assertionError.get(
|
|
671
680
|
'unexpected_properties',
|
|
@@ -678,8 +687,9 @@ class Validation {
|
|
|
678
687
|
try {
|
|
679
688
|
fieldSpec.typeOptions = this.types[fieldSpec.type]
|
|
680
689
|
.validateFieldSpecification(fieldSpec.typeOptions);
|
|
681
|
-
}
|
|
682
|
-
|
|
690
|
+
}
|
|
691
|
+
catch (e) {
|
|
692
|
+
if (! verboseErrors) {
|
|
683
693
|
if (e instanceof KuzzleError) {
|
|
684
694
|
throw e;
|
|
685
695
|
}
|
|
@@ -695,7 +705,7 @@ class Validation {
|
|
|
695
705
|
}
|
|
696
706
|
|
|
697
707
|
if (errors.length > 0) {
|
|
698
|
-
return {errors, isValid: false};
|
|
708
|
+
return { errors, isValid: false };
|
|
699
709
|
}
|
|
700
710
|
|
|
701
711
|
debug(
|
|
@@ -705,7 +715,7 @@ class Validation {
|
|
|
705
715
|
fieldName,
|
|
706
716
|
fieldSpec);
|
|
707
717
|
|
|
708
|
-
return {fieldSpec, isValid: true};
|
|
718
|
+
return { fieldSpec, isValid: true };
|
|
709
719
|
}
|
|
710
720
|
|
|
711
721
|
/**
|
|
@@ -717,7 +727,7 @@ class Validation {
|
|
|
717
727
|
* @returns {object}
|
|
718
728
|
* @throws PreconditionError
|
|
719
729
|
*/
|
|
720
|
-
curateFieldSpecificationFormat(
|
|
730
|
+
curateFieldSpecificationFormat (
|
|
721
731
|
fieldSpec,
|
|
722
732
|
indexName,
|
|
723
733
|
collectionName,
|
|
@@ -735,7 +745,7 @@ class Validation {
|
|
|
735
745
|
'typeOptions'
|
|
736
746
|
];
|
|
737
747
|
|
|
738
|
-
if (!checkAllowedProperties(fieldSpec, props)) {
|
|
748
|
+
if (! checkAllowedProperties(fieldSpec, props)) {
|
|
739
749
|
throwOrStoreError(
|
|
740
750
|
assertionError.get(
|
|
741
751
|
'unexpected_properties',
|
|
@@ -745,7 +755,7 @@ class Validation {
|
|
|
745
755
|
errors);
|
|
746
756
|
}
|
|
747
757
|
|
|
748
|
-
if (!has(fieldSpec, 'type')) {
|
|
758
|
+
if (! has(fieldSpec, 'type')) {
|
|
749
759
|
throwOrStoreError(
|
|
750
760
|
assertionError.get(
|
|
751
761
|
'missing_type',
|
|
@@ -754,7 +764,7 @@ class Validation {
|
|
|
754
764
|
errors);
|
|
755
765
|
}
|
|
756
766
|
|
|
757
|
-
if (!has(this.types, fieldSpec.type)) {
|
|
767
|
+
if (! has(this.types, fieldSpec.type)) {
|
|
758
768
|
throwOrStoreError(
|
|
759
769
|
assertionError.get(
|
|
760
770
|
'unknown_type',
|
|
@@ -766,7 +776,7 @@ class Validation {
|
|
|
766
776
|
|
|
767
777
|
if (has(fieldSpec, 'multivalued')) {
|
|
768
778
|
const multivaluedProps = ['value', 'minCount', 'maxCount'];
|
|
769
|
-
if (!checkAllowedProperties(fieldSpec.multivalued, multivaluedProps)) {
|
|
779
|
+
if (! checkAllowedProperties(fieldSpec.multivalued, multivaluedProps)) {
|
|
770
780
|
throwOrStoreError(
|
|
771
781
|
assertionError.get(
|
|
772
782
|
'unexpected_properties',
|
|
@@ -776,7 +786,7 @@ class Validation {
|
|
|
776
786
|
errors);
|
|
777
787
|
}
|
|
778
788
|
|
|
779
|
-
if (!has(fieldSpec.multivalued, 'value')) {
|
|
789
|
+
if (! has(fieldSpec.multivalued, 'value')) {
|
|
780
790
|
throwOrStoreError(
|
|
781
791
|
assertionError.get(
|
|
782
792
|
'missing_value',
|
|
@@ -796,7 +806,7 @@ class Validation {
|
|
|
796
806
|
}
|
|
797
807
|
|
|
798
808
|
for (const unexpected of ['minCount', 'maxCount']) {
|
|
799
|
-
if ( !fieldSpec.multivalued.value
|
|
809
|
+
if ( ! fieldSpec.multivalued.value
|
|
800
810
|
&& has(fieldSpec.multivalued, unexpected)
|
|
801
811
|
) {
|
|
802
812
|
throwOrStoreError(
|
|
@@ -825,10 +835,10 @@ class Validation {
|
|
|
825
835
|
}
|
|
826
836
|
|
|
827
837
|
if (errors.length > 0) {
|
|
828
|
-
return {errors, isValid: false};
|
|
838
|
+
return { errors, isValid: false };
|
|
829
839
|
}
|
|
830
840
|
|
|
831
|
-
return {isValid: true};
|
|
841
|
+
return { isValid: true };
|
|
832
842
|
}
|
|
833
843
|
|
|
834
844
|
/**
|
|
@@ -838,7 +848,7 @@ class Validation {
|
|
|
838
848
|
* @param {boolean} dryRun
|
|
839
849
|
* @returns {string}
|
|
840
850
|
*/
|
|
841
|
-
curateValidatorFilter(indexName, collectionName, validatorFilter, dryRun) {
|
|
851
|
+
curateValidatorFilter (indexName, collectionName, validatorFilter, dryRun) {
|
|
842
852
|
const query = {
|
|
843
853
|
bool: {
|
|
844
854
|
must: validatorFilter
|
|
@@ -847,7 +857,7 @@ class Validation {
|
|
|
847
857
|
|
|
848
858
|
this.koncorde.validate(query);
|
|
849
859
|
|
|
850
|
-
if (!dryRun) {
|
|
860
|
+
if (! dryRun) {
|
|
851
861
|
debug(
|
|
852
862
|
'Registering filter validator %s/%s: %O',
|
|
853
863
|
indexName,
|
|
@@ -866,12 +876,12 @@ class Validation {
|
|
|
866
876
|
* @param {ValidationType} validationType
|
|
867
877
|
* @throws {PluginImplementationError}
|
|
868
878
|
*/
|
|
869
|
-
addType(validationType) {
|
|
870
|
-
if (!validationType.typeName) {
|
|
879
|
+
addType (validationType) {
|
|
880
|
+
if (! validationType.typeName) {
|
|
871
881
|
throw kerror.get('validation', 'types', 'missing_type_name');
|
|
872
882
|
}
|
|
873
883
|
|
|
874
|
-
if ( !validationType.validate
|
|
884
|
+
if ( ! validationType.validate
|
|
875
885
|
|| typeof validationType.validate !== 'function'
|
|
876
886
|
) {
|
|
877
887
|
throw kerror.get(
|
|
@@ -882,7 +892,7 @@ class Validation {
|
|
|
882
892
|
'validate');
|
|
883
893
|
}
|
|
884
894
|
|
|
885
|
-
if ( !validationType.validateFieldSpecification
|
|
895
|
+
if ( ! validationType.validateFieldSpecification
|
|
886
896
|
|| typeof validationType.validateFieldSpecification !== 'function'
|
|
887
897
|
) {
|
|
888
898
|
throw kerror.get(
|
|
@@ -896,7 +906,7 @@ class Validation {
|
|
|
896
906
|
if (has(validationType, 'allowChildren')
|
|
897
907
|
&& validationType.allowChildren
|
|
898
908
|
) {
|
|
899
|
-
if (!validationType.getStrictness
|
|
909
|
+
if (! validationType.getStrictness
|
|
900
910
|
|| typeof validationType.getStrictness !== 'function'
|
|
901
911
|
) {
|
|
902
912
|
throw kerror.get(
|
|
@@ -928,13 +938,13 @@ class Validation {
|
|
|
928
938
|
* @param {string[]} allowedProperties
|
|
929
939
|
* @returns {boolean}
|
|
930
940
|
*/
|
|
931
|
-
function checkAllowedProperties(object, allowedProperties) {
|
|
932
|
-
if (!isPlainObject(object)) {
|
|
941
|
+
function checkAllowedProperties (object, allowedProperties) {
|
|
942
|
+
if (! isPlainObject(object)) {
|
|
933
943
|
return false;
|
|
934
944
|
}
|
|
935
945
|
|
|
936
|
-
return !Object.keys(object).some(
|
|
937
|
-
propertyName => !allowedProperties.includes(propertyName));
|
|
946
|
+
return ! Object.keys(object).some(
|
|
947
|
+
propertyName => ! allowedProperties.includes(propertyName));
|
|
938
948
|
}
|
|
939
949
|
|
|
940
950
|
/**
|
|
@@ -943,7 +953,7 @@ function checkAllowedProperties(object, allowedProperties) {
|
|
|
943
953
|
* @param {number} maxDepth : depth of the fields; counting starts at 1
|
|
944
954
|
* @throws PreconditionError
|
|
945
955
|
*/
|
|
946
|
-
function curateStructuredFields(typeAllowsChildren, fields, maxDepth) {
|
|
956
|
+
function curateStructuredFields (typeAllowsChildren, fields, maxDepth) {
|
|
947
957
|
const
|
|
948
958
|
/** @type StructuredFieldSpecification */
|
|
949
959
|
structuredFields = {
|
|
@@ -952,7 +962,7 @@ function curateStructuredFields(typeAllowsChildren, fields, maxDepth) {
|
|
|
952
962
|
};
|
|
953
963
|
|
|
954
964
|
for (let i = 1; i <= maxDepth; i++) {
|
|
955
|
-
if (!has(fields, i)) {
|
|
965
|
+
if (! has(fields, i)) {
|
|
956
966
|
throw assertionError.get('missing_nested_spec');
|
|
957
967
|
}
|
|
958
968
|
|
|
@@ -961,11 +971,11 @@ function curateStructuredFields(typeAllowsChildren, fields, maxDepth) {
|
|
|
961
971
|
parent = getParent(structuredFields, field.path),
|
|
962
972
|
childKey = field.path[field.path.length - 1];
|
|
963
973
|
|
|
964
|
-
if (!parent.root && typeAllowsChildren.indexOf(parent.type) === -1) {
|
|
974
|
+
if (! parent.root && typeAllowsChildren.indexOf(parent.type) === -1) {
|
|
965
975
|
throw assertionError.get('unexpected_children', parent.type);
|
|
966
976
|
}
|
|
967
977
|
|
|
968
|
-
if (!has(parent, 'children')) {
|
|
978
|
+
if (! has(parent, 'children')) {
|
|
969
979
|
parent.children = {};
|
|
970
980
|
}
|
|
971
981
|
|
|
@@ -981,7 +991,7 @@ function curateStructuredFields(typeAllowsChildren, fields, maxDepth) {
|
|
|
981
991
|
* @param {string[]}fieldPath
|
|
982
992
|
* @returns {StructuredFieldSpecification}
|
|
983
993
|
*/
|
|
984
|
-
function getParent(structuredFields, fieldPath) {
|
|
994
|
+
function getParent (structuredFields, fieldPath) {
|
|
985
995
|
if (fieldPath.length === 1) {
|
|
986
996
|
return structuredFields;
|
|
987
997
|
}
|
|
@@ -989,7 +999,7 @@ function getParent(structuredFields, fieldPath) {
|
|
|
989
999
|
let pointer = structuredFields;
|
|
990
1000
|
|
|
991
1001
|
for (let i = 0; i < fieldPath.length - 1; i++) {
|
|
992
|
-
if (!has(pointer.children, fieldPath[i])) {
|
|
1002
|
+
if (! has(pointer.children, fieldPath[i])) {
|
|
993
1003
|
throw assertionError.get('missing_parent', fieldPath.join('.'));
|
|
994
1004
|
}
|
|
995
1005
|
|
|
@@ -1004,8 +1014,8 @@ function getParent(structuredFields, fieldPath) {
|
|
|
1004
1014
|
* @param {boolean} doNotThrow
|
|
1005
1015
|
* @param {string[]} errors
|
|
1006
1016
|
*/
|
|
1007
|
-
function throwOrStoreError(error, doNotThrow, errorMessages) {
|
|
1008
|
-
if (!doNotThrow) {
|
|
1017
|
+
function throwOrStoreError (error, doNotThrow, errorMessages) {
|
|
1018
|
+
if (! doNotThrow) {
|
|
1009
1019
|
throw error;
|
|
1010
1020
|
}
|
|
1011
1021
|
|
|
@@ -1018,33 +1028,34 @@ function throwOrStoreError(error, doNotThrow, errorMessages) {
|
|
|
1018
1028
|
* @param {string} message
|
|
1019
1029
|
* @param {boolean} structured
|
|
1020
1030
|
*/
|
|
1021
|
-
function manageErrorMessage(errorContext, errorHolder, message, structured) {
|
|
1031
|
+
function manageErrorMessage (errorContext, errorHolder, message, structured) {
|
|
1022
1032
|
if (structured) {
|
|
1023
1033
|
if (errorContext === 'document') {
|
|
1024
|
-
if (!errorHolder.documentScope) {
|
|
1034
|
+
if (! errorHolder.documentScope) {
|
|
1025
1035
|
errorHolder.documentScope = [];
|
|
1026
1036
|
}
|
|
1027
1037
|
|
|
1028
1038
|
errorHolder.documentScope.push(message);
|
|
1029
|
-
}
|
|
1030
|
-
|
|
1039
|
+
}
|
|
1040
|
+
else {
|
|
1041
|
+
if (! errorHolder.fieldScope) {
|
|
1031
1042
|
errorHolder.fieldScope = {};
|
|
1032
1043
|
}
|
|
1033
1044
|
|
|
1034
1045
|
let pointer = errorHolder.fieldScope;
|
|
1035
1046
|
|
|
1036
1047
|
for (let i = 0; i < errorContext.length; i++) {
|
|
1037
|
-
if (!pointer.children) {
|
|
1048
|
+
if (! pointer.children) {
|
|
1038
1049
|
pointer.children = {};
|
|
1039
1050
|
}
|
|
1040
1051
|
|
|
1041
|
-
if (!has(pointer.children, errorContext[i])) {
|
|
1052
|
+
if (! has(pointer.children, errorContext[i])) {
|
|
1042
1053
|
pointer.children[errorContext[i]] = {};
|
|
1043
1054
|
}
|
|
1044
1055
|
pointer = pointer.children[errorContext[i]];
|
|
1045
1056
|
}
|
|
1046
1057
|
|
|
1047
|
-
if (!has(pointer, 'messages')) {
|
|
1058
|
+
if (! has(pointer, 'messages')) {
|
|
1048
1059
|
pointer.messages = [];
|
|
1049
1060
|
}
|
|
1050
1061
|
|
|
@@ -1070,9 +1081,9 @@ function manageErrorMessage(errorContext, errorHolder, message, structured) {
|
|
|
1070
1081
|
*
|
|
1071
1082
|
* @returns {Promise}
|
|
1072
1083
|
*/
|
|
1073
|
-
function getValidationConfiguration() {
|
|
1084
|
+
function getValidationConfiguration () {
|
|
1074
1085
|
return global.kuzzle.internalIndex
|
|
1075
|
-
.search('validations', {}, {from: 0, size: 1000})
|
|
1086
|
+
.search('validations', {}, { from: 0, size: 1000 })
|
|
1076
1087
|
.then(result => {
|
|
1077
1088
|
let validation = {};
|
|
1078
1089
|
|
|
@@ -1083,28 +1094,28 @@ function getValidationConfiguration() {
|
|
|
1083
1094
|
for (const { _source, _id } of result.hits) {
|
|
1084
1095
|
const collectionName = `${_id.split('#')[0]}/${_id.split('#')[1]}`;
|
|
1085
1096
|
|
|
1086
|
-
if (!get(_source, 'index')) {
|
|
1097
|
+
if (! get(_source, 'index')) {
|
|
1087
1098
|
throw assertionError.get(
|
|
1088
1099
|
'incorrect_validation_format',
|
|
1089
1100
|
collectionName,
|
|
1090
1101
|
'index');
|
|
1091
1102
|
}
|
|
1092
1103
|
|
|
1093
|
-
if (!get(_source, 'collection')) {
|
|
1104
|
+
if (! get(_source, 'collection')) {
|
|
1094
1105
|
throw assertionError.get(
|
|
1095
1106
|
'incorrect_validation_format',
|
|
1096
1107
|
collectionName,
|
|
1097
1108
|
'collection');
|
|
1098
1109
|
}
|
|
1099
1110
|
|
|
1100
|
-
if (!get(_source, 'validation')) {
|
|
1111
|
+
if (! get(_source, 'validation')) {
|
|
1101
1112
|
throw assertionError.get(
|
|
1102
1113
|
'incorrect_validation_format',
|
|
1103
1114
|
collectionName,
|
|
1104
1115
|
'validation');
|
|
1105
1116
|
}
|
|
1106
1117
|
|
|
1107
|
-
if (!has(validation, _source.index)) {
|
|
1118
|
+
if (! has(validation, _source.index)) {
|
|
1108
1119
|
validation[_source.index] = {};
|
|
1109
1120
|
}
|
|
1110
1121
|
|
|
@@ -275,6 +275,18 @@
|
|
|
275
275
|
"code": 48,
|
|
276
276
|
"message": "An \"%s\" is not allowed to be associated with multiple \"%\". This is probably not linked to this request but rather the consequence of previous actions on ElasticSearch.",
|
|
277
277
|
"class": "PreconditionError"
|
|
278
|
+
},
|
|
279
|
+
"invalid_multi_index_collection_usage": {
|
|
280
|
+
"description": "Searches on multiple collections should be achieved with the \"targets\" argument who contains list of indexes and collections to search within.",
|
|
281
|
+
"message": "Searches on multiple collections should be achieved with the \"targets\" argument who contains list of indexes and collections to search within.",
|
|
282
|
+
"code": 49,
|
|
283
|
+
"class": "BadRequestError"
|
|
284
|
+
},
|
|
285
|
+
"invalid_target_format": {
|
|
286
|
+
"description": "When a target index or collections contains invalid characters used for multi index search or \"_all\"",
|
|
287
|
+
"message": "The %s (\"%s\") contains invalid characters \",+*\" or is equal to \"_all\" which is forbidden",
|
|
288
|
+
"code": 50,
|
|
289
|
+
"class": "BadRequestError"
|
|
278
290
|
}
|
|
279
291
|
}
|
|
280
292
|
},
|
|
@@ -87,6 +87,18 @@
|
|
|
87
87
|
"code": 14,
|
|
88
88
|
"message": "%s",
|
|
89
89
|
"class": "BadRequestError"
|
|
90
|
+
},
|
|
91
|
+
"forbidden_stream": {
|
|
92
|
+
"description": "A forbidden HttpStream has been provided in a response",
|
|
93
|
+
"code": 15,
|
|
94
|
+
"message": "Cannot set an HttpStream as a request's response in a non-http protocol",
|
|
95
|
+
"class": "InternalError"
|
|
96
|
+
},
|
|
97
|
+
"unsupported_protocol": {
|
|
98
|
+
"description": "A request has been made with an unsupported protocol",
|
|
99
|
+
"code": 16,
|
|
100
|
+
"message": "The protocol \"%s\" is not supported by the API action \"%s\".",
|
|
101
|
+
"class": "InternalError"
|
|
90
102
|
}
|
|
91
103
|
}
|
|
92
104
|
},
|
|
@@ -81,6 +81,18 @@
|
|
|
81
81
|
"code": 13,
|
|
82
82
|
"message": "Maximum HTTP file size exceeded",
|
|
83
83
|
"class": "SizeLimitError"
|
|
84
|
+
},
|
|
85
|
+
"stream_closed": {
|
|
86
|
+
"description": "The stream has been closed or destroyed before sending the response",
|
|
87
|
+
"code": 14,
|
|
88
|
+
"message": "Stream closed or destroyed.",
|
|
89
|
+
"class": "InternalError"
|
|
90
|
+
},
|
|
91
|
+
"stream_errored": {
|
|
92
|
+
"description": "The stream is errored",
|
|
93
|
+
"code": 15,
|
|
94
|
+
"message": "Stream errored: %s",
|
|
95
|
+
"class": "InternalError"
|
|
84
96
|
}
|
|
85
97
|
}
|
|
86
98
|
},
|