kuzzle 2.14.0 → 2.14.5

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.
Files changed (36) hide show
  1. package/lib/api/controllers/securityController.js +49 -13
  2. package/lib/api/funnel.js +13 -24
  3. package/lib/api/openApiGenerator.js +6 -0
  4. package/lib/api/request/kuzzleRequest.js +9 -9
  5. package/lib/config/default.config.js +10 -1
  6. package/lib/core/auth/tokenManager.d.ts +65 -0
  7. package/lib/core/auth/tokenManager.js +222 -256
  8. package/lib/core/backend/backend.js +3 -4
  9. package/lib/core/backend/backendController.d.ts +27 -0
  10. package/lib/core/backend/backendController.js +27 -0
  11. package/lib/core/backend/backendImport.js +6 -6
  12. package/lib/core/backend/backendPlugin.js +1 -1
  13. package/lib/core/plugin/plugin.js +42 -2
  14. package/lib/core/plugin/pluginContext.js +2 -2
  15. package/lib/core/plugin/pluginsManager.js +1 -0
  16. package/lib/core/realtime/hotelClerk.js +30 -16
  17. package/lib/core/security/profileRepository.js +5 -22
  18. package/lib/core/security/roleRepository.js +11 -5
  19. package/lib/core/security/tokenRepository.js +1 -1
  20. package/lib/core/security/userRepository.js +2 -2
  21. package/lib/core/shared/KoncordeWrapper.d.ts +1 -2
  22. package/lib/core/shared/KoncordeWrapper.js +10 -9
  23. package/lib/core/shared/repository.js +3 -3
  24. package/lib/core/shared/sdk/embeddedSdk.d.ts +2 -2
  25. package/lib/core/shared/sdk/embeddedSdk.js +2 -2
  26. package/lib/kerror/codes/4-plugin.json +6 -0
  27. package/lib/kuzzle/kuzzle.js +1 -1
  28. package/lib/model/security/token.d.ts +29 -0
  29. package/lib/model/security/token.js +25 -24
  30. package/lib/service/storage/elasticsearch.js +23 -5
  31. package/lib/types/ControllerDefinition.d.ts +51 -1
  32. package/lib/types/Plugin.js +1 -1
  33. package/lib/util/koncordeCompat.js +1 -1
  34. package/lib/util/mutex.js +2 -2
  35. package/package-lock.json +559 -1889
  36. package/package.json +27 -34
@@ -73,7 +73,7 @@ class BackendPlugin extends index_1.ApplicationManager {
73
73
  */
74
74
  get(name) {
75
75
  if (!this._application._plugins[name]) {
76
- throw assertionError.get('plugin_not_found', name, didYouMean_1.default(name, this.list()));
76
+ throw assertionError.get('plugin_not_found', name, (0, didYouMean_1.default)(name, this.list()));
77
77
  }
78
78
  return this._application._plugins[name].plugin;
79
79
  }
@@ -23,8 +23,8 @@
23
23
 
24
24
  const path = require('path');
25
25
  const fs = require('fs');
26
-
27
26
  const semver = require('semver');
27
+ const enforcer = require('openapi-enforcer');
28
28
 
29
29
  const { PluginContext } = require('./pluginContext');
30
30
  const PrivilegedPluginContext = require('./privilegedContext');
@@ -34,6 +34,7 @@ const Manifest = require('./pluginManifest');
34
34
  const { has, isPlainObject } = require('../../util/safeObject');
35
35
 
36
36
  const assertionError = kerror.wrap('plugin', 'assert');
37
+ const controllerError = kerror.wrap('plugin', 'controller');
37
38
  const runtimeError = kerror.wrap('plugin', 'runtime');
38
39
 
39
40
  const PLUGIN_NAME_REGEX = /^[a-z-\d]+$/;
@@ -330,16 +331,21 @@ class Plugin {
330
331
  checkHttpRouteProperties(route, action, name, application);
331
332
 
332
333
  const routeProperties = Object.keys(route);
333
- if (routeProperties.length > 2) {
334
+ if (routeProperties.length > 3) {
334
335
  routeProperties.splice(routeProperties.indexOf('url'), 1);
335
336
  routeProperties.splice(routeProperties.indexOf('path'), 1);
336
337
  routeProperties.splice(routeProperties.indexOf('verb'), 1);
338
+ routeProperties.splice(routeProperties.indexOf('openapi'), 1);
337
339
 
338
340
  throw assertionError.get(
339
341
  'invalid_controller_definition',
340
342
  name,
341
343
  `action "${action}" has invalid http properties: ${routeProperties.join(', ')}`);
342
344
  }
345
+
346
+ if (route.openapi) {
347
+ checkOpenAPISpecification(name, action, route);
348
+ }
343
349
  }
344
350
  }
345
351
  }
