kuzzle 2.16.8 → 2.17.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.
Files changed (167) hide show
  1. package/README.md +11 -0
  2. package/lib/api/controllers/adminController.js +7 -6
  3. package/lib/api/controllers/authController.js +11 -11
  4. package/lib/api/controllers/baseController.js +60 -3
  5. package/lib/api/controllers/clusterController.js +1 -1
  6. package/lib/api/controllers/collectionController.js +7 -5
  7. package/lib/api/controllers/documentController.js +130 -17
  8. package/lib/api/controllers/indexController.js +1 -1
  9. package/lib/api/controllers/memoryStorageController.js +39 -38
  10. package/lib/api/controllers/realtimeController.js +1 -1
  11. package/lib/api/controllers/securityController.js +49 -49
  12. package/lib/api/controllers/serverController.js +73 -27
  13. package/lib/api/documentExtractor.js +3 -3
  14. package/lib/api/funnel.js +40 -21
  15. package/lib/api/httpRoutes.js +9 -4
  16. package/lib/api/openapi/OpenApiManager.d.ts +11 -0
  17. package/lib/api/openapi/OpenApiManager.js +96 -0
  18. package/lib/api/openapi/{document → components/document}/count.yaml +2 -2
  19. package/lib/api/openapi/{document → components/document}/create.yaml +2 -2
  20. package/lib/api/openapi/{document → components/document}/createOrReplace.yaml +2 -2
  21. package/lib/api/openapi/{document → components/document}/delete.yaml +1 -1
  22. package/lib/api/openapi/{document → components/document}/deleteByQuery.yaml +2 -2
  23. package/lib/api/openapi/{document → components/document}/exists.yaml +1 -1
  24. package/lib/api/openapi/{document → components/document}/get.yaml +1 -1
  25. package/lib/api/openapi/{document → components/document}/index.d.ts +2 -0
  26. package/lib/api/openapi/{document → components/document}/index.js +7 -2
  27. package/lib/api/openapi/{document → components/document}/replace.yaml +2 -2
  28. package/lib/api/openapi/{document → components/document}/scroll.yaml +1 -1
  29. package/lib/api/openapi/{document → components/document}/update.yaml +2 -2
  30. package/lib/api/openapi/components/document/validate.yaml +42 -0
  31. package/lib/api/openapi/components/index.d.ts +2 -0
  32. package/lib/api/openapi/components/index.js +18 -0
  33. package/lib/api/openapi/{payloads.yaml → components/payloads.yaml} +0 -0
  34. package/lib/api/openapi/index.d.ts +1 -2
  35. package/lib/api/openapi/index.js +1 -5
  36. package/lib/api/openapi/openApiGenerator.d.ts +7 -0
  37. package/lib/api/openapi/openApiGenerator.js +133 -0
  38. package/lib/api/request/kuzzleRequest.d.ts +11 -11
  39. package/lib/api/request/kuzzleRequest.js +38 -48
  40. package/lib/cluster/node.js +9 -9
  41. package/lib/cluster/publisher.js +1 -1
  42. package/lib/cluster/subscriber.js +1 -1
  43. package/lib/cluster/workers/IDCardRenewer.js +13 -4
  44. package/lib/config/default.config.js +1 -0
  45. package/lib/config/index.js +6 -6
  46. package/lib/core/auth/passportResponse.js +6 -6
  47. package/lib/core/auth/passportWrapper.js +5 -5
  48. package/lib/core/backend/backend.d.ts +5 -1
  49. package/lib/core/backend/backend.js +12 -8
  50. package/lib/core/backend/backendConfig.d.ts +5 -1
  51. package/lib/core/backend/backendConfig.js +4 -0
  52. package/lib/core/backend/backendOpenApi.d.ts +9 -0
  53. package/lib/core/backend/backendOpenApi.js +69 -0
  54. package/lib/core/backend/index.d.ts +1 -0
  55. package/lib/core/backend/index.js +1 -0
  56. package/lib/core/network/accessLogger.js +6 -6
  57. package/lib/core/network/clientConnection.js +1 -1
  58. package/lib/core/network/entryPoint.js +5 -5
  59. package/lib/core/network/httpRouter/index.js +5 -5
  60. package/lib/core/network/httpRouter/routeHandler.js +3 -3
  61. package/lib/core/network/httpRouter/routePart.js +5 -5
  62. package/lib/core/network/protocolManifest.js +1 -1
  63. package/lib/core/network/protocols/httpMessage.js +2 -2
  64. package/lib/core/network/protocols/httpwsProtocol.js +207 -46
  65. package/lib/core/network/protocols/mqttProtocol.js +3 -3
  66. package/lib/core/network/protocols/protocol.js +3 -3
  67. package/lib/core/network/router.js +7 -6
  68. package/lib/core/plugin/plugin.js +38 -64
  69. package/lib/core/plugin/pluginContext.d.ts +10 -1
  70. package/lib/core/plugin/pluginContext.js +2 -0
  71. package/lib/core/plugin/pluginManifest.js +3 -3
  72. package/lib/core/plugin/pluginRepository.js +5 -5
  73. package/lib/core/plugin/pluginsManager.js +29 -28
  74. package/lib/core/realtime/notification/server.js +1 -1
  75. package/lib/core/realtime/notification/user.js +1 -1
  76. package/lib/core/realtime/notifier.js +5 -5
  77. package/lib/core/security/index.js +1 -1
  78. package/lib/core/security/profileRepository.d.ts +176 -0
  79. package/lib/core/security/profileRepository.js +426 -443
  80. package/lib/core/security/roleRepository.js +16 -16
  81. package/lib/core/security/securityLoader.js +3 -3
  82. package/lib/core/security/tokenRepository.js +18 -21
  83. package/lib/core/security/userRepository.js +8 -8
  84. package/lib/core/shared/abstractManifest.js +4 -4
  85. package/lib/core/shared/repository.js +6 -6
  86. package/lib/core/shared/sdk/funnelProtocol.js +1 -1
  87. package/lib/core/shared/sdk/impersonatedSdk.js +1 -1
  88. package/lib/core/shared/store.js +30 -23
  89. package/lib/core/statistics/statistics.js +17 -17
  90. package/lib/core/storage/clientAdapter.js +45 -10
  91. package/lib/core/validation/baseType.js +5 -5
  92. package/lib/core/validation/types/anything.js +1 -1
  93. package/lib/core/validation/types/boolean.js +2 -2
  94. package/lib/core/validation/types/date.js +9 -9
  95. package/lib/core/validation/types/email.js +5 -5
  96. package/lib/core/validation/types/enum.js +6 -6
  97. package/lib/core/validation/types/geoPoint.js +2 -2
  98. package/lib/core/validation/types/geoShape.js +28 -25
  99. package/lib/core/validation/types/integer.js +4 -4
  100. package/lib/core/validation/types/ipAddress.js +7 -6
  101. package/lib/core/validation/types/numeric.js +4 -4
  102. package/lib/core/validation/types/object.js +5 -5
  103. package/lib/core/validation/types/string.js +5 -5
  104. package/lib/core/validation/types/url.js +7 -6
  105. package/lib/core/validation/validation.js +95 -84
  106. package/lib/kerror/codes/1-services.json +12 -0
  107. package/lib/kerror/codes/2-api.json +12 -0
  108. package/lib/kerror/codes/3-network.json +12 -0
  109. package/lib/kerror/codes/4-plugin.json +6 -0
  110. package/lib/kerror/codes/index.js +11 -11
  111. package/lib/kerror/index.js +1 -1
  112. package/lib/kuzzle/dumpGenerator.js +3 -3
  113. package/lib/kuzzle/event/kuzzleEventEmitter.js +4 -4
  114. package/lib/kuzzle/event/pipeRunner.js +1 -1
  115. package/lib/kuzzle/event/waterfall.js +6 -6
  116. package/lib/kuzzle/kuzzle.js +36 -5
  117. package/lib/kuzzle/log.js +3 -3
  118. package/lib/kuzzle/vault.js +3 -3
  119. package/lib/model/security/profile.d.ts +54 -0
  120. package/lib/model/security/profile.js +174 -233
  121. package/lib/model/security/rights.js +1 -1
  122. package/lib/model/security/role.d.ts +40 -0
  123. package/lib/model/security/role.js +159 -191
  124. package/lib/model/security/user.d.ts +29 -0
  125. package/lib/model/security/user.js +84 -52
  126. package/lib/model/storage/apiKey.js +2 -2
  127. package/lib/model/storage/baseModel.js +3 -3
  128. package/lib/service/cache/redis.js +7 -7
  129. package/lib/service/storage/elasticsearch.js +152 -90
  130. package/lib/service/storage/esWrapper.js +2 -3
  131. package/lib/types/ControllerDefinition.d.ts +3 -3
  132. package/lib/types/ControllerRights.d.ts +22 -0
  133. package/lib/types/ControllerRights.js +23 -0
  134. package/lib/types/HttpStream.d.ts +32 -0
  135. package/lib/types/HttpStream.js +70 -0
  136. package/lib/types/OpenApiDefinition.d.ts +43 -0
  137. package/lib/types/{config/StorageService/StorageServiceElasticsearchConfiguration.js → OpenApiDefinition.js} +1 -1
  138. package/lib/types/Policy.d.ts +25 -0
  139. package/lib/types/Policy.js +23 -0
  140. package/lib/types/PolicyRestrictions.d.ts +21 -0
  141. package/lib/types/PolicyRestrictions.js +23 -0
  142. package/lib/types/Target.d.ts +15 -0
  143. package/lib/types/Target.js +23 -0
  144. package/lib/types/config/KuzzleConfiguration.d.ts +4 -0
  145. package/lib/types/config/ServicesConfiguration.d.ts +2 -2
  146. package/lib/types/config/{StorageService/StorageServiceElasticsearchConfiguration.d.ts → storageEngine/StorageEngineElasticsearchConfiguration.d.ts} +10 -3
  147. package/lib/types/config/storageEngine/StorageEngineElasticsearchConfiguration.js +3 -0
  148. package/lib/types/index.d.ts +7 -1
  149. package/lib/types/index.js +7 -1
  150. package/lib/util/array.d.ts +11 -0
  151. package/lib/util/array.js +57 -0
  152. package/lib/util/assertType.js +6 -6
  153. package/lib/util/bufferedPassThrough.d.ts +76 -0
  154. package/lib/util/bufferedPassThrough.js +161 -0
  155. package/lib/util/deprecate.js +7 -5
  156. package/lib/util/didYouMean.js +1 -1
  157. package/lib/util/dump-collection.d.ts +3 -0
  158. package/lib/util/dump-collection.js +265 -0
  159. package/lib/util/extractFields.js +2 -2
  160. package/lib/util/inflector.d.ts +8 -0
  161. package/lib/util/inflector.js +16 -0
  162. package/lib/util/requestAssertions.js +7 -7
  163. package/lib/util/wildcard.js +55 -0
  164. package/package-lock.json +881 -431
  165. package/package.json +23 -20
  166. package/lib/api/openApiGenerator.d.ts +0 -7
  167. package/lib/api/openApiGenerator.js +0 -197
