kuzzle 2.17.7 → 2.18.1

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 (212) hide show
  1. package/bin/start-kuzzle-server +1 -1
  2. package/lib/api/controllers/adminController.js +1 -1
  3. package/lib/api/controllers/authController.js +9 -3
  4. package/lib/api/controllers/baseController.js +1 -1
  5. package/lib/api/controllers/bulkController.js +1 -1
  6. package/lib/api/controllers/clusterController.js +1 -1
  7. package/lib/api/controllers/collectionController.js +1 -1
  8. package/lib/api/controllers/documentController.js +13 -4
  9. package/lib/api/controllers/index.js +1 -1
  10. package/lib/api/controllers/indexController.js +11 -7
  11. package/lib/api/controllers/memoryStorageController.js +1 -1
  12. package/lib/api/controllers/realtimeController.js +1 -1
  13. package/lib/api/controllers/securityController.js +80 -42
  14. package/lib/api/controllers/serverController.js +3 -2
  15. package/lib/api/documentExtractor.js +3 -2
  16. package/lib/api/funnel.js +1 -1
  17. package/lib/api/httpRoutes.js +7 -5
  18. package/lib/api/openapi/OpenApiManager.js +5 -1
  19. package/lib/api/openapi/components/document/get.yaml +1 -1
  20. package/lib/api/openapi/components/document/index.d.ts +2 -0
  21. package/lib/api/openapi/components/document/index.js +6 -1
  22. package/lib/api/openapi/components/document/mCreateOrReplace.yaml +93 -0
  23. package/lib/api/openapi/components/document/update.yaml +1 -1
  24. package/lib/api/openapi/components/index.d.ts +1 -0
  25. package/lib/api/openapi/components/index.js +1 -0
  26. package/lib/api/openapi/components/security/index.d.ts +2 -0
  27. package/lib/api/openapi/components/security/index.js +10 -0
  28. package/lib/api/openapi/components/security/upsertUser.yaml +59 -0
  29. package/lib/api/openapi/openApiGenerator.js +1 -1
  30. package/lib/api/rateLimiter.js +1 -1
  31. package/lib/api/request/kuzzleRequest.d.ts +46 -0
  32. package/lib/api/request/kuzzleRequest.js +147 -19
  33. package/lib/api/request/requestContext.js +1 -1
  34. package/lib/api/request/requestInput.js +1 -1
  35. package/lib/api/request/requestResponse.js +26 -1
  36. package/lib/cluster/command.js +1 -1
  37. package/lib/cluster/idCardHandler.js +1 -1
  38. package/lib/cluster/index.js +1 -1
  39. package/lib/cluster/node.js +8 -8
  40. package/lib/cluster/publisher.js +1 -1
  41. package/lib/cluster/state.js +1 -1
  42. package/lib/cluster/subscriber.js +4 -1
  43. package/lib/config/documentEventAliases.js +1 -1
  44. package/lib/config/index.js +1 -1
  45. package/lib/core/auth/formatProcessing.js +1 -1
  46. package/lib/core/auth/passportResponse.js +1 -1
  47. package/lib/core/auth/passportWrapper.js +1 -1
  48. package/lib/core/auth/tokenManager.js +1 -1
  49. package/lib/core/backend/applicationManager.js +1 -1
  50. package/lib/core/backend/backend.js +1 -1
  51. package/lib/core/backend/backendCluster.js +1 -1
  52. package/lib/core/backend/backendConfig.js +1 -1
  53. package/lib/core/backend/backendController.d.ts +7 -1
  54. package/lib/core/backend/backendController.js +16 -4
  55. package/lib/core/backend/backendErrors.js +1 -1
  56. package/lib/core/backend/backendHook.js +1 -1
  57. package/lib/core/backend/backendImport.js +1 -1
  58. package/lib/core/backend/backendOpenApi.js +1 -1
  59. package/lib/core/backend/backendPipe.js +1 -1
  60. package/lib/core/backend/backendPlugin.js +1 -1
  61. package/lib/core/backend/backendStorage.js +1 -1
  62. package/lib/core/backend/backendVault.js +1 -1
  63. package/lib/core/backend/internalLogger.js +1 -1
  64. package/lib/core/cache/cacheDbEnum.js +1 -1
  65. package/lib/core/cache/cacheEngine.js +1 -1
  66. package/lib/core/network/accessLogger.js +1 -1
  67. package/lib/core/network/clientConnection.js +1 -1
  68. package/lib/core/network/context.js +1 -1
  69. package/lib/core/network/entryPoint.js +6 -6
  70. package/lib/core/network/httpRouter/index.js +1 -1
  71. package/lib/core/network/httpRouter/routeHandler.js +1 -1
  72. package/lib/core/network/httpRouter/routePart.js +1 -1
  73. package/lib/core/network/protocolManifest.js +1 -1
  74. package/lib/core/network/protocols/httpMessage.js +1 -1
  75. package/lib/core/network/protocols/httpwsProtocol.js +13 -16
  76. package/lib/core/network/protocols/internalProtocol.js +1 -1
  77. package/lib/core/network/protocols/mqttProtocol.js +4 -3
  78. package/lib/core/network/protocols/protocol.js +1 -1
  79. package/lib/core/network/router.js +11 -2
  80. package/lib/core/plugin/plugin.js +8 -1
  81. package/lib/core/plugin/pluginContext.js +1 -1
  82. package/lib/core/plugin/pluginManifest.js +1 -1
  83. package/lib/core/plugin/pluginRepository.js +1 -1
  84. package/lib/core/plugin/pluginsManager.js +1 -1
  85. package/lib/core/plugin/privilegedContext.js +1 -1
  86. package/lib/core/realtime/actionEnum.js +1 -1
  87. package/lib/core/realtime/channel.js +1 -1
  88. package/lib/core/realtime/connectionRooms.js +1 -1
  89. package/lib/core/realtime/hotelClerk.js +66 -24
  90. package/lib/core/realtime/index.js +1 -1
  91. package/lib/core/realtime/notification/document.js +1 -1
  92. package/lib/core/realtime/notification/index.js +1 -1
  93. package/lib/core/realtime/notification/server.js +1 -1
  94. package/lib/core/realtime/notification/user.js +1 -1
  95. package/lib/core/realtime/notifier.js +1 -1
  96. package/lib/core/realtime/room.js +1 -1
  97. package/lib/core/realtime/subscription.js +1 -1
  98. package/lib/core/security/index.js +1 -1
  99. package/lib/core/security/profileRepository.js +1 -1
  100. package/lib/core/security/roleRepository.js +1 -1
  101. package/lib/core/security/securityLoader.js +1 -1
  102. package/lib/core/security/tokenRepository.js +1 -1
  103. package/lib/core/security/userRepository.js +1 -1
  104. package/lib/core/shared/KoncordeWrapper.js +1 -1
  105. package/lib/core/shared/abstractManifest.js +1 -1
  106. package/lib/core/shared/repository.js +1 -1
  107. package/lib/core/shared/sdk/embeddedSdk.d.ts +2 -2
  108. package/lib/core/shared/sdk/embeddedSdk.js +4 -3
  109. package/lib/core/shared/sdk/funnelProtocol.d.ts +13 -0
  110. package/lib/core/shared/sdk/funnelProtocol.js +76 -81
  111. package/lib/core/shared/sdk/impersonatedSdk.js +1 -1
  112. package/lib/core/shared/store.js +1 -1
  113. package/lib/core/statistics/index.js +1 -1
  114. package/lib/core/statistics/statistics.js +1 -1
  115. package/lib/core/storage/clientAdapter.js +1 -1
  116. package/lib/core/storage/indexCache.js +1 -1
  117. package/lib/core/storage/storageEngine.js +1 -1
  118. package/lib/core/storage/storeScopeEnum.js +1 -1
  119. package/lib/core/validation/baseType.js +1 -1
  120. package/lib/core/validation/index.js +1 -1
  121. package/lib/core/validation/types/anything.js +1 -1
  122. package/lib/core/validation/types/boolean.js +1 -1
  123. package/lib/core/validation/types/date.js +1 -1
  124. package/lib/core/validation/types/email.js +1 -1
  125. package/lib/core/validation/types/enum.js +1 -1
  126. package/lib/core/validation/types/geoPoint.js +1 -1
  127. package/lib/core/validation/types/geoShape.js +1 -1
  128. package/lib/core/validation/types/integer.js +1 -1
  129. package/lib/core/validation/types/ipAddress.js +1 -1
  130. package/lib/core/validation/types/numeric.js +1 -1
  131. package/lib/core/validation/types/object.js +1 -1
  132. package/lib/core/validation/types/string.js +1 -1
  133. package/lib/core/validation/types/url.js +1 -1
  134. package/lib/core/validation/validation.js +1 -1
  135. package/lib/kerror/codes/1-services.json +1 -1
  136. package/lib/kerror/codes/index.js +1 -1
  137. package/lib/kerror/errors/badRequestError.js +1 -1
  138. package/lib/kerror/errors/externalServiceError.js +1 -1
  139. package/lib/kerror/errors/forbiddenError.js +1 -1
  140. package/lib/kerror/errors/gatewayTimeoutError.js +1 -1
  141. package/lib/kerror/errors/index.js +1 -1
  142. package/lib/kerror/errors/internalError.js +1 -1
  143. package/lib/kerror/errors/kuzzleError.d.ts +1 -1
  144. package/lib/kerror/errors/kuzzleError.js +1 -1
  145. package/lib/kerror/errors/multipleErrorsError.js +1 -1
  146. package/lib/kerror/errors/notFoundError.js +1 -1
  147. package/lib/kerror/errors/partialError.js +1 -1
  148. package/lib/kerror/errors/pluginImplementationError.js +1 -1
  149. package/lib/kerror/errors/preconditionError.js +1 -1
  150. package/lib/kerror/errors/serviceUnavailableError.js +1 -1
  151. package/lib/kerror/errors/sizeLimitError.js +1 -1
  152. package/lib/kerror/errors/tooManyRequestsError.js +1 -1
  153. package/lib/kerror/errors/unauthorizedError.js +1 -1
  154. package/lib/kerror/index.js +2 -4
  155. package/lib/kuzzle/dumpGenerator.js +1 -1
  156. package/lib/kuzzle/event/kuzzleEventEmitter.js +39 -1
  157. package/lib/kuzzle/event/pipeRunner.js +1 -1
  158. package/lib/kuzzle/event/waterfall.js +1 -1
  159. package/lib/kuzzle/index.js +1 -1
  160. package/lib/kuzzle/internalIndexHandler.js +1 -1
  161. package/lib/kuzzle/kuzzle.js +1 -1
  162. package/lib/kuzzle/kuzzleStateEnum.js +1 -1
  163. package/lib/kuzzle/log.js +1 -1
  164. package/lib/kuzzle/vault.js +1 -1
  165. package/lib/model/security/profile.js +1 -1
  166. package/lib/model/security/rights.js +1 -1
  167. package/lib/model/security/role.js +1 -1
  168. package/lib/model/security/token.js +1 -1
  169. package/lib/model/security/user.js +6 -7
  170. package/lib/model/storage/apiKey.js +1 -1
  171. package/lib/model/storage/baseModel.js +1 -1
  172. package/lib/service/cache/redis.js +1 -1
  173. package/lib/service/service.js +1 -1
  174. package/lib/service/storage/elasticsearch.js +108 -39
  175. package/lib/service/storage/esWrapper.js +1 -1
  176. package/lib/service/storage/queryTranslator.js +1 -1
  177. package/lib/types/Controller.js +1 -1
  178. package/lib/types/ControllerDefinition.js +1 -1
  179. package/lib/types/Deprecation.js +1 -1
  180. package/lib/types/EventHandler.js +1 -1
  181. package/lib/types/KuzzleDocument.d.ts +3 -0
  182. package/lib/types/Plugin.js +1 -1
  183. package/lib/types/PluginManifest.js +1 -1
  184. package/lib/types/RequestPayload.js +1 -1
  185. package/lib/types/ResponsePayload.js +1 -1
  186. package/lib/types/StrategyDefinition.js +1 -1
  187. package/lib/types/Token.js +1 -1
  188. package/lib/types/User.js +1 -1
  189. package/lib/types/index.d.ts +0 -1
  190. package/lib/types/index.js +1 -2
  191. package/lib/util/array.js +1 -1
  192. package/lib/util/assertType.js +1 -1
  193. package/lib/util/asyncStore.js +1 -1
  194. package/lib/util/debug.js +1 -1
  195. package/lib/util/deprecate.js +1 -1
  196. package/lib/util/didYouMean.js +1 -1
  197. package/lib/util/dump-collection.d.ts +35 -0
  198. package/lib/util/dump-collection.js +11 -8
  199. package/lib/util/extractFields.js +1 -1
  200. package/lib/util/inflector.js +1 -1
  201. package/lib/util/koncordeCompat.js +1 -1
  202. package/lib/util/memoize.js +1 -1
  203. package/lib/util/mutex.js +1 -1
  204. package/lib/util/name-generator.js +1 -1
  205. package/lib/util/promback.js +1 -1
  206. package/lib/util/requestAssertions.js +1 -1
  207. package/lib/util/safeObject.js +1 -1
  208. package/lib/util/stackTrace.js +56 -17
  209. package/lib/util/wildcard.js +1 -1
  210. package/package-lock.json +102 -83
  211. package/package.json +18 -17
  212. package/lib/core/network/removeErrorStack.js +0 -56