@@ -359,4 +365,38 @@ function checkHttpRouteProperties (route, action, name, application) {
359
365
  }
360
366
  }
361
367
 
368
+ function checkOpenAPISpecification (controller, action, route) {
369
+ if (! isPlainObject(route.openapi)) {
370
+ throw assertionError.get(
371
+ 'invalid_controller_definition',
372
+ controller,
373
+ 'The "openapi" property must be an object');
374
+ }
375
+
376
+ // Set :param notation to {param}
377
+ const formattedPath = route.path.replace(/\/:([^/]*)/g,'/{$1}');
378
+
379
+ const { error, warning } = enforcer({
380
+ /* eslint-disable sort-keys */
381
+ openapi: '3.0.1',
382
+ info: {
383
+ title: 'Kuzzle API',
384
+ version: require('../../../package').version
385
+ },
386
+ paths: {
387
+ [formattedPath]: {
388
+ [route.verb]: route.openapi
389
+ }
390
+ },
391
+ /* eslint-enable sort-keys */
392
+ });
393
+
394
+ if (warning) {
395
+ global.kuzzle.log.warn(`Warning for OpenAPI specification in "${controller}:${action}", ${route.openapi} : ${warning}`);
396
+ }
397
+ if (error) {
398
+ throw controllerError.get('invalid_openapi_schema', controller, action, route.openapi, error);
399
+ }
400
+ }
401
+
362
402
  module.exports = Plugin;