@@ -24,7 +24,7 @@
24
24
  const Bluebird = require('bluebird');
25
25
 
26
26
  const kuzzleStateEnum = require('../../kuzzle/kuzzleStateEnum');
27
- const Role = require('../../model/security/role');
27
+ const { Role } = require('../../model/security/role');
28
28
  const Repository = require('../shared/repository');
29
29
  const kerror = require('../../kerror');
30
30
  const didYouMean = require('../../util/didYouMean');
@@ -166,7 +166,7 @@ class RoleRepository extends Repository {
166
166
  for (const id of ids) {
167
167
  let role = this.roles.get(id);
168
168
 
169
- if (!role) {
169
+ if (! role) {
170
170
  role = this.loadOneFromDatabase(id)
171
171
  .then(r => {
172
172
  this.roles.set(id, r);
@@ -209,7 +209,7 @@ class RoleRepository extends Repository {
209
209
 
210
210
  const role = await this.fromDTO(dto);
211
211
 
212
- return this.validateAndSaveRole(role, {force, method, refresh});
212
+ return this.validateAndSaveRole(role, { force, method, refresh });
213
213
  }
214
214
 
215
215
  /**
@@ -253,7 +253,7 @@ class RoleRepository extends Repository {
253
253
  * @param {Object} [opts]
254
254
  * @returns {Promise}
255
255
  */
256
- async update (id, content, {force, refresh, retryOnConflict, userId} = {}) {
256
+ async update (id, content, { force, refresh, retryOnConflict, userId } = {}) {
257
257
  const updated = await this.fromDTO({
258
258
  // /!\ order is important
259
259
  ...content,
@@ -299,7 +299,7 @@ class RoleRepository extends Repository {
299
299
  try {
300
300
  return await super.loadOneFromDatabase(id);
301
301
  }
302
- catch(err) {
302
+ catch (err) {
303
303
  if (err.status === 404) {
304
304
  throw kerror.get('security', 'role', 'not_found', id);
305
305
  }
@@ -317,7 +317,7 @@ class RoleRepository extends Repository {
317
317
  }
318
318
 
319
319
  const searchResults = await this.search(
320
- { query: {}, sort: [{ _id: { order: 'asc' } }]},
320
+ { query: {}, sort: [{ _id: { order: 'asc' } }] },
321
321
  { from: 0, size: 9999 }); // /!\ NOT the options values
322
322
 
323
323
  const result = {
@@ -349,7 +349,7 @@ class RoleRepository extends Repository {
349
349
  async validateAndSaveRole (role, options = {}) {
350
350
  await role.validateDefinition();
351
351
 
352
- if (role._id === 'anonymous' && !role.canLogIn()) {
352
+ if (role._id === 'anonymous' && ! role.canLogIn()) {
353
353
  throw kerror.get('security', 'role', 'login_required');
354
354
  }
355
355
 
@@ -371,7 +371,7 @@ class RoleRepository extends Repository {
371
371
  checkRoleNativeRights (role) {
372
372
  Object.keys(role.controllers).forEach(roleController => {
373
373
  if ( roleController !== '*'
374
- && !global.kuzzle.funnel.isNativeController(roleController)
374
+ && ! global.kuzzle.funnel.isNativeController(roleController)
375
375
  ) {
376
376
  return;
377
377
  }
@@ -388,7 +388,7 @@ class RoleRepository extends Repository {
388
388
  const actions = Object.keys(role.controllers[roleController].actions);
389
389
 
390
390
  actions.forEach(action => {
391
- if (action !== '*' && !controller._isAction(action)) {
391
+ if (action !== '*' && ! controller._isAction(action)) {
392
392
  throw roleRightsError.get(
393
393
  'unknown_action',
394
394
  role._id,
@@ -407,7 +407,7 @@ class RoleRepository extends Repository {
407
407
  * @param {Role} role
408
408
  * @param {Force} force
409
409
  */
410
- checkRolePluginsRights (role, { force=false, forceWarn=false } = {}) {
410
+ checkRolePluginsRights (role, { force = false, forceWarn = false } = {}) {
411
411
  const plugins = global.kuzzle.pluginsManager;
412
412
 
413
413
  for (const roleController of Object.keys(role.controllers)) {
@@ -417,8 +417,8 @@ class RoleRepository extends Repository {
417
417
  return;
418
418
  }
419
419
 
420
- if (!plugins.isController(roleController)) {
421
- if (!force) {
420
+ if (! plugins.isController(roleController)) {
421
+ if (! force) {
422
422
  throw roleRightsError.get(
423
423
  'unknown_controller',
424
424
  role._id,
@@ -440,8 +440,8 @@ class RoleRepository extends Repository {
440
440
 
441
441
  const roleActions = Object.keys(role.controllers[roleController].actions);
442
442
  for (const action of roleActions) {
443
- if (action !== '*' && !plugins.isAction(roleController, action)) {
444
- if (!force) {
443
+ if (action !== '*' && ! plugins.isAction(roleController, action)) {
444
+ if (! force) {
445
445
  throw roleRightsError.get(
446
446
  'unknown_action',
447
447
  role._id,
@@ -487,7 +487,7 @@ class RoleRepository extends Repository {
487
487
  /**
488
488
  * @override
489
489
  */
490
- async delete (role, {refresh = 'false'} = {}) {
490
+ async delete (role, { refresh = 'false' } = {}) {
491
491
  if (['admin', 'default', 'anonymous'].indexOf(role._id) > -1) {
492
492
  throw kerror.get('security', 'role', 'cannot_delete');
493
493
  }
@@ -544,7 +544,7 @@ class RoleRepository extends Repository {
544
544
  * @param {string} [roleId]
545
545
  */
546
546
  invalidate (roleId) {
547
- if (!roleId) {
547
+ if (! roleId) {
548
548
  this.roles.clear();
549
549
  }
550
550
  else {
@@ -46,12 +46,12 @@ class SecurityLoader {
46
46
  (json, opts) => this.load(json, opts));
47
47
  }
48
48
 
49
- async load(permissions = {}, {
49
+ async load (permissions = {}, {
50
50
  force,
51
51
  onExistingUsers = 'fail',
52
52
  onExistingUsersWarning = false,
53
- refresh = false,
54
- user=null,
53
+ refresh = 'false',
54
+ user = null,
55
55
  } = {}) {
56
56
  assertIsObject(permissions);
57
57
 
@@ -57,7 +57,7 @@ class TokenRepository extends Repository {
57
57
  this.anonymousToken = new Token({ userId: '-1' });
58
58
  }
59
59
 
60
- async init() {
60
+ async init () {
61
61
  await this._loadApiKeys();
62
62
 
63
63
  /**
@@ -130,7 +130,7 @@ class TokenRepository extends Repository {
130
130
  global.kuzzle.onAsk(
131
131
  'core:security:token:verify',
132
132
  hash => this.verifyToken(hash));
133
-
133
+
134
134
  }
135
135
 
136
136
  /**
@@ -169,11 +169,11 @@ class TokenRepository extends Repository {
169
169
  );
170
170
  }
171
171
 
172
- const refreshed = await this.generateToken(user, {expiresIn});
172
+ const refreshed = await this.generateToken(user, { expiresIn });
173
173
 
174
174
  // Mark as "refreshed" only if generating the new token succeeds
175
175
  token.refreshed = true;
176
- await this.persistToCache(token, {ttl: this.tokenGracePeriod});
176
+ await this.persistToCache(token, { ttl: this.tokenGracePeriod });
177
177
 
178
178
  global.kuzzle.tokenManager.refresh(token, refreshed);
179
179
 
@@ -195,7 +195,7 @@ class TokenRepository extends Repository {
195
195
  type = 'authToken',
196
196
  } = {}
197
197
  ) {
198
- if (!user || user._id === null) {
198
+ if (! user || user._id === null) {
199
199
  throw securityError.get('unknown_user');
200
200
  }
201
201
 
@@ -213,7 +213,7 @@ class TokenRepository extends Repository {
213
213
  throw securityError.get('ttl_exceeded');
214
214
  }
215
215
 
216
- const signOptions = {algorithm};
216
+ const signOptions = { algorithm };
217
217
 
218
218
  if (parsedExpiresIn === 0) {
219
219
  throw kerror.get('api', 'assert', 'invalid_argument', 'expiresIn', 'a number of milliseconds, or a parsable timespan string');
@@ -255,8 +255,8 @@ class TokenRepository extends Repository {
255
255
  * @returns {Promise}
256
256
  */
257
257
  async persistForUser (encodedToken, userId, ttl) {
258
- const redisTTL = ttl !== -1 ? ttl : 0;
259
- const expiresAt = ttl !== -1 ? Date.now() + ttl : -1;
258
+ const redisTTL = ttl === -1 ? 0 : ttl;
259
+ const expiresAt = ttl === -1 ? -1 : Date.now() + ttl;
260
260
  const token = new Token({
261
261
  _id: `${userId}#${encodedToken}`,
262
262
  expiresAt,
@@ -268,7 +268,7 @@ class TokenRepository extends Repository {
268
268
  try {
269
269
  return await this.persistToCache(token, { ttl: redisTTL });
270
270
  }
271
- catch(err) {
271
+ catch (err) {
272
272
  throw kerror.getFrom(
273
273
  err,
274
274
  'services',
@@ -289,7 +289,7 @@ class TokenRepository extends Repository {
289
289
  decoded = jwt.verify(this.removeTokenPrefix(token), global.kuzzle.secret);
290
290
 
291
291
  // probably forged token => throw without providing any information
292
- if (!decoded._id) {
292
+ if (! decoded._id) {
293
293
  throw new jwt.JsonWebTokenError('Invalid token');
294
294
  }
295
295
  }
@@ -336,13 +336,13 @@ class TokenRepository extends Repository {
336
336
  }
337
337
 
338
338
  async hydrate (userToken, data) {
339
- if (!_.isObject(data)) {
339
+ if (! _.isObject(data)) {
340
340
  return userToken;
341
341
  }
342
342
 
343
343
  _.assignIn(userToken, data);
344
344
 
345
- if (!userToken.userId) {
345
+ if (! userToken.userId) {
346
346
  return this.anonymousToken;
347
347
  }
348
348
 
@@ -359,7 +359,7 @@ class TokenRepository extends Repository {
359
359
  * @param {string} kuid
360
360
  * @returns {Promise}
361
361
  */
362
- async deleteByKuid (kuid, {keepApiKeys = true} = {}) {
362
+ async deleteByKuid (kuid, { keepApiKeys = true } = {}) {
363
363
  const emptyKeyLength = super.getCacheKey('').length;
364
364
  const userKey = super.getCacheKey(`${kuid}#*`);
365
365
 
@@ -396,7 +396,7 @@ class TokenRepository extends Repository {
396
396
  if (keepApiKeys && cacheToken.type === 'apiKey') {
397
397
  return;
398
398
  }
399
-
399
+
400
400
  await this.expire(cacheToken);
401
401
  }
402
402
  });
@@ -428,13 +428,10 @@ class TokenRepository extends Repository {
428
428
  debug('Loading API keys into Redis');
429
429
 
430
430
  const promises = [];
431
- const createToken = async ({ token, userId, ttl }) => {
432
- return await this.persistForUser(token, userId, ttl);
433
- };
434
431
 
435
- await ApiKey.batchExecute({ match_all: {} }, apiKeys => {
436
- for (const apiKey of apiKeys) {
437
- promises.push(createToken(apiKey));
432
+ await ApiKey.batchExecute({ match_all: {} }, documents => {
433
+ for (const { _source } of documents) {
434
+ promises.push(this.persistForUser(_source.token, _source.userId, _source.ttl));
438
435
  }
439
436
  });
440
437
 
@@ -456,7 +453,7 @@ class TokenRepository extends Repository {
456
453
  *
457
454
  * So we need to override the TTL auto-refresh function to disable it
458
455
  */
459
- refreshCacheTTL() {
456
+ refreshCacheTTL () {
460
457
  // This comment is here to please Sonarqube. It requires a comment
461
458
  // explaining why a function is empty, but there is no sense
462
459
  // duplicating what has been just said in the JSDoc.
@@ -25,7 +25,7 @@ const { Request } = require('../../api/request');
25
25
  const debug = require('../../util/debug')('kuzzle:core:security:users');
26
26
  const Repository = require('../shared/repository');
27
27
  const kerror = require('../../kerror');
28
- const User = require('../../model/security/user');
28
+ const { User } = require('../../model/security/user');
29
29
  const ApiKey = require('../../model/storage/apiKey');
30
30
 
31
31
  /**
@@ -166,7 +166,7 @@ class UserRepository extends Repository {
166
166
  * @param {Object} content
167
167
  * @param {Object} [opts]
168
168
  */
169
- async create (id, profileIds, content, {userId, refresh = 'false'} = {}) {
169
+ async create (id, profileIds, content, { userId, refresh = 'false' } = {}) {
170
170
  const user = await this.fromDTO({
171
171
  ...content,
172
172
  // Profile Ids and content are stored at the same level... for now.
@@ -242,7 +242,7 @@ class UserRepository extends Repository {
242
242
  * @param {Object} [opts]
243
243
  * @returns {Promise}
244
244
  */
245
- async replace (id, profileIds, content, {refresh = 'false', userId} = {}) {
245
+ async replace (id, profileIds, content, { refresh = 'false', userId } = {}) {
246
246
  // Assertion: the user must exist
247
247
  await this.load(id);
248
248
 
@@ -304,7 +304,7 @@ class UserRepository extends Repository {
304
304
  * @returns {Promise<User>}
305
305
  */
306
306
  async fromDTO (dto) {
307
- if (dto.profileIds && !Array.isArray(dto.profileIds)) {
307
+ if (dto.profileIds && ! Array.isArray(dto.profileIds)) {
308
308
  dto.profileIds = [dto.profileIds];
309
309
  }
310
310
 
@@ -347,13 +347,13 @@ class UserRepository extends Repository {
347
347
  /**
348
348
  * @override
349
349
  */
350
- async delete (user, {refresh = 'false'} = {}) {
350
+ async delete (user, { refresh = 'false' } = {}) {
351
351
  debug('Delete user: %s', user);
352
352
 
353
353
  await this._removeUserStrategies(user);
354
- await ApiKey.deleteByUser(user, {refresh});
354
+ await ApiKey.deleteByUser(user, { refresh });
355
355
  await this.module.token.deleteByKuid(user._id);
356
- await super.delete(user, {refresh});
356
+ await super.delete(user, { refresh });
357
357
  }
358
358
 
359
359
  async _removeUserStrategies (user) {
@@ -406,7 +406,7 @@ class UserRepository extends Repository {
406
406
  try {
407
407
  return await super.loadOneFromDatabase(id);
408
408
  }
409
- catch(err) {
409
+ catch (err) {
410
410
  if (err.status === 404) {
411
411
  throw kerror.get('security', 'user', 'not_found', id);
412
412
  }
@@ -35,7 +35,7 @@ const kerror = require('../../kerror').wrap('plugin', 'manifest');
35
35
  * @param {string} pluginPath - Absolute path to the plugin directory
36
36
  */
37
37
  class AbstractManifest {
38
- constructor(pluginPath) {
38
+ constructor (pluginPath) {
39
39
  this.path = pluginPath;
40
40
 
41
41
  this.manifestPath = path.resolve(this.path, 'manifest.json');
@@ -58,7 +58,7 @@ class AbstractManifest {
58
58
 
59
59
  this.kuzzleVersion = this.raw.kuzzleVersion;
60
60
 
61
- if (!semver.satisfies(global.kuzzle.config.version, this.kuzzleVersion)) {
61
+ if (! semver.satisfies(global.kuzzle.config.version, this.kuzzleVersion)) {
62
62
  throw kerror.get(
63
63
  'version_mismatch',
64
64
  this.path,
@@ -66,7 +66,7 @@ class AbstractManifest {
66
66
  this.kuzzleVersion);
67
67
  }
68
68
 
69
- if (!_.isNil(this.raw.name)) {
69
+ if (! _.isNil(this.raw.name)) {
70
70
  if (typeof this.raw.name !== 'string' || this.raw.name.length === 0) {
71
71
  throw kerror.get('invalid_name_type', this.manifestPath);
72
72
  }
@@ -87,7 +87,7 @@ class AbstractManifest {
87
87
  *
88
88
  * @returns {Object}
89
89
  */
90
- toJSON() {
90
+ toJSON () {
91
91
  return {
92
92
  kuzzleVersion: this.kuzzleVersion,
93
93
  name: this.name,
@@ -41,7 +41,7 @@ class Repository {
41
41
  * @param {{cache: cacheDbEnum, store: Store}} [options]
42
42
  * @constructor
43
43
  */
44
- constructor({ cache = cacheDbEnum.INTERNAL, store = null } = {}) {
44
+ constructor ({ cache = cacheDbEnum.INTERNAL, store = null } = {}) {
45
45
  this.ttl = global.kuzzle.config.repositories.common.cacheTTL;
46
46
  this.collection = null;
47
47
  this.ObjectConstructor = null;
@@ -72,7 +72,7 @@ class Repository {
72
72
  const dto = {};
73
73
 
74
74
  if (response._source) {
75
- Object.assign(dto, response._source, {_id: response._id});
75
+ Object.assign(dto, response._source, { _id: response._id });
76
76
  }
77
77
  else {
78
78
  Object.assign(dto, response);
@@ -90,7 +90,7 @@ class Repository {
90
90
  * @returns {Promise<object>}
91
91
  */
92
92
  async loadMultiFromDatabase (ids) {
93
- const {items} = await this.store.mGet(this.collection, ids);
93
+ const { items } = await this.store.mGet(this.collection, ids);
94
94
 
95
95
  if (items.length === 0) {
96
96
  return [];
@@ -98,7 +98,7 @@ class Repository {
98
98
 
99
99
  return Bluebird.map(
100
100
  items,
101
- doc => this.fromDTO(Object.assign({}, doc._source, {_id: doc._id})));
101
+ doc => this.fromDTO(Object.assign({}, doc._source, { _id: doc._id })));
102
102
  }
103
103
 
104
104
  /**
@@ -398,7 +398,7 @@ class Repository {
398
398
  */
399
399
  async _truncate (options, part = null) {
400
400
  if (part === null) {
401
- const objects = await this.search({}, { scroll: '5s', size: 100 });
401
+ const objects = await this.search({}, { refresh: options.refresh, scroll: '5s', size: 100 });
402
402
  const deleted = await this._truncatePart(objects, options);
403
403
 
404
404
  if (objects.hits.length < objects.total) {
@@ -435,7 +435,7 @@ class Repository {
435
435
  * @returns {Promise<integer>} count of deleted objects
436
436
  * @private
437
437
  */
438
- async _truncatePart(objects, options) {
438
+ async _truncatePart (objects, options) {
439
439
  return Bluebird
440
440
  .map(objects.hits, async object => {
441
441
  // profile and role repositories have protected objects, we can't delete
@@ -28,7 +28,7 @@ const kerror = require('../../../kerror');
28
28
  const { hilightUserCode } = require('../../../util/stackTrace');
29
29
 
30
30
  class FunnelProtocol extends KuzzleEventEmitter {
31
- constructor() {
31
+ constructor () {
32
32
  super();
33
33
 
34
34
  this.id = 'funnel';
@@ -64,7 +64,7 @@ class ImpersonatedSDK {
64
64
  // Make sure we bring any local methods into our new custom context
65
65
  Object.getOwnPropertyNames(Object.getPrototypeOf(global.app.sdk[controllerName]))
66
66
  .forEach((localMethod) => {
67
- if (!['constructor', 'query'].includes(localMethod)) {
67
+ if (! ['constructor', 'query'].includes(localMethod)) {
68
68
  customContext[localMethod] = controllerInstance[localMethod];
69
69
  }
70
70
  });
@@ -41,40 +41,47 @@ class Store {
41
41
  this.scope = scope;
42
42
 
43
43
  const methodsMapping = {
44
- count: `core:storage:${scope}:document:count`,
45
- create: `core:storage:${scope}:document:create`,
46
- createCollection: `core:storage:${scope}:collection:create`,
47
- createOrReplace: `core:storage:${scope}:document:createOrReplace`,
48
- delete: `core:storage:${scope}:document:delete`,
49
- deleteByQuery: `core:storage:${scope}:document:deleteByQuery`,
50
- deleteCollection: `core:storage:${scope}:collection:delete`,
51
- deleteFields: `core:storage:${scope}:document:deleteFields`,
52
- deleteIndex: `core:storage:${scope}:index:delete`,
53
- exists: `core:storage:${scope}:document:exist`,
54
- get: `core:storage:${scope}:document:get`,
55
- getMapping: `core:storage:${scope}:mappings:get`,
56
- mExecute: `core:storage:${scope}:document:mExecute`,
57
- mGet: `core:storage:${scope}:document:mGet`,
58
- refreshCollection: `core:storage:${scope}:collection:refresh`,
59
- replace: `core:storage:${scope}:document:replace`,
60
- search: `core:storage:${scope}:document:search`,
44
+ count: `core:storage:${scope}:document:count`,
45
+ create: `core:storage:${scope}:document:create`,
46
+ createCollection: `core:storage:${scope}:collection:create`,
47
+ createOrReplace: `core:storage:${scope}:document:createOrReplace`,
48
+ delete: `core:storage:${scope}:document:delete`,
49
+ deleteByQuery: `core:storage:${scope}:document:deleteByQuery`,
50
+ deleteCollection: `core:storage:${scope}:collection:delete`,
51
+ deleteFields: `core:storage:${scope}:document:deleteFields`,
52
+ deleteIndex: `core:storage:${scope}:index:delete`,
53
+ exists: `core:storage:${scope}:document:exist`,
54
+ get: `core:storage:${scope}:document:get`,
55
+ getMapping: `core:storage:${scope}:mappings:get`,
56
+ mExecute: `core:storage:${scope}:document:mExecute`,
57
+ mGet: `core:storage:${scope}:document:mGet`,
58
+ refreshCollection: `core:storage:${scope}:collection:refresh`,
59
+ replace: `core:storage:${scope}:document:replace`,
60
+ search: `core:storage:${scope}:document:search`,
61
61
  truncateCollection: `core:storage:${scope}:collection:truncate`,
62
- update: `core:storage:${scope}:document:update`,
63
- updateByQuery: `core:storage:${scope}:document:updateByQuery`,
64
- updateCollection: `core:storage:${scope}:collection:update`,
65
- updateMapping: `core:storage:${scope}:mappings:update`,
62
+ update: `core:storage:${scope}:document:update`,
63
+ updateByQuery: `core:storage:${scope}:document:updateByQuery`,
64
+ updateCollection: `core:storage:${scope}:collection:update`,
65
+ updateMapping: `core:storage:${scope}:mappings:update`,
66
66
  };
67
67
 
68
68
  for (const [method, event] of Object.entries(methodsMapping)) {
69
69
  this[method] = (...args) => global.kuzzle.ask(event, this.index, ...args);
70
70
  }
71
71
 
72
- // the scroll method is special: it doesn't need an index parameter
73
- // we keep it for ease of use
72
+ // the scroll and multiSearch method are special: they doesn't need an index parameter
73
+ // we keep them for ease of use
74
74
  this.scroll = (scrollId, opts) => global.kuzzle.ask(
75
75
  `core:storage:${scope}:document:scroll`,
76
76
  scrollId,
77
77
  opts);
78
+
79
+ this.multiSearch = (targets, searchBody, opts) => global.kuzzle.ask(
80
+ `core:storage:${scope}:document:multiSearch`,
81
+ targets,
82
+ searchBody,
83
+ opts
84
+ );
78
85
  }
79
86
 
80
87
  /**
@@ -61,11 +61,11 @@ class Statistics {
61
61
 
62
62
  const protocol = request && request.context.connection.protocol;
63
63
 
64
- if (!protocol) {
64
+ if (! protocol) {
65
65
  return;
66
66
  }
67
67
 
68
- if (!this.currentStats.ongoingRequests.has(protocol)) {
68
+ if (! this.currentStats.ongoingRequests.has(protocol)) {
69
69
  this.currentStats.ongoingRequests.set(protocol, 1);
70
70
  }
71
71
  else {
@@ -87,7 +87,7 @@ class Statistics {
87
87
 
88
88
  const protocol = request && request.context.connection.protocol;
89
89
 
90
- if (!protocol) {
90
+ if (! protocol) {
91
91
  return;
92
92
  }
93
93
 
@@ -95,7 +95,7 @@ class Statistics {
95
95
  protocol,
96
96
  this.currentStats.ongoingRequests.get(protocol) - 1);
97
97
 
98
- if (!this.currentStats.completedRequests.has(protocol)) {
98
+ if (! this.currentStats.completedRequests.has(protocol)) {
99
99
  this.currentStats.completedRequests.set(protocol, 1);
100
100
  }
101
101
  else {
@@ -117,7 +117,7 @@ class Statistics {
117
117
 
118
118
  const protocol = request && request.context.connection.protocol;
119
119
 
120
- if (!protocol) {
120
+ if (! protocol) {
121
121
  return;
122
122
  }
123
123
 
@@ -125,7 +125,7 @@ class Statistics {
125
125
  protocol,
126
126
  this.currentStats.ongoingRequests.get(protocol) - 1);
127
127
 
128
- if (!this.currentStats.failedRequests.has(protocol)) {
128
+ if (! this.currentStats.failedRequests.has(protocol)) {
129
129
  this.currentStats.failedRequests.set(protocol, 1);
130
130
  }
131
131
  else {
@@ -145,11 +145,11 @@ class Statistics {
145
145
  return;
146
146
  }
147
147
 
148
- if (!requestContext.connection.protocol) {
148
+ if (! requestContext.connection.protocol) {
149
149
  return;
150
150
  }
151
151
 
152
- if (!this.currentStats.connections.has(requestContext.connection.protocol)) {
152
+ if (! this.currentStats.connections.has(requestContext.connection.protocol)) {
153
153
  this.currentStats.connections.set(requestContext.connection.protocol, 1);
154
154
  }
155
155
  else {
@@ -169,7 +169,7 @@ class Statistics {
169
169
  return;
170
170
  }
171
171
 
172
- if (!requestContext.connection.protocol) {
172
+ if (! requestContext.connection.protocol) {
173
173
  return;
174
174
  }
175
175
 
@@ -194,10 +194,10 @@ class Statistics {
194
194
  }
195
195
 
196
196
  const frame = Object.assign(
197
- {timestamp: (new Date()).getTime()},
197
+ { timestamp: (new Date()).getTime() },
198
198
  this.currentStats);
199
199
 
200
- if (!this.lastFrame) {
200
+ if (! this.lastFrame) {
201
201
  return frame;
202
202
  }
203
203
 
@@ -260,11 +260,11 @@ class Statistics {
260
260
  ongoingRequests: Object.fromEntries(this.currentStats.ongoingRequests),
261
261
  };
262
262
 
263
- if (!this.lastFrame) {
264
- if (!stopTime || stopTime >= currentDate) {
263
+ if (! this.lastFrame) {
264
+ if (! stopTime || stopTime >= currentDate) {
265
265
  response.hits.push(
266
266
  Object.assign(
267
- {timestamp: (new Date(currentDate)).getTime()},
267
+ { timestamp: (new Date(currentDate)).getTime() },
268
268
  stats));
269
269
  }
270
270
 
@@ -288,13 +288,13 @@ class Statistics {
288
288
  const frameDate = new Date(Number(frames[idx].replace(regex, '')));
289
289
  const frameDateTime = frameDate.getTime();
290
290
 
291
- if ( (!startTime || startTime <= frameDateTime)
292
- && (!stopTime || stopTime >= frameDateTime)
291
+ if ( (! startTime || startTime <= frameDateTime)
292
+ && (! stopTime || stopTime >= frameDateTime)
293
293
  ) {
294
294
  response.hits.push(
295
295
  Object.assign(
296
296
  JSON.parse(v),
297
- {timestamp: (new Date(frameDateTime)).getTime()}));
297
+ { timestamp: (new Date(frameDateTime)).getTime() }));
298
298
  }
299
299
  });
300
300