@@ -4,7 +4,7 @@
4
4
  * Kuzzle, a backend software, self-hostable and ready to use
5
5
  * to power modern apps
6
6
  *
7
- * Copyright 2015-2020 Kuzzle
7
+ * Copyright 2015-2022 Kuzzle
8
8
  * mailto: support AT kuzzle.io
9
9
  * website: http://kuzzle.io
10
10
  *
@@ -2,7 +2,7 @@
2
2
  * Kuzzle, a backend software, self-hostable and ready to use
3
3
  * to power modern apps
4
4
  *
5
- * Copyright 2015-2020 Kuzzle
5
+ * Copyright 2015-2022 Kuzzle
6
6
  * mailto: support AT kuzzle.io
7
7
  * website: http://kuzzle.io
8
8
  *
@@ -2,7 +2,7 @@
2
2
  * Kuzzle, a backend software, self-hostable and ready to use
3
3
  * to power modern apps
4
4
  *
5
- * Copyright 2015-2020 Kuzzle
5
+ * Copyright 2015-2022 Kuzzle
6
6
  * mailto: support AT kuzzle.io
7
7
  * website: http://kuzzle.io
8
8
  *
@@ -35,6 +35,7 @@ const { NativeController } = require('./baseController');
35
35
  const formatProcessing = require('../../core/auth/formatProcessing');
