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
@@ -23,9 +23,9 @@
23
23
 
24
24
  const os = require('os');
25
25
  const jsonToYaml = require('json2yaml');
26
+ const packagejson = require('../../../package.json');
26
27
 
27
28
  const { NativeController } = require('./baseController');
28
- const { generateOpenApi } = require('../openApiGenerator');
29
29
 
30
30
  const kerror = require('../../kerror');
31
31
 
@@ -33,9 +33,10 @@ const kerror = require('../../kerror');
33
33
  * @class ServerController
34
34
  */
35
35
  class ServerController extends NativeController {
36
- constructor() {
36
+ constructor () {
37
37
  super([
38
38
  'adminExists',
39
+ 'capabilities',
39
40
  'getAllStats',
40
41
  'getConfig',
41
42
  'getLastStats',
@@ -48,12 +49,28 @@ class ServerController extends NativeController {
48
49
  'openapi',
49
50
  ]);
50
51
 
51
- this._openApiDefinition = {
52
- json: null,
53
- yaml: null,
52
+ this._info = {
53
+ elasticsearch: null,
54
+ redis: null,
54
55
  };
55
56
  }
56
57
 
58
+ /**
59
+ * Init ServerController
60
+ * Used to perform asynchronous initialization safely: the funnel will wait
61
+ * for all controllers to be initialized before accepting requests.
62
+ *
63
+ * @returns {Promise}
64
+ */
65
+ async init () {
66
+ const [storageInfo, cacheInfo] = await Promise.all([
67
+ global.kuzzle.ask('core:storage:public:info:get'),
68
+ global.kuzzle.ask('core:cache:public:info:get'),
69
+ ]);
70
+ this._info.elasticsearch = storageInfo;
71
+ this._info.redis = cacheInfo;
72
+ }
73
+
57
74
  /**
58
75
  * Returns the statistics frame from a date
59
76
  *
@@ -110,6 +127,39 @@ class ServerController extends NativeController {
110
127
  return config;
111
128
  }
112
129
 
130
+ /**
131
+ * Returns the Kuzzle capabilities
132
+ * @returns {Promise<Object>}
133
+ */
134
+ async capabilities () {
135
+ const config = JSON.parse(JSON.stringify(global.kuzzle.config));
136
+ const publicApi = await this.publicApi();
137
+ const services = {};
138
+ const plugins = {};
139
+
140
+ for (const plugin of config.plugins.common.include) {
141
+ plugins[plugin] = {
142
+ version: packagejson.dependencies[plugin]
143
+ };
144
+ }
145
+
146
+ for (const [name, info] of Object.entries(config.services)) {
147
+ if (info.backend !== undefined) {
148
+ services[name] = {
149
+ backend: info.backend,
150
+ version: this._info[info.backend].version,
151
+ };
152
+ }
153
+ }
154
+
155
+ return {
156
+ limits: config.limits,
157
+ plugins: plugins,
158
+ routes: publicApi,
159
+ services: services,
160
+ version: config.version,
161
+ };
162
+ }
113
163
  /**
114
164
  * Checks if an admin user Exists
115
165
  *
@@ -140,7 +190,7 @@ class ServerController extends NativeController {
140
190
  if (typeof request.input.args.services === 'string') {
141
191
  services = request.input.args.services.split(',');
142
192
  }
143
- if (!services || services.includes('internalCache')) {
193
+ if (! services || services.includes('internalCache')) {
144
194
  try {
145
195
  await global.kuzzle.ask('core:cache:internal:info:get');
146
196
  result.services.internalCache = 'green';
@@ -151,7 +201,7 @@ class ServerController extends NativeController {
151
201
  result.status = 'red';
152
202
  }
153
203
  }
154
- if (!services || services.includes('memoryStorage')) {
204
+ if (! services || services.includes('memoryStorage')) {
155
205
  try {
156
206
  await global.kuzzle.ask('core:cache:public:info:get');
157
207
  result.services.memoryStorage = 'green';
@@ -162,7 +212,7 @@ class ServerController extends NativeController {
162
212
  result.status = 'red';
163
213
  }
164
214
  }
165
- if (!services || services.includes('storageEngine')) {
215
+ if (! services || services.includes('storageEngine')) {
166
216
  try {
167
217
  const response = await global.kuzzle.ask('core:storage:public:info:get');
168
218
 
@@ -247,7 +297,19 @@ class ServerController extends NativeController {
247
297
 
248
298
  async openapi (request) {
249
299
  const format = request.getString('format', 'json');
250
- const specifications = this.getOpenApiDefinition(format);
300
+ const scope = request.getString('scope', 'kuzzle');
301
+
302
+ let definition;
303
+
304
+ if (scope === 'kuzzle') {
305
+ definition = await global.kuzzle.ask('core:api:openapi:kuzzle');
306
+ }
307
+ else if (scope === 'app') {
308
+ definition = await global.kuzzle.ask('core:api:openapi:app');
309
+ }
310
+ else {
311
+ throw kerror.get('api', 'assert', 'unexpected_argument', scope, ['kuzzle', 'app']);
312
+ }
251
313
 
252
314
  request.response.configure({
253
315
  format: 'raw',
@@ -255,23 +317,7 @@ class ServerController extends NativeController {
255
317
  status: 200,
256
318
  });
257
319
 
258
- return specifications;
259
- }
260
-
261
- /**
262
- * Lazy loading of OpenAPI definition.
263
- *
264
- * Mainly because we need to wait all plugin to be loaded
265
- * to generate the definition.
266
- */
267
- getOpenApiDefinition (format) {
268
- if (! this._openApiDefinition[format]) {
269
- this._openApiDefinition[format] = format === 'json'
270
- ? generateOpenApi()
271
- : jsonToYaml.stringify(generateOpenApi());
272
- }
273
-
274
- return this._openApiDefinition[format];
320
+ return format === 'json' ? definition : jsonToYaml.stringify(definition);
275
321
  }
276
322
 
277
323
  /**
@@ -293,7 +339,7 @@ class ServerController extends NativeController {
293
339
  const actionList = {};
294
340
 
295
341
  for (const action of controller._actions) {
296
- actionList[action] = { action , controller: name };
342
+ actionList[action] = { action, controller: name };
297
343
 
298
344
  // resolve associated http route for each actions
299
345
  const routes = httpRoutes.filter(route => {
@@ -229,7 +229,7 @@ const extractors = ([
229
229
  }, {});
230
230
 
231
231
  class DocumentExtractor {
232
- constructor(request) {
232
+ constructor (request) {
233
233
  this.request = request;
234
234
 
235
235
  const extractor = extractors[request.input.action];
@@ -248,11 +248,11 @@ class DocumentExtractor {
248
248
  }
249
249
  }
250
250
 
251
- extract() {
251
+ extract () {
252
252
  return this.extractMethod(this.request);
253
253
  }
254
254
 
255
- insert(documents) {
255
+ insert (documents) {
256
256
  return this.insertMethod(documents, this.request);
257
257
  }
258
258
  }
package/lib/api/funnel.js CHANGED
@@ -61,7 +61,7 @@ const SKIP_TOKEN_VERIF_ACTIONS = ['login', 'checkToken', 'logout'];
61
61
  * @param {Object} context
62
62
  */
63
63
  class PendingRequest {
64
- constructor(request, fn, context) {
64
+ constructor (request, fn, context) {
65
65
  this.request = request;
66
66
  this.fn = fn;
67
67
  this.context = context;
@@ -132,7 +132,7 @@ class Funnel {
132
132
  return Bluebird.all(initPromises);
133
133
  }
134
134
 
135
- loadDocumentEventAliases() {
135
+ loadDocumentEventAliases () {
136
136
  this.documentEventAliases = documentEventAliases;
137
137
  this.documentEventAliases.mirrorList = {};
138
138
 
@@ -223,13 +223,13 @@ class Funnel {
223
223
  throw error;
224
224
  }
225
225
 
226
- if (!this.pendingRequestsById.has(request.internalId)) {
226
+ if (! this.pendingRequestsById.has(request.internalId)) {
227
227
  this.pendingRequestsById.set(
228
228
  request.internalId,
229
229
  new PendingRequest(request, fn, context));
230
230
  this.pendingRequestsQueue.push(request.internalId);
231
231
 
232
- if (!this.overloaded) {
232
+ if (! this.overloaded) {
233
233
  this.overloaded = true;
234
234
 
235
235
  /*
@@ -262,23 +262,39 @@ class Funnel {
262
262
  * @returns {Number} -1: request delayed, 0: request processing, 1: error
263
263
  */
264
264
  execute (request, callback) {
265
- if (!request.input.controller || !request.input.controller.length) {
265
+ if (! request.input.controller || ! request.input.controller.length) {
266
266
  callback(
267
267
  kerror.get('api', 'assert', 'missing_argument', 'controller'),
268
268
  request);
269
269
  return 1;
270
270
  }
271
271
 
272
- if (!request.input.action || !request.input.action.length) {
272
+ if (! request.input.action || ! request.input.action.length) {
273
273
  callback(
274
274
  kerror.get('api', 'assert', 'missing_argument', 'action'),
275
275
  request);
276
276
  return 1;
277
277
  }
278
278
 
279
+ // If there is a body, retrieve the targets if any
280
+ const targets = request.getArray('targets', []);
281
+ /**
282
+ * Only index and collection as a pair or the targets parameter is allowed at the same time
283
+ * otherwise we throw an error because we don't know which one to use to verify the rights
284
+ */
285
+ if ( targets.length > 0
286
+ && (request.input.args.index
287
+ || request.input.args.collection)
288
+ ) {
289
+ callback(
290
+ kerror.get('api', 'assert', 'mutually_exclusive', 'index, collection', 'targets'),
291
+ request);
292
+ return 1;
293
+ }
294
+
279
295
  if (request.input.headers
280
296
  && has(request.input.headers, 'origin')
281
- && !this._isOriginAuthorized(request.input.headers.origin)
297
+ && ! this._isOriginAuthorized(request.input.headers.origin)
282
298
  ) {
283
299
  debug('Reject request, unauthorized origin %s', request.input.headers.origin);
284
300
  return this._executeError(
@@ -292,7 +308,7 @@ class Funnel {
292
308
  const executing = this.throttle(req => {
293
309
  // if the connection is closed there is no need to execute the request
294
310
  // => discarding it
295
- if (!global.kuzzle.router.isConnectionAlive(req.context)) {
311
+ if (! global.kuzzle.router.isConnectionAlive(req.context)) {
296
312
  debug('Client connection dead: dropping request: %a', req.input);
297
313
  callback(processError.get('connection_dropped'), req);
298
314
  return;
@@ -314,7 +330,7 @@ class Funnel {
314
330
  return this.rateLimiter.isAllowed(_request);
315
331
  })
316
332
  .then(allowed => {
317
- if (!allowed) {
333
+ if (! allowed) {
318
334
  if (request.input.controller === 'auth' && request.input.action === 'login') {
319
335
  throw processError.get('too_many_logins_requests');
320
336
  }
@@ -346,7 +362,8 @@ class Funnel {
346
362
  }, this, request);
347
363
 
348
364
  return executing ? 0 : -1;
349
- } catch (error) {
365
+ }
366
+ catch (error) {
350
367
  request.setError(error);
351
368
  callback(error, request);
352
369
  return 1;
@@ -374,11 +391,11 @@ class Funnel {
374
391
  // JSON.stringify(new NativeError()) === '{}'
375
392
  // i.e. Error, SyntaxError, TypeError, ReferenceError, etc.
376
393
  global.kuzzle.log.error(
377
- err instanceof Error && !(err instanceof KuzzleError)
394
+ err instanceof Error && ! (err instanceof KuzzleError)
378
395
  ? `${err.message}\n${err.stack}`
379
396
  : err);
380
397
 
381
- if (!this.lastDumpedErrors[errorType]
398
+ if (! this.lastDumpedErrors[errorType]
382
399
  || this.lastDumpedErrors[errorType] < now - handledErrors.minInterval
383
400
  ) {
384
401
  // simplify error message to use it in folder dump name
@@ -432,7 +449,7 @@ class Funnel {
432
449
  cookie = Cookie.parse(request.input.headers.cookie);
433
450
  }
434
451
  catch (error) {
435
- throw kerror.get('security','cookie', 'invalid');
452
+ throw kerror.get('security', 'cookie', 'invalid');
436
453
  }
437
454
 
438
455
  // if cookie is present and not null, and a token is present we should throw because we don't know which one to use
@@ -546,7 +563,7 @@ class Funnel {
546
563
  responseData,
547
564
  { status: _request.status === 102 ? 200 : _request.status });
548
565
 
549
- if (!this.isNativeController(_request.input.controller) && !_request.response.raw) {
566
+ if (! this.isNativeController(_request.input.controller) && ! _request.response.raw) {
550
567
  // check if the plugin response can be serialized
551
568
  try {
552
569
  JSON.stringify(responseData);
@@ -591,9 +608,9 @@ class Funnel {
591
608
  controller === 'document'
592
609
  && this.documentEventAliases.mirrorList[action]
593
610
  && ( prefix !== 'before'
594
- || !this.documentEventAliases.notBefore.includes(action));
611
+ || ! this.documentEventAliases.notBefore.includes(action));
595
612
 
596
- if (!mustTrigger) {
613
+ if (! mustTrigger) {
597
614
  return request;
598
615
  }
599
616
 
@@ -680,7 +697,7 @@ class Funnel {
680
697
  ? 'ms'
681
698
  : request.input.controller;
682
699
 
683
- return`${event}:${prefix}${capitalize(request.input.action)}`;
700
+ return `${event}:${prefix}${capitalize(request.input.action)}`;
684
701
  }
685
702
 
686
703
  /**
@@ -823,10 +840,12 @@ class Funnel {
823
840
  try {
824
841
  if (this.throttle(pendingItem.fn, pendingItem.context, pendingItem.request)) {
825
842
  this.pendingRequestsQueue.shift();
826
- } else {
843
+ }
844
+ else {
827
845
  break;
828
846
  }
829
- } catch (error) {
847
+ }
848
+ catch (error) {
830
849
  break;
831
850
  }
832
851
  }
@@ -857,7 +876,7 @@ class Funnel {
857
876
  * @returns {KuzzleError}
858
877
  */
859
878
  _wrapError (request, error) {
860
- if (!this.isNativeController(request) && !(error instanceof KuzzleError)) {
879
+ if (! this.isNativeController(request) && ! (error instanceof KuzzleError)) {
861
880
  return kerror.getFrom(
862
881
  error,
863
882
  'plugin',
@@ -916,7 +935,7 @@ function capitalize (string) {
916
935
  function doAction (controller, request) {
917
936
  const ret = controller[request.input.action](request);
918
937
 
919
- if (!ret || typeof ret.then !== 'function') {
938
+ if (! ret || typeof ret.then !== 'function') {
920
939
  return kerror.reject(
921
940
  'plugin',
922
941
  'controller',
@@ -34,7 +34,8 @@ const {
34
34
  OpenApiDocumentGet,
35
35
  OpenApiDocumentCreate,
36
36
  OpenApiDocumentCreateOrReplace,
37
- } = require('./openapi/document');
37
+ OpenApiDocumentValidate,
38
+ } = require('./openapi/components/document');
38
39
 
39
40
 
40
41
  const routes = [
@@ -53,6 +54,7 @@ const routes = [
53
54
  // We need to expose a GET method for "login" action in order to make authentication protocol like Oauth2 or CAS work:
54
55
  { verb: 'get', path: '/_login/:strategy', controller: 'auth', action: 'login' },
55
56
 
57
+ { verb: 'get', path: '/:index/:collection/_export', controller: 'document', action: 'export' },
56
58
  { verb: 'get', path: '/:index/:collection/_exists', controller: 'collection', action: 'exists' },
57
59
  { verb: 'get', path: '/:index/:collection/_mapping', controller: 'collection', action: 'getMapping' },
58
60
  { verb: 'get', path: '/:index/:collection/_search', controller: 'document', action: 'search' },
@@ -74,6 +76,7 @@ const routes = [
74
76
  { verb: 'get', path: '/:index/:collection/:_id', controller: 'document', action: 'get', openapi: OpenApiDocumentGet },
75
77
  { verb: 'get', path: '/:index/:collection/_mGet', controller: 'document', action: 'mGet' },
76
78
  { verb: 'get', path: '/:index/:collection/:_id/_exists', controller: 'document', action: 'exists', openapi: OpenApiDocumentExists },
79
+ { verb: 'get', path: '/:index/:collection/_mExists', controller: 'document', action: 'mExists' },
77
80
  { verb: 'get', path: '/_scroll/:scrollId', controller: 'document', action: 'scroll', openapi: OpenApiDocumentScroll },
78
81
 
79
82
  { verb: 'get', path: '/:index/_exists', controller: 'index', action: 'exists' },
@@ -104,6 +107,7 @@ const routes = [
104
107
  { verb: 'get', path: '/_adminExists', controller: 'server', action: 'adminExists' },
105
108
  { verb: 'get', path: '/_getAllStats', controller: 'server', action: 'getAllStats', deprecated: { since: 'auto-version', message: 'Use this route instead: http://kuzzle:7512/_metrics' } }, // @deprecated
106
109
  { verb: 'get', path: '/_getConfig', controller: 'server', action: 'getConfig' },
110
+ { verb: 'get', path: '/_capabilities', controller: 'server', action: 'capabilities' },
107
111
  { verb: 'get', path: '/_getLastStats', controller: 'server', action: 'getLastStats', deprecated: { since: 'auto-version', message: 'Use this route instead: http://kuzzle:7512/_metrics' } }, // @deprecated
108
112
  { verb: 'get', path: '/_getStats', controller: 'server', action: 'getStats', deprecated: { since: 'auto-version', message: 'Use this route instead: http://kuzzle:7512/_metrics' } }, // @deprecated
109
113
  { verb: 'get', path: '/', controller: 'server', action: 'info' },
@@ -171,7 +175,7 @@ const routes = [
171
175
  { verb: 'get', path: '/ms/_zscan/:_id', controller: 'ms', action: 'zscan' },
172
176
  { verb: 'get', path: '/ms/_zscore/:_id/:member', controller: 'ms', action: 'zscore' },
173
177
  { verb: 'get', path: '/ms/:_id', controller: 'ms', action: 'get' },
174
- { verb: 'get', path: '/cluster/_status', controller:'cluster', action: 'status' },
178
+ { verb: 'get', path: '/cluster/_status', controller: 'cluster', action: 'status' },
175
179
 
176
180
 
177
181
  // POST
@@ -202,12 +206,13 @@ const routes = [
202
206
  { verb: 'post', path: '/:index/:collection/_create', controller: 'document', action: 'create', openapi: OpenApiDocumentCreate },
203
207
  { verb: 'post', path: '/:index/:collection/:_id/_create', controller: 'document', action: 'create' },
204
208
  { verb: 'post', path: '/:index/:collection/_publish', controller: 'realtime', action: 'publish' },
209
+ { verb: 'post', path: '/:index/:collection/_export', controller: 'document', action: 'export' },
205
210
  { verb: 'post', path: '/:index/:collection/_search', controller: 'document', action: 'search' },
206
211
  { verb: 'post', path: '/:index/:collection/_mGet', controller: 'document', action: 'mGet' },
207
212
  { verb: 'post', path: '/:index/:collection/_mCreate', controller: 'document', action: 'mCreate' },
208
213
  { verb: 'post', path: '/:index/:collection/_mUpsert', controller: 'document', action: 'mUpsert' },
209
- { verb: 'post', path: '/:index/:collection/:_id/_upsert', controller: 'document', action: 'upsert'},
210
- { verb: 'post', path: '/:index/:collection/_validate', controller: 'document', action: 'validate' },
214
+ { verb: 'post', path: '/:index/:collection/:_id/_upsert', controller: 'document', action: 'upsert' },
215
+ { verb: 'post', path: '/:index/:collection/_validate', controller: 'document', action: 'validate', openapi: OpenApiDocumentValidate },
211
216
 
212
217
  { verb: 'post', path: '/_createFirstAdmin/:_id', controller: 'security', action: 'createFirstAdmin' },
213
218
  { verb: 'post', path: '/_createFirstAdmin', controller: 'security', action: 'createFirstAdmin' },
@@ -0,0 +1,11 @@
1
+ import { OpenApiDefinition } from '../../types/OpenApiDefinition';
2
+ export declare class OpenApiManager {
3
+ kuzzleDefinition: OpenApiDefinition;
4
+ applicationDefinition: OpenApiDefinition;
5
+ /**
6
+ * @param applicationDefinition Application OpenApi definition
7
+ * @param pluginsManager PluginsManager instance
8
+ */
9
+ constructor(applicationDefinition: OpenApiDefinition, kuzzleRoutes: any[], pluginsRoutes: any[]);
10
+ registerAskEvents(): void;
11
+ }
@@ -0,0 +1,96 @@
1
+ "use strict";
2
+ /*
3
+ * Kuzzle, a backend software, self-hostable and ready to use
4
+ * to power modern apps
5
+ *
6
+ * Copyright 2015-2020 Kuzzle
7
+ * mailto: support AT kuzzle.io
8
+ * website: http://kuzzle.io
9
+ *
10
+ * Licensed under the Apache License, Version 2.0 (the "License");
11
+ * you may not use this file except in compliance with the License.
12
+ * You may obtain a copy of the License at
13
+ *
14
+ * https://www.apache.org/licenses/LICENSE-2.0
15
+ *
16
+ * Unless required by applicable law or agreed to in writing, software
17
+ * distributed under the License is distributed on an "AS IS" BASIS,
18
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19
+ * See the License for the specific language governing permissions and
20
+ * limitations under the License.
21
+ */
22
+ Object.defineProperty(exports, "__esModule", { value: true });
23
+ exports.OpenApiManager = void 0;
24
+ const components_1 = require("./components");
25
+ const package_json_1 = require("../../../package.json");
26
+ const openApiGenerator_1 = require("./openApiGenerator");
27
+ class OpenApiManager {
28
+ /**
29
+ * @param applicationDefinition Application OpenApi definition
30
+ * @param pluginsManager PluginsManager instance
31
+ */
32
+ constructor(applicationDefinition, kuzzleRoutes, pluginsRoutes) {
33
+ /* eslint-disable sort-keys */
34
+ this.kuzzleDefinition = {
35
+ swagger: '2.0',
36
+ info: {
37
+ title: 'Kuzzle API',
38
+ description: 'Kuzzle HTTP API definition',
39
+ contact: {
40
+ name: 'Kuzzle team',
41
+ url: 'https://kuzzle.io',
42
+ email: 'support@kuzzle.io',
43
+ discord: 'http://join.discord.kuzzle.io'
44
+ },
45
+ license: {
46
+ name: 'Apache 2',
47
+ url: 'http://opensource.org/licenses/apache2.0'
48
+ },
49
+ version: package_json_1.version
50
+ },
51
+ externalDocs: {
52
+ description: 'Kuzzle API Documentation',
53
+ url: 'https://docs.kuzzle.io/core/2/api/'
54
+ },
55
+ servers: [
56
+ {
57
+ url: 'https://{baseUrl}:{port}',
58
+ description: 'Kuzzle Base Url',
59
+ variables: {
60
+ baseUrl: { default: 'localhost' },
61
+ port: { default: 7512 }
62
+ },
63
+ }
64
+ ],
65
+ tags: [],
66
+ schemes: ['https', 'http'],
67
+ paths: {},
68
+ components: {
69
+ ...components_1.OpenApiPayloadsDefinitions,
70
+ document: {
71
+ ...components_1.OpenApiDocumentCountComponent,
72
+ ...components_1.OpenApiDocumentDeleteByQueryComponent,
73
+ ...components_1.OpenApiDocumentDeleteComponent,
74
+ ...components_1.OpenApiDocumentScrollComponent,
75
+ ...components_1.OpenApiDocumentExistsComponent,
76
+ ...components_1.OpenApiDocumentUpdateComponent,
77
+ ...components_1.OpenApiDocumentReplaceComponent,
78
+ ...components_1.OpenApiDocumentGetComponent,
79
+ ...components_1.OpenApiDocumentCreateOrReplaceComponent,
80
+ ...components_1.OpenApiDocumentCreateComponent,
81
+ ...components_1.OpenApiDocumentValidateComponent,
82
+ }
83
+ }
84
+ };
85
+ this.applicationDefinition = applicationDefinition;
86
+ (0, openApiGenerator_1.generateOpenApi)(kuzzleRoutes, this.kuzzleDefinition);
87
+ (0, openApiGenerator_1.generateOpenApi)(pluginsRoutes, this.applicationDefinition);
88
+ this.registerAskEvents();
89
+ }
90
+ registerAskEvents() {
91
+ global.kuzzle.onAsk('core:api:openapi:kuzzle', () => this.kuzzleDefinition);
92
+ global.kuzzle.onAsk('core:api:openapi:app', () => this.applicationDefinition);
93
+ }
94
+ }
95
+ exports.OpenApiManager = OpenApiManager;
96
+ //# sourceMappingURL=OpenApiManager.js.map
@@ -16,12 +16,12 @@ DocumentCount:
16
16
  description: "Counts documents in a collection."
17
17
  required: true
18
18
  schema:
19
- $ref: "#/components/schemas/DocumentCountRequest"
19
+ $ref: "#/components/document/DocumentCountRequest"
20
20
  responses:
21
21
  200:
22
22
  description: "Counts documents in a collection."
23
23
  schema:
24
- $ref: "#/components/schemas/DocumentCountResponse"
24
+ $ref: "#/components/document/DocumentCountResponse"
25
25
 
26
26
  components:
27
27
  schemas:
@@ -16,12 +16,12 @@ DocumentCreate:
16
16
  description: "Creates a new document in the persistent data storage."
17
17
  required: true
18
18
  schema:
19
- $ref: "#/components/schemas/DocumentCreateRequest"
19
+ $ref: "#/components/document/DocumentCreateRequest"
20
20
  responses:
21
21
  200:
22
22
  description: "Creates a new document in the persistent data storage."
23
23
  schema:
24
- $ref: "#/components/schemas/DocumentCreateResponse"
24
+ $ref: "#/components/document/DocumentCreateResponse"
25
25
 
26
26
  components:
27
27
  schemas:
@@ -28,12 +28,12 @@ DocumentCreateOrReplace:
28
28
  description: "Creates a new document in the persistent data storage, or replaces its content if it already exists."
29
29
  required: true
30
30
  schema:
31
- $ref: "#/components/schemas/DocumentCreateOrReplaceRequest"
31
+ $ref: "#/components/document/DocumentCreateOrReplaceRequest"
32
32
  responses:
33
33
  200:
34
34
  description: "Creates a new document in the persistent data storage, or replaces its content if it already exists."
35
35
  schema:
36
- $ref: "#/components/schemas/DocumentCreateOrReplaceResponse"
36
+ $ref: "#/components/document/DocumentCreateOrReplaceResponse"
37
37
 
38
38
  components:
39
39
  schemas:
@@ -40,7 +40,7 @@ DocumentDelete:
40
40
  200:
41
41
  description: "Deletes a document."
42
42
  schema:
43
- $ref: "#/components/schemas/DocumentDeleteResponse"
43
+ $ref: "#/components/document/DocumentDeleteResponse"
44
44
 
45
45
  components:
46
46
  schemas:
@@ -47,12 +47,12 @@ DocumentDeleteByQuery:
47
47
  description: "Deletes documents matching the provided search query."
48
48
  required: true
49
49
  schema:
50
- $ref: "#/components/schemas/DocumentDeleteByQueryRequest"
50
+ $ref: "#/components/document/DocumentDeleteByQueryRequest"
51
51
  responses:
52
52
  200:
53
53
  description: "Deletes documents matching the provided search query."
54
54
  schema:
55
- $ref: "#/components/schemas/DocumentDeleteByQueryResponse"
55
+ $ref: "#/components/document/DocumentDeleteByQueryResponse"
56
56
 
57
57
  components:
58
58
  schemas:
@@ -22,7 +22,7 @@ DocumentExists:
22
22
  200:
23
23
  description: "Checks if a document exists."
24
24
  schema:
25
- $ref: "#/components/schemas/DocumentExistsResponse"
25
+ $ref: "#/components/document/DocumentExistsResponse"
26
26
 
27
27
  components:
28
28
  schemas:
@@ -22,7 +22,7 @@ DocumentGet:
22
22
  200:
23
23
  description: "Gets a document."
24
24
  schema:
25
- $ref: "#/components/schemas/DocumentGetResponse"
25
+ $ref: "#/components/document/DocumentGetResponse"
26
26
 
27
27
  components:
28
28
  schemas:
@@ -18,3 +18,5 @@ export declare const OpenApiDocumentDelete: any;
18
18
  export declare const OpenApiDocumentDeleteComponent: any;
19
19
  export declare const OpenApiDocumentDeleteByQuery: any;
20
20
  export declare const OpenApiDocumentDeleteByQueryComponent: any;
21
+ export declare const OpenApiDocumentValidate: any;
22
+ export declare const OpenApiDocumentValidateComponent: any;