kuzzle 2.17.8 → 2.19.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/index.d.ts +1 -0
- package/index.js +3 -0
- package/lib/api/controllers/adminController.js +9 -0
- package/lib/api/controllers/authController.js +8 -2
- package/lib/api/controllers/debugController.d.ts +59 -0
- package/lib/api/controllers/debugController.js +285 -0
- package/lib/api/controllers/documentController.js +49 -31
- package/lib/api/controllers/index.js +1 -0
- package/lib/api/controllers/indexController.js +10 -6
- package/lib/api/controllers/securityController.js +81 -43
- package/lib/api/controllers/serverController.js +2 -1
- package/lib/api/documentExtractor.js +51 -9
- package/lib/api/funnel.js +30 -8
- package/lib/api/httpRoutes.js +8 -1
- package/lib/api/openapi/OpenApiManager.js +3 -0
- package/lib/api/openapi/components/document/get.yaml +1 -1
- package/lib/api/openapi/components/document/update.yaml +1 -1
- package/lib/api/openapi/components/index.d.ts +1 -0
- package/lib/api/openapi/components/index.js +1 -0
- package/lib/api/openapi/components/security/index.d.ts +2 -0
- package/lib/api/openapi/components/security/index.js +10 -0
- package/lib/api/openapi/components/security/upsertUser.yaml +59 -0
- package/lib/api/request/kuzzleRequest.d.ts +58 -4
- package/lib/api/request/kuzzleRequest.js +163 -31
- package/lib/api/request/requestResponse.js +25 -0
- package/lib/cluster/idCardHandler.js +1 -1
- package/lib/config/default.config.js +3 -0
- package/lib/config/documentEventAliases.d.ts +7 -0
- package/lib/config/documentEventAliases.js +26 -12
- package/lib/core/backend/backend.d.ts +4 -0
- package/lib/core/backend/backend.js +9 -0
- package/lib/core/backend/backendController.d.ts +7 -1
- package/lib/core/backend/backendController.js +15 -3
- package/lib/core/network/protocols/httpwsProtocol.js +14 -6
- package/lib/core/plugin/plugin.js +7 -0
- package/lib/core/shared/sdk/embeddedSdk.d.ts +3 -3
- package/lib/core/shared/sdk/embeddedSdk.js +33 -0
- package/lib/core/shared/sdk/funnelProtocol.d.ts +1 -2
- package/lib/kerror/codes/0-core.json +35 -0
- package/lib/kerror/codes/1-services.json +1 -1
- package/lib/kerror/codes/2-api.json +6 -0
- package/lib/kerror/errors/kuzzleError.d.ts +1 -1
- package/lib/kuzzle/kuzzle.d.ts +1 -1
- package/lib/kuzzle/kuzzle.js +27 -8
- package/lib/model/security/user.js +5 -6
- package/lib/model/storage/apiKey.js +1 -6
- package/lib/service/storage/elasticsearch.js +143 -47
- package/lib/types/DebugModule.d.ts +23 -0
- package/lib/types/DebugModule.js +39 -0
- package/lib/types/config/SecurityConfiguration.d.ts +10 -0
- package/lib/types/index.d.ts +0 -1
- package/lib/types/index.js +0 -1
- package/lib/util/crypto.d.ts +1 -0
- package/lib/util/crypto.js +12 -0
- package/lib/util/dump-collection.d.ts +35 -0
- package/lib/util/dump-collection.js +11 -8
- package/lib/util/name-generator.d.ts +79 -0
- package/lib/util/name-generator.js +1409 -1345
- package/lib/util/time.d.ts +1 -0
- package/lib/util/time.js +9 -0
- package/package.json +19 -21
- package/lib/core/security/README.md +0 -224
- package/lib/core/shared/README.md +0 -3
- package/package-lock.json +0 -8403
|
@@ -258,6 +258,9 @@ export declare class KuzzleRequest {
|
|
|
258
258
|
/**
|
|
259
259
|
* Gets a parameter from a request arguments and checks that it is an array
|
|
260
260
|
*
|
|
261
|
+
* If the request argument is a JSON String instead of an array, it will be parsed
|
|
262
|
+
* and returned if it is a valid JSON array, otherwise it will @throws {api.assert.invalid_type}.
|
|
263
|
+
*
|
|
261
264
|
* @param name parameter name
|
|
262
265
|
* @param def default value to return if the parameter is not set
|
|
263
266
|
*
|
|
@@ -266,9 +269,29 @@ export declare class KuzzleRequest {
|
|
|
266
269
|
* @throws {api.assert.invalid_type} If the fetched parameter is not an array
|
|
267
270
|
*/
|
|
268
271
|
getArray(name: string, def?: [] | undefined): any[];
|
|
272
|
+
/**
|
|
273
|
+
* @deprecated do not use, Use getArray instead
|
|
274
|
+
*
|
|
275
|
+
* Gets a parameter from a request arguments and checks that it is an array
|
|
276
|
+
*
|
|
277
|
+
* If the request argument is a String instead of an array, it will be JSON parsed
|
|
278
|
+
* and returned if it is a valid JSON array, otherwise it will return the string splitted on `,`.
|
|
279
|
+
*
|
|
280
|
+
*
|
|
281
|
+
* @param name parameter name
|
|
282
|
+
* @param def default value to return if the parameter is not set
|
|
283
|
+
*
|
|
284
|
+
* @throws {api.assert.missing_argument} If parameter not found and no default
|
|
285
|
+
* value provided
|
|
286
|
+
* @throws {api.assert.invalid_type} If the fetched parameter is not an array or a string
|
|
287
|
+
*/
|
|
288
|
+
getArrayLegacy(name: string, def?: [] | undefined): any[];
|
|
269
289
|
/**
|
|
270
290
|
* Gets a parameter from a request arguments and checks that it is an object
|
|
271
291
|
*
|
|
292
|
+
* If the request argument is a JSON String instead of an object, it will be parsed
|
|
293
|
+
* and returned if it is a valid JSON object, otherwise it will @throws {api.assert.invalid_type}.
|
|
294
|
+
*
|
|
272
295
|
* @param name parameter name
|
|
273
296
|
* @param def default value to return if the parameter is not set
|
|
274
297
|
*
|
|
@@ -277,14 +300,39 @@ export declare class KuzzleRequest {
|
|
|
277
300
|
* @throws {api.assert.invalid_type} If the fetched parameter is not an object
|
|
278
301
|
*/
|
|
279
302
|
getObject(name: string, def?: JSONObject | undefined): JSONObject;
|
|
303
|
+
/**
|
|
304
|
+
* Gets a parameter from a request arguments and check with moment.js if the date is an ISO8601 format date
|
|
305
|
+
* or is valid regarding a given custom format (example : YYYY-MM-DD).
|
|
306
|
+
*
|
|
307
|
+
* @param name parameter name.
|
|
308
|
+
* @param format optional parameter to check if the date is valid regarding a format. If not set, the format checked
|
|
309
|
+
* is ISO8601.
|
|
310
|
+
* @throws {api.assert.missing_argument} If parameter not found and no default
|
|
311
|
+
* value provided
|
|
312
|
+
* @throws {api.assert.invalid_type} If parameter value is not a valid date.
|
|
313
|
+
*/
|
|
314
|
+
getDate(name: string, format?: string): string;
|
|
315
|
+
/**
|
|
316
|
+
* Gets a parameter from a request arguments and returns it to timestamp format.
|
|
317
|
+
*
|
|
318
|
+
* @param name parameter name.
|
|
319
|
+
* @throws {api.assert.missing_argument} If parameter not found and no default
|
|
320
|
+
* value provided
|
|
321
|
+
* @throws {api.assert.invalid_type} If parameter value is not a valid date.
|
|
322
|
+
*/
|
|
323
|
+
getTimestamp(name: string): number;
|
|
280
324
|
/**
|
|
281
325
|
* Returns the index specified in the request
|
|
282
326
|
*/
|
|
283
|
-
getIndex(
|
|
327
|
+
getIndex({ required }?: {
|
|
328
|
+
required?: boolean;
|
|
329
|
+
}): string;
|
|
284
330
|
/**
|
|
285
331
|
* Returns the collection specified in the request
|
|
286
332
|
*/
|
|
287
|
-
getCollection(
|
|
333
|
+
getCollection({ required }?: {
|
|
334
|
+
required?: boolean;
|
|
335
|
+
}): string;
|
|
288
336
|
/**
|
|
289
337
|
* Returns the index and collection specified in the request
|
|
290
338
|
*/
|
|
@@ -322,8 +370,8 @@ export declare class KuzzleRequest {
|
|
|
322
370
|
*/
|
|
323
371
|
getUser(): User | null;
|
|
324
372
|
/**
|
|
325
|
-
|
|
326
|
-
|
|
373
|
+
* Returns the search body query according to the http method
|
|
374
|
+
*/
|
|
327
375
|
getSearchBody(): JSONObject;
|
|
328
376
|
/**
|
|
329
377
|
* Returns the search params.
|
|
@@ -353,6 +401,7 @@ export declare class KuzzleRequest {
|
|
|
353
401
|
* @param obj container object
|
|
354
402
|
* @param name parameter name
|
|
355
403
|
* @param errorName name to use in error messages
|
|
404
|
+
* @param querystring if true, the object is expected to be found in a querystring
|
|
356
405
|
*/
|
|
357
406
|
private _getBoolean;
|
|
358
407
|
/**
|
|
@@ -398,8 +447,13 @@ export declare class KuzzleRequest {
|
|
|
398
447
|
* @param name parameter name
|
|
399
448
|
* @param errorName name to use in error messages
|
|
400
449
|
* @param def default value
|
|
450
|
+
* @param querystring if true, the object is expected to be found in a querystring
|
|
401
451
|
*/
|
|
402
452
|
private _getObject;
|
|
453
|
+
/**
|
|
454
|
+
* Throw `missing_argument` when this one is required
|
|
455
|
+
*/
|
|
456
|
+
private checkRequired;
|
|
403
457
|
}
|
|
404
458
|
export declare class Request extends KuzzleRequest {
|
|
405
459
|
}
|
|
@@ -42,8 +42,14 @@ var __importStar = (this && this.__importStar) || function (mod) {
|
|
|
42
42
|
__setModuleDefault(result, mod);
|
|
43
43
|
return result;
|
|
44
44
|
};
|
|
45
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
46
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
47
|
+
};
|
|
45
48
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
46
49
|
exports.Request = exports.KuzzleRequest = void 0;
|
|
50
|
+
const safeObject_1 = require("../../util/safeObject");
|
|
51
|
+
const lodash_1 = require("lodash");
|
|
52
|
+
const moment_1 = __importDefault(require("moment"));
|
|
47
53
|
const uuid = __importStar(require("uuid"));
|
|
48
54
|
const nanoid_1 = require("nanoid");
|
|
49
55
|
const requestInput_1 = require("./requestInput");
|
|
@@ -53,8 +59,6 @@ const errors_1 = require("../../kerror/errors");
|
|
|
53
59
|
const kerror = __importStar(require("../../kerror"));
|
|
54
60
|
const types_1 = require("../../types");
|
|
55
61
|
const assert = __importStar(require("../../util/assertType"));
|
|
56
|
-
const safeObject_1 = require("../../util/safeObject");
|
|
57
|
-
const lodash_1 = require("lodash");
|
|
58
62
|
const assertionError = kerror.wrap('api', 'assert');
|
|
59
63
|
// private properties
|
|
60
64
|
// \u200b is a zero width space, used to masquerade console.log output
|
|
@@ -224,7 +228,9 @@ class KuzzleRequest {
|
|
|
224
228
|
}
|
|
225
229
|
this.status = options.status || 200;
|
|
226
230
|
if (options.headers) {
|
|
227
|
-
this.response.
|
|
231
|
+
this.response.configure({
|
|
232
|
+
headers: options.headers
|
|
233
|
+
});
|
|
228
234
|
}
|
|
229
235
|
if (options.raw !== undefined) {
|
|
230
236
|
this.response.raw = options.raw;
|
|
@@ -461,7 +467,7 @@ class KuzzleRequest {
|
|
|
461
467
|
* @param name parameter name
|
|
462
468
|
*/
|
|
463
469
|
getBoolean(name) {
|
|
464
|
-
return this._getBoolean(this.input.args, name, name);
|
|
470
|
+
return this._getBoolean(this.input.args, name, name, true);
|
|
465
471
|
}
|
|
466
472
|
/**
|
|
467
473
|
* Gets a parameter from a request arguments and checks that it is a number
|
|
@@ -505,6 +511,9 @@ class KuzzleRequest {
|
|
|
505
511
|
/**
|
|
506
512
|
* Gets a parameter from a request arguments and checks that it is an array
|
|
507
513
|
*
|
|
514
|
+
* If the request argument is a JSON String instead of an array, it will be parsed
|
|
515
|
+
* and returned if it is a valid JSON array, otherwise it will @throws {api.assert.invalid_type}.
|
|
516
|
+
*
|
|
508
517
|
* @param name parameter name
|
|
509
518
|
* @param def default value to return if the parameter is not set
|
|
510
519
|
*
|
|
@@ -513,11 +522,56 @@ class KuzzleRequest {
|
|
|
513
522
|
* @throws {api.assert.invalid_type} If the fetched parameter is not an array
|
|
514
523
|
*/
|
|
515
524
|
getArray(name, def = undefined) {
|
|
516
|
-
return this._getArray(this.input.args, name, name, def);
|
|
525
|
+
return this._getArray(this.input.args, name, name, def, true);
|
|
526
|
+
}
|
|
527
|
+
/**
|
|
528
|
+
* @deprecated do not use, Use getArray instead
|
|
529
|
+
*
|
|
530
|
+
* Gets a parameter from a request arguments and checks that it is an array
|
|
531
|
+
*
|
|
532
|
+
* If the request argument is a String instead of an array, it will be JSON parsed
|
|
533
|
+
* and returned if it is a valid JSON array, otherwise it will return the string splitted on `,`.
|
|
534
|
+
*
|
|
535
|
+
*
|
|
536
|
+
* @param name parameter name
|
|
537
|
+
* @param def default value to return if the parameter is not set
|
|
538
|
+
*
|
|
539
|
+
* @throws {api.assert.missing_argument} If parameter not found and no default
|
|
540
|
+
* value provided
|
|
541
|
+
* @throws {api.assert.invalid_type} If the fetched parameter is not an array or a string
|
|
542
|
+
*/
|
|
543
|
+
getArrayLegacy(name, def = undefined) {
|
|
544
|
+
const value = (0, lodash_1.get)(this.input.args, name, def);
|
|
545
|
+
if (value === undefined) {
|
|
546
|
+
throw assertionError.get('missing_argument', name);
|
|
547
|
+
}
|
|
548
|
+
if (Array.isArray(value)) {
|
|
549
|
+
return value;
|
|
550
|
+
}
|
|
551
|
+
if (typeof value !== 'string') {
|
|
552
|
+
throw assertionError.get('invalid_type', name, 'array');
|
|
553
|
+
}
|
|
554
|
+
// If we are using the HTTP protocol and we have a string instead of an Array
|
|
555
|
+
// we try to parse it as JSON
|
|
556
|
+
if (this.context.connection.protocol === 'http') {
|
|
557
|
+
try {
|
|
558
|
+
const parsedValue = JSON.parse(value);
|
|
559
|
+
if (Array.isArray(parsedValue)) {
|
|
560
|
+
return parsedValue;
|
|
561
|
+
}
|
|
562
|
+
}
|
|
563
|
+
catch (e) {
|
|
564
|
+
// Do nothing, let the code continue
|
|
565
|
+
}
|
|
566
|
+
}
|
|
567
|
+
return value.split(',');
|
|
517
568
|
}
|
|
518
569
|
/**
|
|
519
570
|
* Gets a parameter from a request arguments and checks that it is an object
|
|
520
571
|
*
|
|
572
|
+
* If the request argument is a JSON String instead of an object, it will be parsed
|
|
573
|
+
* and returned if it is a valid JSON object, otherwise it will @throws {api.assert.invalid_type}.
|
|
574
|
+
*
|
|
521
575
|
* @param name parameter name
|
|
522
576
|
* @param def default value to return if the parameter is not set
|
|
523
577
|
*
|
|
@@ -526,27 +580,65 @@ class KuzzleRequest {
|
|
|
526
580
|
* @throws {api.assert.invalid_type} If the fetched parameter is not an object
|
|
527
581
|
*/
|
|
528
582
|
getObject(name, def = undefined) {
|
|
529
|
-
return this._getObject(this.input.args, name, name, def);
|
|
583
|
+
return this._getObject(this.input.args, name, name, def, true);
|
|
584
|
+
}
|
|
585
|
+
/**
|
|
586
|
+
* Gets a parameter from a request arguments and check with moment.js if the date is an ISO8601 format date
|
|
587
|
+
* or is valid regarding a given custom format (example : YYYY-MM-DD).
|
|
588
|
+
*
|
|
589
|
+
* @param name parameter name.
|
|
590
|
+
* @param format optional parameter to check if the date is valid regarding a format. If not set, the format checked
|
|
591
|
+
* is ISO8601.
|
|
592
|
+
* @throws {api.assert.missing_argument} If parameter not found and no default
|
|
593
|
+
* value provided
|
|
594
|
+
* @throws {api.assert.invalid_type} If parameter value is not a valid date.
|
|
595
|
+
*/
|
|
596
|
+
getDate(name, format) {
|
|
597
|
+
const args = this.input.args;
|
|
598
|
+
if (args[name] === undefined) {
|
|
599
|
+
throw assertionError.get('missing_argument', name);
|
|
600
|
+
}
|
|
601
|
+
if (format && !(0, moment_1.default)(args[name], format, true).isValid()) {
|
|
602
|
+
throw assertionError.get('invalid_type', name, 'date');
|
|
603
|
+
}
|
|
604
|
+
if (!(0, moment_1.default)(args[name], moment_1.default.ISO_8601).isValid()) {
|
|
605
|
+
throw assertionError.get('invalid_type', name, 'date');
|
|
606
|
+
}
|
|
607
|
+
return this.getString(name);
|
|
608
|
+
}
|
|
609
|
+
/**
|
|
610
|
+
* Gets a parameter from a request arguments and returns it to timestamp format.
|
|
611
|
+
*
|
|
612
|
+
* @param name parameter name.
|
|
613
|
+
* @throws {api.assert.missing_argument} If parameter not found and no default
|
|
614
|
+
* value provided
|
|
615
|
+
* @throws {api.assert.invalid_type} If parameter value is not a valid date.
|
|
616
|
+
*/
|
|
617
|
+
getTimestamp(name) {
|
|
618
|
+
const args = this.input.args;
|
|
619
|
+
if (args[name] === undefined) {
|
|
620
|
+
throw assertionError.get('missing_argument', name);
|
|
621
|
+
}
|
|
622
|
+
if ((0, moment_1.default)(args[name], true).isValid() === false) {
|
|
623
|
+
throw assertionError.get('invalid_type', name, 'date');
|
|
624
|
+
}
|
|
625
|
+
return this.getInteger(name);
|
|
530
626
|
}
|
|
531
627
|
/**
|
|
532
628
|
* Returns the index specified in the request
|
|
533
629
|
*/
|
|
534
|
-
getIndex() {
|
|
630
|
+
getIndex({ required = true } = {}) {
|
|
535
631
|
const index = this.input.args.index;
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
}
|
|
539
|
-
return index;
|
|
632
|
+
this.checkRequired(index, 'index', required);
|
|
633
|
+
return index ? String(index) : null;
|
|
540
634
|
}
|
|
541
635
|
/**
|
|
542
636
|
* Returns the collection specified in the request
|
|
543
637
|
*/
|
|
544
|
-
getCollection() {
|
|
638
|
+
getCollection({ required = true } = {}) {
|
|
545
639
|
const collection = this.input.args.collection;
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
}
|
|
549
|
-
return collection;
|
|
640
|
+
this.checkRequired(collection, 'collection', required);
|
|
641
|
+
return collection ? String(collection) : null;
|
|
550
642
|
}
|
|
551
643
|
/**
|
|
552
644
|
* Returns the index and collection specified in the request
|
|
@@ -603,7 +695,7 @@ class KuzzleRequest {
|
|
|
603
695
|
if (typeof id !== 'string') {
|
|
604
696
|
throw assertionError.get('invalid_type', '_id', 'string');
|
|
605
697
|
}
|
|
606
|
-
return id;
|
|
698
|
+
return String(id);
|
|
607
699
|
}
|
|
608
700
|
/**
|
|
609
701
|
* Returns the current user kuid
|
|
@@ -624,20 +716,14 @@ class KuzzleRequest {
|
|
|
624
716
|
return null;
|
|
625
717
|
}
|
|
626
718
|
/**
|
|
627
|
-
|
|
628
|
-
|
|
719
|
+
* Returns the search body query according to the http method
|
|
720
|
+
*/
|
|
629
721
|
getSearchBody() {
|
|
630
722
|
if (this.context.connection.protocol !== 'http'
|
|
631
723
|
|| this.context.connection.misc.verb !== 'GET') {
|
|
632
724
|
return this.getBody({});
|
|
633
725
|
}
|
|
634
|
-
|
|
635
|
-
try {
|
|
636
|
-
return JSON.parse(searchBody);
|
|
637
|
-
}
|
|
638
|
-
catch (err) {
|
|
639
|
-
throw assertionError.get('invalid_argument', err.message);
|
|
640
|
-
}
|
|
726
|
+
return this.getObject('searchBody', {});
|
|
641
727
|
}
|
|
642
728
|
/**
|
|
643
729
|
* Returns the search params.
|
|
@@ -690,16 +776,17 @@ class KuzzleRequest {
|
|
|
690
776
|
* @param obj container object
|
|
691
777
|
* @param name parameter name
|
|
692
778
|
* @param errorName name to use in error messages
|
|
779
|
+
* @param querystring if true, the object is expected to be found in a querystring
|
|
693
780
|
*/
|
|
694
|
-
_getBoolean(obj, name, errorName) {
|
|
781
|
+
_getBoolean(obj, name, errorName, querystring = false) {
|
|
695
782
|
let value = (0, lodash_1.get)(obj, name);
|
|
696
783
|
// In HTTP, booleans are flags: if it's in the querystring, it's set,
|
|
697
784
|
// whatever its value.
|
|
698
785
|
// If a user needs to unset the option, they need to remove it from the
|
|
699
786
|
// querystring.
|
|
700
|
-
if (this.context.connection.protocol === 'http') {
|
|
787
|
+
if (this.context.connection.protocol === 'http' && querystring) {
|
|
701
788
|
value = value !== undefined;
|
|
702
|
-
obj
|
|
789
|
+
(0, lodash_1.set)(obj, name, value);
|
|
703
790
|
}
|
|
704
791
|
else if (value === undefined || value === null) {
|
|
705
792
|
value = false;
|
|
@@ -776,12 +863,30 @@ class KuzzleRequest {
|
|
|
776
863
|
* @param errorName name to use in error messages
|
|
777
864
|
* @param def default value
|
|
778
865
|
*/
|
|
779
|
-
_getArray(obj, name, errorName, def = undefined) {
|
|
866
|
+
_getArray(obj, name, errorName, def = undefined, querystring = false) {
|
|
780
867
|
const value = (0, lodash_1.get)(obj, name, def);
|
|
781
868
|
if (value === undefined) {
|
|
782
869
|
throw assertionError.get('missing_argument', errorName);
|
|
783
870
|
}
|
|
784
871
|
if (!Array.isArray(value)) {
|
|
872
|
+
// If we are using the HTTP protocol and we have a string instead of an Array
|
|
873
|
+
// we try to parse it as JSON
|
|
874
|
+
if (this.context.connection.protocol === 'http'
|
|
875
|
+
&& querystring
|
|
876
|
+
&& typeof value === 'string') {
|
|
877
|
+
try {
|
|
878
|
+
const parsedValue = JSON.parse(value);
|
|
879
|
+
if (Array.isArray(parsedValue)) {
|
|
880
|
+
// Replace the value with the parsed value
|
|
881
|
+
// This way subsequent calls to this function will return the parsed value directly
|
|
882
|
+
(0, lodash_1.set)(obj, name, parsedValue);
|
|
883
|
+
return parsedValue;
|
|
884
|
+
}
|
|
885
|
+
}
|
|
886
|
+
catch (e) {
|
|
887
|
+
// Do nothing, let the error be thrown below
|
|
888
|
+
}
|
|
889
|
+
}
|
|
785
890
|
throw assertionError.get('invalid_type', errorName, 'array');
|
|
786
891
|
}
|
|
787
892
|
return value;
|
|
@@ -793,17 +898,44 @@ class KuzzleRequest {
|
|
|
793
898
|
* @param name parameter name
|
|
794
899
|
* @param errorName name to use in error messages
|
|
795
900
|
* @param def default value
|
|
901
|
+
* @param querystring if true, the object is expected to be found in a querystring
|
|
796
902
|
*/
|
|
797
|
-
_getObject(obj, name, errorName, def = undefined) {
|
|
903
|
+
_getObject(obj, name, errorName, def = undefined, querystring = false) {
|
|
798
904
|
const value = (0, lodash_1.get)(obj, name, def);
|
|
799
905
|
if (value === undefined) {
|
|
800
906
|
throw assertionError.get('missing_argument', errorName);
|
|
801
907
|
}
|
|
802
908
|
if (!(0, safeObject_1.isPlainObject)(value)) {
|
|
909
|
+
// If we are using the HTTP protocol and we have a string instead of an Array
|
|
910
|
+
// we try to parse it as JSON
|
|
911
|
+
if (this.context.connection.protocol === 'http'
|
|
912
|
+
&& querystring
|
|
913
|
+
&& typeof value === 'string') {
|
|
914
|
+
try {
|
|
915
|
+
const parsedValue = JSON.parse(value);
|
|
916
|
+
if ((0, safeObject_1.isPlainObject)(parsedValue)) {
|
|
917
|
+
// Replace the value with the parsed value
|
|
918
|
+
// This way subsequent calls to this function will return the parsed value directly
|
|
919
|
+
(0, lodash_1.set)(obj, name, parsedValue);
|
|
920
|
+
return parsedValue;
|
|
921
|
+
}
|
|
922
|
+
}
|
|
923
|
+
catch (e) {
|
|
924
|
+
// Do nothing, let the error be thrown below
|
|
925
|
+
}
|
|
926
|
+
}
|
|
803
927
|
throw assertionError.get('invalid_type', errorName, 'object');
|
|
804
928
|
}
|
|
805
929
|
return value;
|
|
806
930
|
}
|
|
931
|
+
/**
|
|
932
|
+
* Throw `missing_argument` when this one is required
|
|
933
|
+
*/
|
|
934
|
+
checkRequired(arg, argName, required) {
|
|
935
|
+
if (required && !arg) {
|
|
936
|
+
throw assertionError.get('missing_argument', argName);
|
|
937
|
+
}
|
|
938
|
+
}
|
|
807
939
|
}
|
|
808
940
|
exports.KuzzleRequest = KuzzleRequest;
|
|
809
941
|
class Request extends KuzzleRequest {
|
|
@@ -49,6 +49,11 @@ const assert = __importStar(require("../../util/assertType"));
|
|
|
49
49
|
// \u200b is a zero width space, used to masquerade console.log output
|
|
50
50
|
const _request = 'request\u200b';
|
|
51
51
|
const _headers = 'headers\u200b';
|
|
52
|
+
const _userHeaders = 'userHeaders\u200b'; // List of headers to be sent in the response
|
|
53
|
+
// List of headers that should not be present in the body of the response
|
|
54
|
+
const restrictedHeaders = [
|
|
55
|
+
'set-cookie',
|
|
56
|
+
];
|
|
52
57
|
class Headers {
|
|
53
58
|
constructor() {
|
|
54
59
|
this.namesMap = new Map();
|
|
@@ -150,6 +155,7 @@ class RequestResponse {
|
|
|
150
155
|
this.raw = false;
|
|
151
156
|
this[_request] = request;
|
|
152
157
|
this[_headers] = new Headers();
|
|
158
|
+
this[_userHeaders] = new Set();
|
|
153
159
|
Object.seal(this);
|
|
154
160
|
}
|
|
155
161
|
/**
|
|
@@ -254,6 +260,9 @@ class RequestResponse {
|
|
|
254
260
|
configure(options = {}) {
|
|
255
261
|
if (options.headers) {
|
|
256
262
|
this.setHeaders(options.headers);
|
|
263
|
+
for (const key of Object.keys(options.headers)) {
|
|
264
|
+
this[_userHeaders].add(key.toLowerCase());
|
|
265
|
+
}
|
|
257
266
|
}
|
|
258
267
|
if (options.status) {
|
|
259
268
|
this.status = options.status;
|
|
@@ -316,6 +325,21 @@ class RequestResponse {
|
|
|
316
325
|
status: this.status,
|
|
317
326
|
};
|
|
318
327
|
}
|
|
328
|
+
const filteredHeaders = {};
|
|
329
|
+
for (const name of this[_userHeaders]) {
|
|
330
|
+
filteredHeaders[name] = this.getHeader(name);
|
|
331
|
+
}
|
|
332
|
+
/**
|
|
333
|
+
* Remove headers that are not allowed to be sent to the client in the response's body
|
|
334
|
+
* For example "set-cookie" headers should only be visible by the browser,
|
|
335
|
+
* otherwise they may leak information about the server's cookies, since the browser will
|
|
336
|
+
* not be able to restrict them to the domain of the request.
|
|
337
|
+
*/
|
|
338
|
+
for (const header of restrictedHeaders) {
|
|
339
|
+
if (filteredHeaders[header] !== undefined) {
|
|
340
|
+
filteredHeaders[header] = undefined;
|
|
341
|
+
}
|
|
342
|
+
}
|
|
319
343
|
return {
|
|
320
344
|
content: {
|
|
321
345
|
action: this.action,
|
|
@@ -323,6 +347,7 @@ class RequestResponse {
|
|
|
323
347
|
controller: this.controller,
|
|
324
348
|
deprecations: this.deprecations,
|
|
325
349
|
error: this.error,
|
|
350
|
+
headers: filteredHeaders,
|
|
326
351
|
index: this.index,
|
|
327
352
|
node: this.node,
|
|
328
353
|
requestId: this.requestId,
|
|
@@ -98,7 +98,7 @@ class ClusterIdCardHandler {
|
|
|
98
98
|
async createIdCard() {
|
|
99
99
|
let reserved = false;
|
|
100
100
|
do {
|
|
101
|
-
this.nodeId =
|
|
101
|
+
this.nodeId = name_generator_1.NameGenerator.generateRandomName({ prefix: 'knode' });
|
|
102
102
|
this.nodeIdKey = `${REDIS_PREFIX}${this.nodeId}`;
|
|
103
103
|
this.idCard = new IdCard({
|
|
104
104
|
birthdate: Date.now(),
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
"use strict";
|
|
1
2
|
/*
|
|
2
3
|
* Kuzzle, a backend software, self-hostable and ready to use
|
|
3
4
|
* to power modern apps
|
|
@@ -18,16 +19,29 @@
|
|
|
18
19
|
* See the License for the specific language governing permissions and
|
|
19
20
|
* limitations under the License.
|
|
20
21
|
*/
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
module.exports = {
|
|
25
|
-
list: {
|
|
26
|
-
'delete': ['delete', 'deleteByQuery', 'mDelete'],
|
|
27
|
-
'get': ['get', 'mGet', 'search'],
|
|
28
|
-
'update': ['update', 'mUpdate', 'updateByQuery', 'upsert'],
|
|
29
|
-
'write': ['create', 'createOrReplace', 'mCreate', 'mCreateOrReplace', 'mReplace', 'replace']
|
|
30
|
-
},
|
|
31
|
-
namespace: 'generic:document',
|
|
32
|
-
notBefore: ['search', 'deleteByQuery', 'updateByQuery'],
|
|
22
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
23
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
33
24
|
};
|
|
25
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
|
+
exports.documentEventAliases = void 0;
|
|
27
|
+
const documentController_1 = __importDefault(require("../api/controllers/documentController"));
|
|
28
|
+
function filter(obj, expectValue) {
|
|
29
|
+
const result = [];
|
|
30
|
+
for (const [action, event] of Object.entries(obj)) {
|
|
31
|
+
if (event === expectValue) {
|
|
32
|
+
result.push(action);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
return result;
|
|
36
|
+
}
|
|
37
|
+
exports.documentEventAliases = {
|
|
38
|
+
list: {
|
|
39
|
+
delete: filter(documentController_1.default.actions, 'delete'),
|
|
40
|
+
get: filter(documentController_1.default.actions, 'get'),
|
|
41
|
+
update: filter(documentController_1.default.actions, 'update'),
|
|
42
|
+
write: filter(documentController_1.default.actions, 'write'),
|
|
43
|
+
},
|
|
44
|
+
namespace: 'generic:document',
|
|
45
|
+
notBefore: ['search', 'deleteByQuery', 'updateByQuery', 'export'],
|
|
46
|
+
};
|
|
47
|
+
//# sourceMappingURL=documentEventAliases.js.map
|
|
@@ -243,6 +243,15 @@ class Backend {
|
|
|
243
243
|
}
|
|
244
244
|
return this._sdk;
|
|
245
245
|
}
|
|
246
|
+
/**
|
|
247
|
+
* Cluster node ID
|
|
248
|
+
*/
|
|
249
|
+
get nodeId() {
|
|
250
|
+
if (!this.started) {
|
|
251
|
+
throw runtimeError.get('unavailable_before_start', 'nodeId');
|
|
252
|
+
}
|
|
253
|
+
return this._kuzzle.id;
|
|
254
|
+
}
|
|
246
255
|
get _instanceProxy() {
|
|
247
256
|
return {
|
|
248
257
|
api: this._controllers,
|
|
@@ -86,5 +86,11 @@ export declare class BackendController extends ApplicationManager {
|
|
|
86
86
|
* @param controller Controller class
|
|
87
87
|
*/
|
|
88
88
|
use(controller: Controller): void;
|
|
89
|
-
|
|
89
|
+
/**
|
|
90
|
+
* Adds the controller definition to the list of application controllers.
|
|
91
|
+
*
|
|
92
|
+
* This method also check if the definition is valid to throw with a stacktrace
|
|
93
|
+
* beginning on the user code adding the controller.
|
|
94
|
+
*/
|
|
95
|
+
private add;
|
|
90
96
|
}
|
|
@@ -42,11 +42,15 @@ var __importStar = (this && this.__importStar) || function (mod) {
|
|
|
42
42
|
__setModuleDefault(result, mod);
|
|
43
43
|
return result;
|
|
44
44
|
};
|
|
45
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
46
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
47
|
+
};
|
|
45
48
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
46
49
|
exports.BackendController = void 0;
|
|
47
50
|
const inflector_1 = require("../../util/inflector");
|
|
48
51
|
const kerror = __importStar(require("../../kerror"));
|
|
49
52
|
const index_1 = require("./index");
|
|
53
|
+
const plugin_1 = __importDefault(require("../plugin/plugin"));
|
|
50
54
|
const assertionError = kerror.wrap('plugin', 'assert');
|
|
51
55
|
const runtimeError = kerror.wrap('plugin', 'runtime');
|
|
52
56
|
class BackendController extends index_1.ApplicationManager {
|
|
@@ -74,7 +78,8 @@ class BackendController extends index_1.ApplicationManager {
|
|
|
74
78
|
if (this._application.started) {
|
|
75
79
|
throw runtimeError.get('already_started', 'controller');
|
|
76
80
|
}
|
|
77
|
-
|
|
81
|
+
plugin_1.default.checkControllerDefinition(name, definition);
|
|
82
|
+
this.add(name, definition);
|
|
78
83
|
}
|
|
79
84
|
/**
|
|
80
85
|
* Uses a new controller class.
|
|
@@ -147,6 +152,7 @@ class BackendController extends index_1.ApplicationManager {
|
|
|
147
152
|
controller.name = inflector_1.Inflector.kebabCase(controller.constructor.name)
|
|
148
153
|
.replace('-controller', '');
|
|
149
154
|
}
|
|
155
|
+
plugin_1.default.checkControllerDefinition(controller.name, controller.definition);
|
|
150
156
|
for (const [action, definition] of Object.entries(controller.definition.actions)) {
|
|
151
157
|
if (typeof definition.handler !== 'function') {
|
|
152
158
|
throw assertionError.get('invalid_controller_definition', controller.name, `Handler for action "${action}" is not a function.`);
|
|
@@ -158,9 +164,15 @@ class BackendController extends index_1.ApplicationManager {
|
|
|
158
164
|
definition.handler = definition.handler.bind(controller);
|
|
159
165
|
}
|
|
160
166
|
}
|
|
161
|
-
this.
|
|
167
|
+
this.add(controller.name, controller.definition);
|
|
162
168
|
}
|
|
163
|
-
|
|
169
|
+
/**
|
|
170
|
+
* Adds the controller definition to the list of application controllers.
|
|
171
|
+
*
|
|
172
|
+
* This method also check if the definition is valid to throw with a stacktrace
|
|
173
|
+
* beginning on the user code adding the controller.
|
|
174
|
+
*/
|
|
175
|
+
add(name, definition) {
|
|
164
176
|
if (this._application._controllers[name]) {
|
|
165
177
|
throw assertionError.get('invalid_controller_definition', name, 'A controller with this name already exists');
|
|
166
178
|
}
|