36
36
  const { User } = require('../../model/security/user');
37
37
  const ApiKey = require('../../model/storage/apiKey');
38
+ const SecurityController = require('./securityController');
38
39
 
39
40
  /**
40
41
  * @class AuthController
@@ -471,7 +472,7 @@ class AuthController extends NativeController {
471
472
  userId,
472
473
  });
473
474
 
474
- global.kuzzle.log.info(`[SECURITY] User "${userId}" applied action "${request.input.action}" on user "${userId}."`);
475
+ global.kuzzle.log.info(`[SECURITY] ${SecurityController.userOrSdk(userId)} applied action "${request.input.action}" on user "${userId}."`);
475
476
 
476
477
  return formatProcessing.serializeUser(user);
477
478
  }
@@ -646,7 +647,12 @@ class AuthController extends NativeController {
646
647
 
647
648
  assertIsAuthenticated (request) {
648
649
  if (request.context.user._id === this.anonymousId) {
649
- throw kerror.get('security', 'rights', 'unauthorized');
650
+ throw kerror.get(
651
+ 'security',
652
+ 'rights',
653
+ 'unauthorized',
654
+ request.input.controller,
655
+ request.input.action);
650
656
  }
651
657
  }
652
658
  }
@@ -2,7 +2,7 @@
2
2
  * Kuzzle, a backend software, self-hostable and ready to use
3
3
  * to power modern apps
4
4
  *
5
- * Copyright 2015-2020 Kuzzle
5
+ * Copyright 2015-2022 Kuzzle
6
6
  * mailto: support AT kuzzle.io
7
7
  * website: http://kuzzle.io
8
8
  *
@@ -2,7 +2,7 @@
2
2
  * Kuzzle, a backend software, self-hostable and ready to use
3
3
  * to power modern apps
4
4
  *
5
- * Copyright 2015-2020 Kuzzle
5
+ * Copyright 2015-2022 Kuzzle
6
6
  * mailto: support AT kuzzle.io
7
7
  * website: http://kuzzle.io
8
8
  *
@@ -2,7 +2,7 @@
2
2
  * Kuzzle, a backend software, self-hostable and ready to use
3
3
  * to power modern apps
4
4
  *
5
- * Copyright 2015-2020 Kuzzle
5
+ * Copyright 2015-2022 Kuzzle
6
6
  * mailto: support AT kuzzle.io
7
7
  * website: http://kuzzle.io
8
8
  *
@@ -2,7 +2,7 @@
2
2
  * Kuzzle, a backend software, self-hostable and ready to use
3
3
  * to power modern apps
4
4
  *
5
- * Copyright 2015-2020 Kuzzle
5
+ * Copyright 2015-2022 Kuzzle
6
6
  * mailto: support AT kuzzle.io
7
7
  * website: http://kuzzle.io
8
8
  *
@@ -2,7 +2,7 @@
2
2
  * Kuzzle, a backend software, self-hostable and ready to use
3
3
  * to power modern apps
4
4
  *
5
- * Copyright 2015-2020 Kuzzle
5
+ * Copyright 2015-2022 Kuzzle
6
6
  * mailto: support AT kuzzle.io
7
7
  * website: http://kuzzle.io
8
8
  *
@@ -228,8 +228,12 @@ class DocumentController extends NativeController {
228
228
  mimeType = 'text/csv';
229
229
  }
230
230
 
231
- request.response.setHeader('Content-Type', mimeType);
232
- request.response.setHeader('Content-Disposition', `attachment; filename="${index}-${collection}.${format}"`);
231
+ request.response.configure({
232
+ headers: {
233
+ 'Content-Disposition': `attachment; filename="${index}-${collection}.${format}"`,
234
+ 'Content-Type': mimeType,
235
+ }
236
+ });
233
237
 
234
238
  return dumpCollectionDocuments(
235
239
  index,
@@ -829,6 +833,7 @@ class DocumentController extends NativeController {
829
833
  * @returns {Promise.<Object>} { successes, errors }
830
834
  */