@@ -249,8 +249,8 @@ function curryAddStrategy(pluginName) {
249
249
  // be serialized and propagated to other cluster nodes
250
250
  // so if a strategy is not defined using an authenticator, we have
251
251
  // to reject the call
252
- if (!safeObject_1.isPlainObject(strategy)
253
- || !safeObject_1.isPlainObject(strategy.config)
252
+ if (!(0, safeObject_1.isPlainObject)(strategy)
253
+ || !(0, safeObject_1.isPlainObject)(strategy.config)
254
254
  || typeof strategy.config.authenticator !== 'string') {
255
255
  throw contextError.get('missing_authenticator', pluginName, name);
256
256
  }
@@ -712,6 +712,7 @@ class PluginsManager {
712
712
  this.routes.push({
713
713
  action,
714
714
  controller,
715
+ openapi: httpRoute.openapi,
715
716
  path: routePath,
716
717
  verb: httpRoute.verb
717
718
  });
@@ -54,12 +54,13 @@ class Channel {
54
54
  }
55
55
 
56
56
  class Subscription {
57
- constructor (index, collection, filters, roomId, connectionId) {
57
+ constructor (index, collection, filters, roomId, connectionId, user) {
58
58
  this.index = index;
59
59
  this.collection = collection;
60
60
  this.filters = filters;
61
61
  this.roomId = roomId;
62
62
  this.connectionId = connectionId;
63
+ this.kuid = user && user._id || null;
63
64
  }
64
65
  }
65
66
 
@@ -186,6 +187,7 @@ class HotelClerk {
186
187
  * Unsubscribes a user from a room
187
188
  * @param {string} connectionId
188
189
  * @param {string} roomId
190
+ * @param {string} kuid
189
191
  * @param {boolean} [notify]
190
192
  */
191
193
  global.kuzzle.onAsk(
@@ -209,7 +211,6 @@ class HotelClerk {
209
211
  */
210
212
  async subscribe (request) {
211
213
  const { index, collection } = request.input.resource;
212
- const propagate = request.input.args.propagate || false;
213
214
 
214
215
  if (! index) {
215
216
  return kerror.reject('api', 'assert', 'missing_argument', 'index');
@@ -230,7 +231,7 @@ class HotelClerk {
230
231
  * is made on the very last moment and is essential to ensure
231
232
  * that no zombie subscription can be performed
232
233
  */
233
- if (!global.kuzzle.router.isConnectionAlive(request.context)) {
234
+ if (! global.kuzzle.router.isConnectionAlive(request.context)) {
234
235
  return null;
235
236
  }
236
237
 
@@ -245,13 +246,13 @@ class HotelClerk {
245
246
  throw kerror.get('api', 'assert', 'koncorde_dsl_error', e.message);
246
247
  }
247
248
 
248
- await this._createRoom(normalized, { propagate });
249
+ this._createRoom(normalized);
249
250
 
250
251
  const { channel, subscribed } = await this._subscribeToRoom(
251
252
  normalized.id,
252
253
  request);
253
254
 
254
- if (propagate && subscribed) {
255
+ if (subscribed) {
255
256
  global.kuzzle.emit('core:realtime:subscribe:after', normalized.id);
256
257
 
257
258
  // @deprecated -- to be removed in next major version
@@ -271,7 +272,8 @@ class HotelClerk {
271
272
  collection,
272
273
  request.input.body,
273
274
  normalized.id,
274
- request.context.connection.id);
275
+ request.context.connection.id,
276
+ request.context.user);
275
277
 
276
278
  global.kuzzle.emit('core:realtime:user:subscribe:after', subscription);
277
279
 
@@ -419,14 +421,15 @@ class HotelClerk {
419
421
  * Create new room if needed
420
422
  *
421
423
  * @this HotelClerk
424
+ *
422
425
  * @param {NormalizedFilter} normalized - Obtained with Koncorde.normalize
423
426
  * @param {Object} [options]
424
- * @param {boolean} [options.propagate] - whether the new room creation should
425
- * be propagated to the cluster
427
+ *
426
428
  * @returns {void}
427
429
  */
428
- _createRoom (normalized, { propagate = true } = {}) {
429
- const { collection, index, id: roomId } = normalized;
430
+ _createRoom (normalized) {
431
+ const { index: koncordeIndex, id: roomId } = normalized;
432
+ const [index, collection] = koncordeIndex.split('/');
430
433
 
431
434
  if (this.rooms.has(normalized.id)) {
432
435
  return;
@@ -440,12 +443,10 @@ class HotelClerk {
440
443
 
441
444
  global.kuzzle.koncorde.store(normalized);
442
445
 
443
- if (propagate) {
444
- global.kuzzle.emit('core:realtime:room:create:after', normalized);
446
+ global.kuzzle.emit('core:realtime:room:create:after', normalized);
445
447
 
446
- // @deprecated -- to be removed in the next major version of kuzzle
447
- global.kuzzle.emit('room:new', { collection, index, roomId });
448
- }
448
+ // @deprecated -- to be removed in the next major version of kuzzle
449
+ global.kuzzle.emit('room:new', { collection, index, roomId });
449
450
 
450
451
  /*
451
452
  In some very rare cases, the room may have been created between
@@ -550,13 +551,26 @@ class HotelClerk {
550
551
  });
551
552
  }
552
553
 
554
+ const kuid = global.kuzzle.tokenManager.getKuidFromConnection(connectionId);
555
+
556
+ const subscription = new Subscription(
557
+ room.index,
558
+ room.collection,
559
+ undefined,
560
+ roomId,
561
+ connectionId,
562
+ { _id: kuid });
563
+
553
564
  global.kuzzle.emit('core:realtime:user:unsubscribe:after', {
565
+ /* @deprecated */
554
566
  requestContext,
567
+ /* @deprecated */
555
568
  room: {
556
569
  collection: room.collection,
557
570
  id: roomId,
558
571
  index: room.index,
559
- }
572
+ },
573
+ subscription,
560
574
  });
561
575
  }
562
576
 
@@ -124,14 +124,16 @@ class ProfileRepository extends Repository {
124
124
  (id, ttl) => this.scroll(id, ttl));
125
125
 
126
126
  /**
127
- * Searches profiles associated to a provided list of roles
128
- * @param {Array.<String>} roles
127
+ * Searches profiles
128
+ *
129
+ * @param {Object} searchBody - Search query (ES format)
129
130
  * @param {Object} opts (from, size, scroll)
131
+ *
130
132
  * @returns {Object} Search results
131
133
  */
132
134
  global.kuzzle.onAsk(
133
135
  'core:security:profile:search',
134
- (roles, opts) => this.searchProfiles(roles, opts));
136
+ (searchBody, opts) => this.search(searchBody, opts));
135
137
 
136
138
  /**
137
139
  * Removes all existing profiles and invalidates the RAM cache
@@ -316,25 +318,6 @@ class ProfileRepository extends Repository {
316
318
  });
317
319
  }
318
320
 
319
- /**
320
- *
321
- * @param {string[]} roles - array of role ids
322
- * @param {object} [options] - optional search arguments (from, size, scroll)
323
- * @returns {Promise}
324
- */
325
- searchProfiles (roles = [], {from=0, scroll, size=1000} = {}) {
326
- const query = {query: {}};
327
-
328
- if (roles && roles.length > 0) {
329
- query.query = {terms: {'policies.roleId': roles}};
330
- }
331
- else {
332
- query.query = {match_all: {}};
333
- }
334
-
335
- return this.search(query, {from, scroll, size});
336
- }
337
-
338
321
  /**
339
322
  * Deletes a profile
340
323
  *
@@ -308,10 +308,14 @@ class RoleRepository extends Repository {
308
308
  }
309
309
 
310
310
  /**
311
- * @param {Array} controllers
311
+ * @param {Object} body Search body containing either "query" or "controllers"
312
312
  * @param {Object} options
313
313
  */
314
- async searchRole (controllers, {from = 0, size = 9999} = {}) {
314
+ async searchRole (body, { from = 0, size = 9999 } = {}) {
315
+ if (! body.controllers) {
316
+ return this.search(body, { from, size });
317
+ }
318
+
315
319
  const searchResults = await this.search(
316
320
  { query: {}, sort: [{ _id: { order: 'asc' } }]},
317
321
  { from: 0, size: 9999 }); // /!\ NOT the options values
@@ -321,11 +325,11 @@ class RoleRepository extends Repository {
321
325
  total: searchResults.total
322
326
  };
323
327
 
324
- if (controllers.length > 0) {
328
+ if (body.controllers.length > 0) {
325
329
  result.hits = searchResults.hits
326
330
  .filter(role => Object
327
331
  .keys(role.controllers)
328
- .some(key => key === '*' || controllers.includes(key)));
332
+ .some(key => key === '*' || body.controllers.includes(key)));
329
333
 
330
334
  result.total = result.hits.length;
331
335
  }
@@ -488,7 +492,9 @@ class RoleRepository extends Repository {
488
492
  throw kerror.get('security', 'role', 'cannot_delete');
489
493
  }
490
494
 
491
- const response = await this.module.profile.searchProfiles([role._id], {
495
+ const query = { term: { 'policies.roleId': role._id } };
496
+
497
+ const response = await this.module.profile.search({ query }, {
492
498
  from: 0,
493
499
  size: 1
494
500
  });
@@ -28,7 +28,7 @@ const Bluebird = require('bluebird');
28
28
 
29
29
  const ApiKey = require('../../model/storage/apiKey');
30
30
  const { UnauthorizedError } = require('../../kerror/errors');
31
- const Token = require('../../model/security/token');
31
+ const { Token } = require('../../model/security/token');
32
32
  const Repository = require('../shared/repository');
33
33
  const kerror = require('../../kerror');
34
34
  const debug = require('../../util/debug')('kuzzle:bootstrap:tokens');
@@ -122,13 +122,13 @@ class UserRepository extends Repository {
122
122
 
123
123
  /**
124
124
  * Searches users
125
- * @param {Object} query - Search query (ES format)
125
+ * @param {Object} searchBody - Search body (ES format)
126
126
  * @param {Object} opts (from, size, scroll)
127
127
  * @returns {Object} Search results
128
128
  */
129
129
  global.kuzzle.onAsk(
130
130
  'core:security:user:search',
131
- (query, opts) => this.search(query, opts));
131
+ (searchBody, opts) => this.search(searchBody, opts));
132
132
 
133
133
  /**
134
134
  * Removes all existing users
@@ -2,7 +2,7 @@ import { JSONObject } from 'kuzzle-sdk';
2
2
  /**
3
3
  * Emulates the normalized object returned by Koncorde v3
4
4
  */
5
- declare class NormalizedFilterV3 {
5
+ export declare class NormalizedFilterV3 {
6
6
  /**
7
7
  * Filter Unique Identifier
8
8
  *
@@ -148,4 +148,3 @@ export declare class Koncorde {
148
148
  */
149
149
  validate(filter: JSONObject): Promise<void>;
150
150
  }
151
- export {};
@@ -20,7 +20,7 @@
20
20
  * limitations under the License.
21
21
  */
22
22
  Object.defineProperty(exports, "__esModule", { value: true });
23
- exports.Koncorde = void 0;
23
+ exports.Koncorde = exports.NormalizedFilterV3 = void 0;
24
24
  const koncorde_1 = require("koncorde");
25
25
  const koncordeCompat_1 = require("../../util/koncordeCompat");
26
26
  /**
@@ -34,6 +34,7 @@ class NormalizedFilterV3 {
34
34
  this.normalized = normalized.filter;
35
35
  }
36
36
  }
37
+ exports.NormalizedFilterV3 = NormalizedFilterV3;
37
38
  /*
38
39
  @deprecated
39
40
 
@@ -81,7 +82,7 @@ class Koncorde {
81
82
  * @return {boolean}
82
83
  */
83
84
  exists(index, collection) {
84
- return this.koncorde.getIndexes().includes(koncordeCompat_1.toKoncordeIndex(index, collection));
85
+ return this.koncorde.getIndexes().includes((0, koncordeCompat_1.toKoncordeIndex)(index, collection));
85
86
  }
86
87
  /**
87
88
  * Returns the list of collections associated to an index registered in this
@@ -91,7 +92,7 @@ class Koncorde {
91
92
  * @return {string[]}
92
93
  */
93
94
  getCollections(index) {
94
- return koncordeCompat_1.getCollections(this.koncorde, index);
95
+ return (0, koncordeCompat_1.getCollections)(this.koncorde, index);
95
96
  }
96
97
  /**
97
98
  * Returns the list of filter identifiers registered on a given
@@ -102,7 +103,7 @@ class Koncorde {
102
103
  * @return {string[]}
103
104
  */
104
105
  getFilterIds(index, collection) {
105
- return this.koncorde.getFilterIds(koncordeCompat_1.toKoncordeIndex(index, collection));
106
+ return this.koncorde.getFilterIds((0, koncordeCompat_1.toKoncordeIndex)(index, collection));
106
107
  }
107
108
  /**
108
109
  * Returns the list of indexes registered in this Koncorde instance
@@ -110,7 +111,7 @@ class Koncorde {
110
111
  * @return {string[]}
111
112
  */
112
113
  getIndexes() {
113
- return koncordeCompat_1.getIndexes(this.koncorde);
114
+ return (0, koncordeCompat_1.getIndexes)(this.koncorde);
114
115
  }
115
116
  /**
116
117
  * Checks if a filter is registered for the given filter identifier
@@ -137,7 +138,7 @@ class Koncorde {
137
138
  * @return {NormalizedFilterV3}
138
139
  */
139
140
  async normalize(index, collection, filter) {
140
- return new NormalizedFilterV3(index, collection, this.koncorde.normalize(filter, koncordeCompat_1.toKoncordeIndex(index, collection)));
141
+ return new NormalizedFilterV3(index, collection, this.koncorde.normalize(filter, (0, koncordeCompat_1.toKoncordeIndex)(index, collection)));
141
142
  }
142
143
  /**
143
144
  * Registers a filter to the engine instance. This method is equivalent to
@@ -149,7 +150,7 @@ class Koncorde {
149
150
  * @return {JSONObject}
150
151
  */
151
152
  async register(index, collection, filter) {
152
- const indexV4 = koncordeCompat_1.toKoncordeIndex(index, collection);
153
+ const indexV4 = (0, koncordeCompat_1.toKoncordeIndex)(index, collection);
153
154
  const normalized = this.koncorde.normalize(filter, indexV4);
154
155
  return this.store(new NormalizedFilterV3(index, collection, normalized));
155
156
  }
@@ -170,7 +171,7 @@ class Koncorde {
170
171
  * @return {JSONObject}
171
172
  */
172
173
  async store(normalized) {
173
- const indexV4 = koncordeCompat_1.toKoncordeIndex(normalized.index, normalized.collection);
174
+ const indexV4 = (0, koncordeCompat_1.toKoncordeIndex)(normalized.index, normalized.collection);
174
175
  if (this.koncorde.hasFilterId(normalized.id, indexV4)) {
175
176
  return {
176
177
  diff: false,
@@ -196,7 +197,7 @@ class Koncorde {
196
197
  * @return {string[]}
197
198
  */
198
199
  test(index, collection, data, id) {
199
- return koncordeCompat_1.koncordeTest(this.koncorde, index, collection, data, id);
200
+ return (0, koncordeCompat_1.koncordeTest)(this.koncorde, index, collection, data, id);
200
201
  }
201
202
  /**
202
203
  * Tests the provided filter without storing it in the engine, to check
@@ -104,12 +104,12 @@ class Repository {
104
104
  /**
105
105
  * Search in database corresponding repository according to a query
106
106
  *
107
- * @param {object} query
107
+ * @param {object} searchBody
108
108
  * @param {object} [options] - optional search arguments (from, size, scroll)
109
109
  * @returns {Promise}
110
110
  */
111
- async search (query, options = {}) {
112
- const response = await this.store.search(this.collection, query, options);
111
+ async search (searchBody, options = {}) {
112
+ const response = await this.store.search(this.collection, searchBody, options);
113
113
 
114
114
  return this._formatSearchResults(response);
115
115
  }
@@ -16,8 +16,8 @@ interface EmbeddedRealtime extends RealtimeController {
16
16
  * - `scope` Subscribe to document entering or leaving the scope. (default: 'all')
17
17
  * - `users` Subscribe to users entering or leaving the room. (default: 'none')
18
18
  * - `subscribeToSelf` Subscribe to notifications fired by our own queries. (default: true)
19
- * - `volatile` Subscription information sent alongside notifications
20
- * - `propagate` Propagate the callback execution on each cluster node
19
+ * - `volatile` Subscription information sent alongside notifications. (default: `{}`)
20
+ * - `propagate` Propagate the callback execution on each cluster node. (default: false)
21
21
  *
22
22
  * @returns A string containing the room ID
23
23
  */
@@ -44,7 +44,7 @@ class EmbeddedSDK extends kuzzle_sdk_1.Kuzzle {
44
44
  * @param options - Optional sdk arguments
45
45
  */
46
46
  as(user, options = { checkRights: false }) {
47
- if (!safeObject_1.isPlainObject(user) || typeof user._id !== 'string') {
47
+ if (!(0, safeObject_1.isPlainObject)(user) || typeof user._id !== 'string') {
48
48
  throw contextError.get('invalid_user');
49
49
  }
50
50
  return new impersonatedSdk_1.default(user._id, options);
@@ -60,7 +60,7 @@ class EmbeddedSDK extends kuzzle_sdk_1.Kuzzle {
60
60
  */
61
61
  query(request, options = {}) {
62
62
  // By default, do not propagate realtime notification accross cluster nodes
63
- if (safeObject_1.isPlainObject(request)
63
+ if ((0, safeObject_1.isPlainObject)(request)
64
64
  && request.controller === 'realtime'
65
65
  && request.action === 'subscribe') {
66
66
  request.propagate = options.propagate === undefined || options.propagate === null
@@ -343,6 +343,12 @@
343
343
  "code": 9,
344
344
  "message": "Unexpected return value from action \"%s:%s\": expected a Promise",
345
345
  "class": "PluginImplementationError"
346
+ },
347
+ "invalid_openapi_schema": {
348
+ "description": "OpenAPI specification is invalid",
349
+ "code": 10,
350
+ "message": "Invalid OpenAPI specification in \"%s:%s\", %s : %s",
351
+ "class": "PluginImplementationError"
346
352
  }
347
353
  }
348
354
  },
@@ -38,7 +38,7 @@ const PassportWrapper = require('../core/auth/passportWrapper');
38
38
  const PluginsManager = require('../core/plugin/pluginsManager');
39
39
  const Router = require('../core/network/router');
40
40
  const Statistics = require('../core/statistics');
41
- const TokenManager = require('../core/auth/tokenManager');
41
+ const { TokenManager } = require('../core/auth/tokenManager');
42
42
  const Validation = require('../core/validation');
43
43
  const Logger = require('./log');
44
44
  const vault = require('./vault');
@@ -0,0 +1,29 @@
1
+ export interface TokenContent {
2
+ /**
3
+ * Token ID (also Redis key)
4
+ *
5
+ * @example `${userId}#${jwt}`
6
+ */
7
+ _id?: string;
8
+ expiresAt?: number;
9
+ ttl?: number;
10
+ userId?: string;
11
+ connectionIds?: string[];
12
+ jwt?: string;
13
+ refreshed?: boolean;
14
+ }
15
+ /**
16
+ * Represents a token that identify an user.
17
+ */
18
+ export declare class Token implements TokenContent {
19
+ _id: string;
20
+ expiresAt: number;
21
+ ttl: number;
22
+ userId: string;
23
+ jwt: string;
24
+ refreshed: boolean;
25
+ constructor(data?: TokenContent);
26
+ get type(): 'apiKey' | 'authToken';
27
+ static get AUTH_PREFIX(): string;
28
+ static get APIKEY_PREFIX(): string;
29
+ }
@@ -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,32 +19,32 @@
18
19
  * See the License for the specific language governing permissions and
19
20
  * limitations under the License.
20
21
  */
21
-
22
- 'use strict';
23
-
22
+ Object.defineProperty(exports, "__esModule", { value: true });
23
+ exports.Token = void 0;
24
24
  /**
25
- * @class Token
25
+ * Represents a token that identify an user.
26
26
  */
27
27
  class Token {
28
- constructor(data = {}) {
29
- this._id = data._id || null;
30
- this.expiresAt = data.expiresAt || null;
31
- this.ttl = data.ttl || null;
32
- this.userId = data.userId || null;
33
- this.connectionId = data.connectionId || null;
34
- this.jwt = data.jwt || null;
35
- this.refreshed = Boolean(data.refreshed);
36
- }
37
-
38
- get type() {
39
- if (this.jwt && this.jwt.startsWith(Token.APIKEY_PREFIX)) {
40
- return 'apiKey';
28
+ constructor(data = {}) {
29
+ this._id = data._id || null;
30
+ this.expiresAt = data.expiresAt || null;
31
+ this.ttl = data.ttl || null;
32
+ this.userId = data.userId || null;
33
+ this.jwt = data.jwt || null;
34
+ this.refreshed = Boolean(data.refreshed);
35
+ }
36
+ get type() {
37
+ if (this.jwt && this.jwt.startsWith(Token.APIKEY_PREFIX)) {
38
+ return 'apiKey';
39
+ }
40
+ return 'authToken';
41
+ }
42
+ static get AUTH_PREFIX() {
43
+ return 'kauth-';
44
+ }
45
+ static get APIKEY_PREFIX() {
46
+ return 'kapikey-';
41
47
  }
42
- return 'authToken';
43
- }
44
48
  }
45
-
46
- Token.AUTH_PREFIX = 'kauth-';
47
- Token.APIKEY_PREFIX = 'kapikey-';
48
-
49
- module.exports = Token;
49
+ exports.Token = Token;
50
+ //# sourceMappingURL=token.js.map
@@ -116,7 +116,6 @@ class ElasticSearch extends Service {
116
116
  'explain',
117
117
  'from',
118
118
  'highlight',
119
- 'inner_hits',
120
119
  'query',
121
120
  'search_after',
122
121
  'search_timeout',
@@ -395,11 +394,30 @@ class ElasticSearch extends Service {
395
394
  }
396
395
 
397
396
  _formatSearchResult (body) {
397
+ function formatHit (hit) {
398
+ return {
399
+ _id: hit._id,
400
+ _score: hit._score,
401
+ _source: hit._source,
402
+ highlight: hit.highlight,
403
+ };
404
+ }
405
+
406
+ function formatInnerHits (innerHits) {
407
+ if (! innerHits) {
408
+ return undefined;
409
+ }
410
+
411
+ const formattedInnerHits = {};
412
+ for (const [name, innerHit] of Object.entries(innerHits)) {
413
+ formattedInnerHits[name] = innerHit.hits.hits.map(formatHit);
414
+ }
415
+ return formattedInnerHits;
416
+ }
417
+
398
418
  const hits = body.hits.hits.map(hit => ({
399
- _id: hit._id,
400
- _score: hit._score,
401
- _source: hit._source,
402
- highlight: hit.highlight,
419
+ inner_hits: formatInnerHits(hit.inner_hits),
420
+ ...formatHit(hit)
403
421
  }));
404
422
 
405
423
  return {