831
835
  async _mChanges (request, methodName, action) {
836
+ let source = true;
832
837
  const userId = request.getKuid();
833
838
  const strict = request.getBoolean('strict');
834
839
  const silent = request.getBoolean('silent');
@@ -842,6 +847,10 @@ class DocumentController extends NativeController {
842
847
 
843
848
  this.assertNotExceedMaxWrite(documents.length);
844
849
 
850
+ if (request.input.args.source !== undefined) {
851
+ source = request.input.args.source === 'false' ? false : request.getBoolean('source');
852
+ }
853
+
845
854
  if (documents.length === 0) {
846
855
  return {
847
856
  errors: [],
@@ -865,7 +874,7 @@ class DocumentController extends NativeController {
865
874
  index,
866
875
  collection,
867
876
  documents,
868
- { refresh, retryOnConflict, userId });
877
+ { refresh, retryOnConflict, source, userId });
869
878
 
870
879
  if (strict && response.errors.length) {
871
880
  throw kerror.get('api', 'process', 'incomplete_multiple_request', methodName, response.errors);
@@ -2,7 +2,7 @@
2
2
  * Kuzzle, a backend software, self-hostable and ready to use
3
3
  * to power modern apps
4
4
  *
5
- * Copyright 2015-2020 Kuzzle
5
+ * Copyright 2015-2022 Kuzzle
6
6
  * mailto: support AT kuzzle.io
7
7
  * website: http://kuzzle.io
8
8
  *
@@ -2,7 +2,7 @@
2
2
  * Kuzzle, a backend software, self-hostable and ready to use
3
3
  * to power modern apps
4
4
  *
5
- * Copyright 2015-2020 Kuzzle
5
+ * Copyright 2015-2022 Kuzzle
6
6
  * mailto: support AT kuzzle.io
7
7
  * website: http://kuzzle.io
8
8
  *
@@ -21,8 +21,6 @@
21
21
 
22
22
  'use strict';
23
23
 
24
- const Bluebird = require('bluebird');
25
-
26
24
  const { Request } = require('../request');
27
25
  const { NativeController } = require('./baseController');
28
26
 
@@ -119,7 +117,7 @@ class IndexController extends NativeController {
119
117
  );
120
118
  }
121
119
 
122
- await Bluebird.all(promises);
120
+ await Promise.all(promises);
123
121
  }
124
122
 
125
123
  return response;
@@ -148,12 +146,18 @@ class IndexController extends NativeController {
148
146
  }
149
147
 
150
148
  /**
151
- * Returns a list of indexes allowed to be deleted by the user
149
+ * Returns a list of indexes allowed to be deleted by the user.
150
+ *
151
+ * Returns entire list of public indexes when called from EmbeddedSDK
152
152
  *
153
153
  * @param {Request} request
154
- * @param {String[]} publicIndexes - Complete indexes list
154
+ * @param {String[]} publicIndexes - Public indexes list
155
155
  */
156
156
  _allowedIndexes (request, publicIndexes) {
157
+ if (request.getUser() === null) {
158
+ return publicIndexes;
159
+ }
160
+
157
161
  const allowedIndexes = [];
158
162
 
159
163
  const promises = publicIndexes
@@ -171,7 +175,7 @@ class IndexController extends NativeController {
171
175
  });
172
176
  });
173
177
 
174
- return Bluebird.all(promises)
178
+ return Promise.all(promises)
175
179
  .then(() => allowedIndexes);
176
180
  }
177
181
  }
@@ -2,7 +2,7 @@
2
2
  * Kuzzle, a backend software, self-hostable and ready to use
3
3
  * to power modern apps
4
4
  *
5
- * Copyright 2015-2020 Kuzzle
5
+ * Copyright 2015-2022 Kuzzle
6
6
  * mailto: support AT kuzzle.io
7
7
  * website: http://kuzzle.io
8
8
  *
@@ -2,7 +2,7 @@
2
2
  * Kuzzle, a backend software, self-hostable and ready to use
3
3
  * to power modern apps
4
4
  *
5
- * Copyright 2015-2020 Kuzzle
5
+ * Copyright 2015-2022 Kuzzle
6
6
  * mailto: support AT kuzzle.io
7
7
  * website: http://kuzzle.io
8
8
  *
@@ -2,7 +2,7 @@
2
2
  * Kuzzle, a backend software, self-hostable and ready to use
3
3
  * to power modern apps
4
4
  *
5
- * Copyright 2015-2020 Kuzzle
5
+ * Copyright 2015-2022 Kuzzle
6
6
  * mailto: support AT kuzzle.io
7
7
  * website: http://kuzzle.io
8
8
  *
@@ -31,13 +31,18 @@ const { NativeController } = require('./baseController');
31
31
  const formatProcessing = require('../../core/auth/formatProcessing');
32
32
  const ApiKey = require('../../model/storage/apiKey');
33
33
  const kerror = require('../../kerror');
34
- const { has, get } = require('../../util/safeObject');
34
+ const { has } = require('../../util/safeObject');
35
35
  const { generateRandomName } = require('../../util/name-generator');
36
36
 
37
37
  /**
38
38
  * @class SecurityController
39
39
  */
40
40
  class SecurityController extends NativeController {
41
+
42
+ static userOrSdk (userId) {
43
+ return userId === null ? 'EmbeddedSDK' : `User "${userId}"`;
44
+ }
45
+
41
46
  constructor () {
42
47
  super([
43
48
  'checkRights',
@@ -92,6 +97,7 @@ class SecurityController extends NativeController {
92
97
  'updateRoleMapping',
93
98
  'updateUser',
94
99
  'updateUserMapping',
100
+ 'upsertUser',
95
101
  'validateCredentials'
96
102
  ]);
97
103
 
@@ -149,7 +155,7 @@ class SecurityController extends NativeController {
149
155
  refresh,
150
156
  });
151
157
 
152
- global.kuzzle.log.info(`[SECURITY] User "${creatorId}" applied action "${request.input.action}" on user "${userId}."`);
158
+ global.kuzzle.log.info(`[SECURITY] ${SecurityController.userOrSdk(creatorId)} applied action "${request.input.action}" on user "${userId}."`);
153
159
  return apiKey.serialize({ includeToken: true });
154
160
  }
155
161
 
@@ -371,7 +377,7 @@ class SecurityController extends NativeController {
371
377
  userId,
372
378
  });
373
379
 
374
- global.kuzzle.log.info(`[SECURITY] User "${userId}" applied action "${request.input.action}" on role "${role._id}."`);
380
+ global.kuzzle.log.info(`[SECURITY] ${SecurityController.userOrSdk(userId)} applied action "${request.input.action}" on role "${role._id}."`);
375
381
  return formatProcessing.serializeRole(role);
376
382
  }
377
383
 
@@ -392,7 +398,7 @@ class SecurityController extends NativeController {
392
398
  userId,
393
399
  });
394
400
 
395
- global.kuzzle.log.info(`[SECURITY] User "${userId}" applied action "${request.input.action}" on role "${role._id}."`);
401
+ global.kuzzle.log.info(`[SECURITY] ${SecurityController.userOrSdk(userId)} applied action "${request.input.action}" on role "${role._id}."`);
396
402
  return formatProcessing.serializeRole(role);
397
403
  }
398
404
 
@@ -409,7 +415,7 @@ class SecurityController extends NativeController {
409
415
  refresh: request.getRefresh('wait_for')
410
416
  });
411
417
 
412
- global.kuzzle.log.info(`[SECURITY] User "${request.getKuid()}" applied action "${request.input.action} on role "${id}."`);
418
+ global.kuzzle.log.info(`[SECURITY] ${SecurityController.userOrSdk(request.getKuid())} applied action "${request.input.action} on role "${id}."`);
413
419
 
414
420
  // @todo This avoids a breaking change... but we should really return
415
421
  // an acknowledgment.
@@ -472,7 +478,7 @@ class SecurityController extends NativeController {
472
478
  userId,
473
479
  });
474
480
 
475
- global.kuzzle.log.info(`[SECURITY] User "${userId}" applied action "${request.input.action}" on profile "${profile._id}."`);
481
+ global.kuzzle.log.info(`[SECURITY] ${SecurityController.userOrSdk(userId)} applied action "${request.input.action}" on profile "${profile._id}."`);
476
482
 
477
483
  return formatProcessing.serializeProfile(profile);
478
484
  }
@@ -501,7 +507,7 @@ class SecurityController extends NativeController {
501
507
  userId,
502
508
  });
503
509
 
504
- global.kuzzle.log.info(`[SECURITY] User "${userId}" applied action "${request.input.action}" on profile "${profile._id}."`);
510
+ global.kuzzle.log.info(`[SECURITY] ${SecurityController.userOrSdk(userId)} applied action "${request.input.action}" on profile "${profile._id}."`);
505
511
 
506
512
  return formatProcessing.serializeProfile(profile);
507
513
  }
@@ -522,7 +528,7 @@ class SecurityController extends NativeController {
522
528
 
523
529
  await this.ask('core:security:profile:delete', id, options);
524
530
 
525
- global.kuzzle.log.info(`[SECURITY] User "${userId}" applied action "${request.input.action}" on profile "${id}."`);
531
+ global.kuzzle.log.info(`[SECURITY] ${SecurityController.userOrSdk(userId)} applied action "${request.input.action}" on profile "${id}."`);
526
532
 
527
533
  // @todo - replace by an acknowledgement
528
534
  return { _id: id };
@@ -602,7 +608,8 @@ class SecurityController extends NativeController {
602
608
  ids = request.getBodyArray('ids');
603
609
  }
604
610
  else {
605
- ids = request.getString('ids').split(',');
611
+ // @deprecated Should be replaced with request.getArray('ids')
612
+ ids = request.getArrayLegacy('ids');
606
613
  }
607
614
 
608
615
  const users = await this.ask('core:security:user:mGet', ids);
@@ -757,7 +764,7 @@ class SecurityController extends NativeController {
757
764
 
758
765
  await this.ask('core:security:user:delete', id, options);
759
766
 
760
- global.kuzzle.log.info(`[SECURITY] User "${request.getKuid()}" applied action "${request.input.action}" on user "${id}."`);
767
+ global.kuzzle.log.info(`[SECURITY] ${SecurityController.userOrSdk(request.getKuid())} applied action "${request.input.action}" on user "${id}."`);
761
768
 
762
769
  return { _id: id };
763
770
  }
@@ -770,17 +777,9 @@ class SecurityController extends NativeController {
770
777
  */
771
778
  async createUser (request) {
772
779
  const content = request.getBodyObject('content');
773
- const profileIds = get(content, 'profileIds');
780
+ const profileIds = request.getBodyArray('content.profileIds');
774
781
  const humanReadableId = request.getString('kuid', 'human') !== 'uuid';
775
782
 
776
- if (profileIds === undefined) {
777
- throw kerror.get('api', 'assert', 'missing_argument', 'body.content.profileIds');
778
- }
779
-
780
- if (! Array.isArray(profileIds)) {
781
- throw kerror.get('api', 'assert', 'invalid_type', 'body.content.profileIds', 'array');
782
- }
783
-
784
783
  return this._persistUser(request, profileIds, content, { humanReadableId });
785
784
  }
786
785
 
@@ -819,20 +818,38 @@ class SecurityController extends NativeController {
819
818
  ? null
820
819
  : request.getBodyArray('profileIds');
821
820
 
822
- const updated = await this.ask(
823
- 'core:security:user:update',
824
- id,
825
- profileIds,
826
- content,
827
- {
828
- refresh: request.getRefresh('wait_for'),
829
- retryOnConflict: request.getInteger('retryOnConflict', 10),
830
- userId,
831
- });
821
+ return this._changeUser(request, id, content, userId, profileIds);
822
+ }
832
823
 
833
- global.kuzzle.log.info(`[SECURITY] User "${userId}" applied action "${request.input.action}" on user "${id}."`);
824
+ /**
825
+ * Applies a partial update to an existing user.
826
+ * If the user doesn't already exist, a new user is created.
827
+ *
828
+ * @param {Request} request
829
+ * @returns {Promise}
830
+ */
831
+ async upsertUser (request) {
832
+ const id = request.getId();
833
+ const content = request.getBodyObject('content');
834
+ const userId = request.getKuid();
835
+ const profileIds = request.getBodyArray('content.profileIds');
836
+ const defaultValues = request.getBodyObject('default', {});
834
837
 
835
- return formatProcessing.serializeUser(updated);
838
+ try {
839
+ return await this._changeUser(request, id, content, userId, profileIds);
840
+ }
841
+ catch (error) {
842
+ if (error.id && error.id === 'security.user.not_found') {
843
+ const creatingContent = {
844
+ ...defaultValues,
845
+ ...content, // Order important, content erase default duplicates
846
+ };
847
+
848
+ return this._persistUser(request, profileIds, creatingContent);
849
+ }
850
+
851
+ throw error;
852
+ }
836
853
  }
837
854
 
838
855
  /**
@@ -854,7 +871,7 @@ class SecurityController extends NativeController {
854
871
  content,
855
872
  { refresh: request.getRefresh('wait_for'), userId });
856
873
 
857
- global.kuzzle.log.info(`[SECURITY] User "${userId}" applied action "${request.input.action}" on user "${id}."`);
874
+ global.kuzzle.log.info(`[SECURITY] ${SecurityController.userOrSdk(userId)} applied action "${request.input.action}" on user "${id}."`);
858
875
 
859
876
  return formatProcessing.serializeUser(user);
860
877
  }
@@ -877,7 +894,7 @@ class SecurityController extends NativeController {
877
894
  userId,
878
895
  });
879
896
 
880
- global.kuzzle.log.info(`[SECURITY] User "${userId}" applied action "${request.input.action}" on profile "${id}."`);
897
+ global.kuzzle.log.info(`[SECURITY] ${SecurityController.userOrSdk(userId)} applied action "${request.input.action}" on profile "${id}."`);
881
898
  return formatProcessing.serializeProfile(updated);
882
899
  }
883
900
 
@@ -899,7 +916,7 @@ class SecurityController extends NativeController {
899
916
  userId,
900
917
  });
901
918
 
902
- global.kuzzle.log.info(`[SECURITY] User "${userId}" applied action "${request.input.action}" on role "${id}."`);
919
+ global.kuzzle.log.info(`[SECURITY] ${SecurityController.userOrSdk(userId)} applied action "${request.input.action}" on role "${id}."`);
903
920
 
904
921
  return formatProcessing.serializeRole(updated);
905
922
  }
@@ -940,7 +957,7 @@ class SecurityController extends NativeController {
940
957
  }
941
958
  }
942
959
 
943
- global.kuzzle.log.info(`[SECURITY] User "${userId}" applied action "${request.input.action}".`);
960
+ global.kuzzle.log.info(`[SECURITY] ${SecurityController.userOrSdk(userId)} applied action "${request.input.action}".`);
944
961
 
945
962
  return user;
946
963
  }
@@ -1029,7 +1046,7 @@ class SecurityController extends NativeController {
1029
1046
 
1030
1047
  const createMethod = this.getStrategyMethod(strategy, 'create');
1031
1048
 
1032
- global.kuzzle.log.info(`[SECURITY] User "${request.getKuid()}" applied action "${request.input.action}" on user "${id}."`);
1049
+ global.kuzzle.log.info(`[SECURITY] ${SecurityController.userOrSdk(request.getKuid())} applied action "${request.input.action}" on user "${id}."`);
1033
1050
  return createMethod(request, body, id, strategy);
1034
1051
  }
1035
1052
 
@@ -1053,7 +1070,7 @@ class SecurityController extends NativeController {
1053
1070
 
1054
1071
  const updateMethod = this.getStrategyMethod(strategy, 'update');
1055
1072
 
1056
- global.kuzzle.log.info(`[SECURITY] User "${request.getKuid()}" applied action "${request.input.action}" on user "${id}."`);
1073
+ global.kuzzle.log.info(`[SECURITY] ${SecurityController.userOrSdk(request.getKuid())} applied action "${request.input.action}" on user "${id}."`);
1057
1074
 
1058
1075
  return updateMethod(request, body, id, strategy);
1059
1076
  }
@@ -1106,7 +1123,7 @@ class SecurityController extends NativeController {
1106
1123
 
1107
1124
  await deleteMethod(request, id, strategy);
1108
1125
 
1109
- global.kuzzle.log.info(`[SECURITY] User "${request.getKuid()}" applied action "${request.input.action}" on user "${id}."`);
1126
+ global.kuzzle.log.info(`[SECURITY] ${SecurityController.userOrSdk(request.getKuid())} applied action "${request.input.action}" on user "${id}."`);
1110
1127
 
1111
1128
  return { acknowledged: true };
1112
1129
  }
@@ -1217,15 +1234,36 @@ class SecurityController extends NativeController {
1217
1234
  }
1218
1235
 
1219
1236
  if (successes.length > 1000) {
1220
- global.kuzzle.log.info(`[SECURITY] User "${request.getKuid()}" deleted the following ${type}s: ${successes.slice(0, 1000).join(', ')}... (${successes.length - 1000} more users deleted)."`);
1237
+ global.kuzzle.log.info(`[SECURITY] ${SecurityController.userOrSdk(request.getKuid())} deleted the following ${type}s: ${successes.slice(0, 1000).join(', ')}... (${successes.length - 1000} more users deleted)."`);
1221
1238
  }
1222
1239
  else {
1223
- global.kuzzle.log.info(`[SECURITY] User "${request.getKuid()}" deleted the following ${type}s: ${successes.join(', ')}."`);
1240
+ global.kuzzle.log.info(`[SECURITY] ${SecurityController.userOrSdk(request.getKuid())} deleted the following ${type}s: ${successes.join(', ')}."`);
1224
1241
  }
1225
1242
 
1226
1243
  return successes;
1227
1244
  }
1228
1245
 
1246
+ /**
1247
+ * @returns {Promise}
1248
+ * @private
1249
+ */
1250
+ async _changeUser (request, id, content, userId, profileIds) {
1251
+ const updated = await this.ask(
1252
+ 'core:security:user:update',
1253
+ id,
1254
+ profileIds,
1255
+ content,
1256
+ {
1257
+ refresh: request.getRefresh('wait_for'),
1258
+ retryOnConflict: request.getInteger('retryOnConflict', 10),
1259
+ userId,
1260
+ });
1261
+
1262
+ global.kuzzle.log.info(`[SECURITY] ${SecurityController.userOrSdk(userId)} applied action "${request.input.action}" on user "${id}."`);
1263
+
1264
+ return formatProcessing.serializeUser(updated);
1265
+ }
1266
+
1229
1267
  /**
1230
1268
  * @param {Request} request
1231
1269
  * @returns {Promise}
@@ -1315,7 +1353,7 @@ class SecurityController extends NativeController {
1315
1353
  }
1316
1354
 
1317
1355
  if (creationFailure === null) {
1318
- global.kuzzle.log.info(`[SECURITY] User "${request.getKuid()}" applied action "${request.input.action}" on user "${id}."`);
1356
+ global.kuzzle.log.info(`[SECURITY] ${SecurityController.userOrSdk(request.getKuid())} applied action "${request.input.action}" on user "${id}."`);
1319
1357
  return createdUser;
1320
1358
  }
1321
1359
 
@@ -2,7 +2,7 @@
2
2
  * Kuzzle, a backend software, self-hostable and ready to use
3
3
  * to power modern apps
4
4
  *
5
- * Copyright 2015-2020 Kuzzle
5
+ * Copyright 2015-2022 Kuzzle
6
6
  * mailto: support AT kuzzle.io
7
7
  * website: http://kuzzle.io
8
8
  *
@@ -188,7 +188,8 @@ class ServerController extends NativeController {
188
188
 
189
189
  let services;
190
190
  if (typeof request.input.args.services === 'string') {
191
- services = request.input.args.services.split(',');
191
+ // @deprecated Should be replaced with request.getArray('services')
192
+ services = request.getArrayLegacy('services');
192
193
  }
193
194
  if (! services || services.includes('internalCache')) {
194
195
  try {
@@ -2,7 +2,7 @@
2
2
  * Kuzzle, a backend software, self-hostable and ready to use
3
3
  * to power modern apps
4
4
  *
5
- * Copyright 2015-2020 Kuzzle
5
+ * Copyright 2015-2022 Kuzzle
6
6
  * mailto: support AT kuzzle.io
7
7
  * website: http://kuzzle.io
8
8
  *
@@ -56,7 +56,8 @@ const extractors = ([
56
56
  ids = request.input.args.ids;
57
57
  }
58
58
  else if (typeof request.input.args.ids === 'string') {
59
- ids = request.input.args.ids.split(',');
59
+ // @deprecated Should be replaced with request.getArray('ids')
60
+ ids = request.getArrayLegacy('ids');
60
61
  }
61
62
  else {
62
63
  throw assertionError.get(
package/lib/api/funnel.js CHANGED
@@ -2,7 +2,7 @@
2
2
  * Kuzzle, a backend software, self-hostable and ready to use
3
3
  * to power modern apps
4
4
  *
5
- * Copyright 2015-2020 Kuzzle
5
+ * Copyright 2015-2022 Kuzzle
6
6
  * mailto: support AT kuzzle.io
7
7
  * website: http://kuzzle.io
8
8
  *
@@ -2,7 +2,7 @@
2
2
  * Kuzzle, a backend software, self-hostable and ready to use
3
3
  * to power modern apps
4
4
  *
5
- * Copyright 2015-2020 Kuzzle
5
+ * Copyright 2015-2022 Kuzzle
6
6
  * mailto: support AT kuzzle.io
7
7
  * website: http://kuzzle.io
8
8
  *
@@ -35,8 +35,9 @@ const {
35
35
  OpenApiDocumentCreate,
36
36
  OpenApiDocumentCreateOrReplace,
37
37
  OpenApiDocumentValidate,
38
- } = require('./openapi/components/document');
39
-
38
+ OpenApiSecurityUpsertUser,
39
+ OpenApiDocumentmCreateOrReplace,
40
+ } = require('./openapi/components');
40
41
 
41
42
  const routes = [
42
43
  // GET (idempotent)
@@ -76,7 +77,7 @@ const routes = [
76
77
  { verb: 'get', path: '/:index/:collection/:_id', controller: 'document', action: 'get', openapi: OpenApiDocumentGet },
77
78
  { verb: 'get', path: '/:index/:collection/_mGet', controller: 'document', action: 'mGet' },
78
79
  { verb: 'get', path: '/:index/:collection/:_id/_exists', controller: 'document', action: 'exists', openapi: OpenApiDocumentExists },
79
- { verb: 'get', path: '/:index/:collection/_mExists', controller: 'document', action: 'mExists' },
80
+ { verb: 'post', path: '/:index/:collection/_mExists', controller: 'document', action: 'mExists' },
80
81
  { verb: 'get', path: '/_scroll/:scrollId', controller: 'document', action: 'scroll', openapi: OpenApiDocumentScroll },
81
82
 
82
83
  { verb: 'get', path: '/:index/_exists', controller: 'index', action: 'exists' },
@@ -234,6 +235,7 @@ const routes = [
234
235
  { verb: 'post', path: '/roles/_search', controller: 'security', action: 'searchRoles' },
235
236
  { verb: 'post', path: '/users/_search', controller: 'security', action: 'searchUsers' },
236
237
  { verb: 'post', path: '/credentials/:strategy/users/_search', controller: 'security', action: 'searchUsersByCredentials' },
238
+ { verb: 'post', path: '/users/:_id/_upsert', controller: 'security', action: 'upsertUser', openapi: OpenApiSecurityUpsertUser },
237
239
  { verb: 'post', path: '/credentials/:strategy/:_id/_validate', controller: 'security', action: 'validateCredentials' },
238
240
  { verb: 'post', path: '/_checkRights', controller: 'auth', action: 'checkRights' },
239
241
  { verb: 'post', path: '/_checkRights/:userId', controller: 'security', action: 'checkRights' },
@@ -355,7 +357,7 @@ const routes = [
355
357
  { verb: 'put', path: '/:index/:collection/_specifications', controller: 'collection', action: 'updateSpecifications' },
356
358
 
357
359
  { verb: 'put', path: '/:index/:collection/:_id', controller: 'document', action: 'createOrReplace', openapi: OpenApiDocumentCreateOrReplace },
358
- { verb: 'put', path: '/:index/:collection/_mCreateOrReplace', controller: 'document', action: 'mCreateOrReplace' },
360
+ { verb: 'put', path: '/:index/:collection/_mCreateOrReplace', controller: 'document', action: 'mCreateOrReplace', openapi: OpenApiDocumentmCreateOrReplace },
359
361
  { verb: 'put', path: '/:index/:collection/:_id/_replace', controller: 'document', action: 'replace', openapi: OpenApiDocumentReplace },
360
362
  { verb: 'put', path: '/:index/:collection/_mReplace', controller: 'document', action: 'mReplace' },
361
363
  { verb: 'put', path: '/:index/:collection/_mUpdate', controller: 'document', action: 'mUpdate', deprecated: { since: '2.11.0', message: 'Use "document:mUpdate" route with PATCH instead of PUT' } }, // @deprecated
@@ -3,7 +3,7 @@
3
3
  * Kuzzle, a backend software, self-hostable and ready to use
4
4
  * to power modern apps
5
5
  *
6
- * Copyright 2015-2020 Kuzzle
6
+ * Copyright 2015-2022 Kuzzle
7
7
  * mailto: support AT kuzzle.io
8
8
  * website: http://kuzzle.io
9
9
  *
@@ -79,6 +79,10 @@ class OpenApiManager {
79
79
  ...components_1.OpenApiDocumentCreateOrReplaceComponent,
80
80
  ...components_1.OpenApiDocumentCreateComponent,
81
81
  ...components_1.OpenApiDocumentValidateComponent,
82
+ },
83
+ security: {
84
+ ...components_1.OpenApiSecurityUpsertUserComponent,
85
+ ...components_1.OpenApiDocumentmCreateOrReplaceComponent,
82
86
  }
83
87
  }
84
88
  };
@@ -14,7 +14,7 @@ DocumentGet:
14
14
  type: string
15
15
  required: true
16
16
  - in: path
17
- name: documentId
17
+ name: _id
18
18
  schema:
19
19
  type: string
20
20
  required: true
@@ -20,3 +20,5 @@ export declare const OpenApiDocumentDeleteByQuery: any;
20
20
  export declare const OpenApiDocumentDeleteByQueryComponent: any;
21
21
  export declare const OpenApiDocumentValidate: any;
22
22
  export declare const OpenApiDocumentValidateComponent: any;
23
+ export declare const OpenApiDocumentmCreateOrReplace: any;
24
+ export declare const OpenApiDocumentmCreateOrReplaceComponent: any;