kuzzle 2.16.11 → 2.17.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/api/controllers/adminController.js +3 -3
- package/lib/api/controllers/authController.js +12 -12
- package/lib/api/controllers/baseController.js +60 -3
- package/lib/api/controllers/clusterController.js +1 -1
- package/lib/api/controllers/collectionController.js +7 -5
- package/lib/api/controllers/documentController.js +130 -17
- package/lib/api/controllers/indexController.js +1 -1
- package/lib/api/controllers/memoryStorageController.js +39 -38
- package/lib/api/controllers/realtimeController.js +1 -1
- package/lib/api/controllers/securityController.js +50 -50
- package/lib/api/controllers/serverController.js +73 -27
- package/lib/api/documentExtractor.js +3 -3
- package/lib/api/funnel.js +44 -21
- package/lib/api/httpRoutes.js +9 -4
- package/lib/api/openapi/OpenApiManager.d.ts +11 -0
- package/lib/api/openapi/OpenApiManager.js +96 -0
- package/lib/api/openapi/{document → components/document}/count.yaml +2 -2
- package/lib/api/openapi/{document → components/document}/create.yaml +2 -2
- package/lib/api/openapi/{document → components/document}/createOrReplace.yaml +2 -2
- package/lib/api/openapi/{document → components/document}/delete.yaml +1 -1
- package/lib/api/openapi/{document → components/document}/deleteByQuery.yaml +2 -2
- package/lib/api/openapi/{document → components/document}/exists.yaml +1 -1
- package/lib/api/openapi/{document → components/document}/get.yaml +1 -1
- package/lib/api/openapi/{document → components/document}/index.d.ts +2 -0
- package/lib/api/openapi/{document → components/document}/index.js +7 -2
- package/lib/api/openapi/{document → components/document}/replace.yaml +2 -2
- package/lib/api/openapi/{document → components/document}/scroll.yaml +1 -1
- package/lib/api/openapi/{document → components/document}/update.yaml +2 -2
- package/lib/api/openapi/components/document/validate.yaml +42 -0
- package/lib/api/openapi/components/index.d.ts +2 -0
- package/lib/api/openapi/components/index.js +18 -0
- package/lib/api/openapi/{payloads.yaml → components/payloads.yaml} +0 -0
- package/lib/api/openapi/index.d.ts +1 -2
- package/lib/api/openapi/index.js +1 -5
- package/lib/api/openapi/openApiGenerator.d.ts +7 -0
- package/lib/api/openapi/openApiGenerator.js +133 -0
- package/lib/api/request/kuzzleRequest.js +8 -6
- package/lib/cluster/node.js +9 -9
- package/lib/cluster/publisher.js +1 -1
- package/lib/cluster/state.js +20 -4
- package/lib/cluster/subscriber.js +1 -1
- package/lib/cluster/workers/IDCardRenewer.js +2 -2
- package/lib/config/default.config.js +1 -0
- package/lib/config/index.js +6 -6
- package/lib/core/auth/passportResponse.js +6 -6
- package/lib/core/auth/passportWrapper.js +5 -5
- package/lib/core/backend/backend.d.ts +11 -3
- package/lib/core/backend/backend.js +22 -17
- package/lib/core/backend/backendConfig.d.ts +5 -1
- package/lib/core/backend/backendConfig.js +25 -2
- package/lib/core/backend/backendController.js +21 -5
- package/lib/core/backend/backendErrors.d.ts +58 -0
- package/lib/core/backend/backendErrors.js +121 -0
- package/lib/core/backend/backendHook.js +21 -5
- package/lib/core/backend/backendImport.js +21 -5
- package/lib/core/backend/backendOpenApi.d.ts +9 -0
- package/lib/core/backend/backendOpenApi.js +69 -0
- package/lib/core/backend/backendPipe.js +21 -5
- package/lib/core/backend/backendPlugin.js +22 -3
- package/lib/core/backend/backendVault.js +21 -2
- package/lib/core/backend/index.d.ts +2 -0
- package/lib/core/backend/index.js +2 -0
- package/lib/core/network/accessLogger.js +6 -6
- package/lib/core/network/clientConnection.js +1 -1
- package/lib/core/network/entryPoint.js +5 -5
- package/lib/core/network/httpRouter/index.js +5 -5
- package/lib/core/network/httpRouter/routeHandler.js +3 -3
- package/lib/core/network/httpRouter/routePart.js +5 -5
- package/lib/core/network/protocolManifest.js +1 -1
- package/lib/core/network/protocols/httpMessage.js +2 -2
- package/lib/core/network/protocols/httpwsProtocol.js +228 -50
- package/lib/core/network/protocols/mqttProtocol.js +3 -3
- package/lib/core/network/protocols/protocol.js +3 -3
- package/lib/core/network/router.js +7 -6
- package/lib/core/plugin/plugin.js +38 -64
- package/lib/core/plugin/pluginContext.js +22 -3
- package/lib/core/plugin/pluginManifest.js +3 -3
- package/lib/core/plugin/pluginRepository.js +5 -5
- package/lib/core/plugin/pluginsManager.js +29 -28
- package/lib/core/realtime/channel.js +20 -4
- package/lib/core/realtime/hotelClerk.js +24 -5
- package/lib/core/realtime/notification/server.js +1 -1
- package/lib/core/realtime/notification/user.js +1 -1
- package/lib/core/realtime/notifier.js +5 -5
- package/lib/core/security/index.js +1 -1
- package/lib/core/security/profileRepository.d.ts +176 -0
- package/lib/core/security/profileRepository.js +445 -443
- package/lib/core/security/roleRepository.js +16 -16
- package/lib/core/security/securityLoader.js +2 -2
- package/lib/core/security/tokenRepository.js +11 -11
- package/lib/core/security/userRepository.js +8 -8
- package/lib/core/shared/abstractManifest.js +4 -4
- package/lib/core/shared/repository.js +5 -5
- package/lib/core/shared/sdk/embeddedSdk.js +21 -2
- package/lib/core/shared/sdk/funnelProtocol.js +1 -1
- package/lib/core/shared/sdk/impersonatedSdk.js +1 -1
- package/lib/core/shared/store.js +30 -23
- package/lib/core/statistics/statistics.js +17 -17
- package/lib/core/storage/clientAdapter.js +45 -10
- package/lib/core/storage/indexCache.js +20 -4
- package/lib/core/validation/baseType.js +5 -5
- package/lib/core/validation/types/anything.js +1 -1
- package/lib/core/validation/types/boolean.js +2 -2
- package/lib/core/validation/types/date.js +9 -9
- package/lib/core/validation/types/email.js +5 -5
- package/lib/core/validation/types/enum.js +6 -6
- package/lib/core/validation/types/geoPoint.js +2 -2
- package/lib/core/validation/types/geoShape.js +28 -25
- package/lib/core/validation/types/integer.js +4 -4
- package/lib/core/validation/types/ipAddress.js +7 -6
- package/lib/core/validation/types/numeric.js +4 -4
- package/lib/core/validation/types/object.js +5 -5
- package/lib/core/validation/types/string.js +5 -5
- package/lib/core/validation/types/url.js +7 -6
- package/lib/core/validation/validation.js +95 -84
- package/lib/kerror/codes/1-services.json +12 -0
- package/lib/kerror/codes/2-api.json +12 -0
- package/lib/kerror/codes/3-network.json +12 -0
- package/lib/kerror/codes/4-plugin.json +6 -0
- package/lib/kerror/codes/index.js +11 -11
- package/lib/kerror/errors/multipleErrorsError.d.ts +1 -1
- package/lib/kerror/errors/multipleErrorsError.js +3 -3
- package/lib/kerror/index.d.ts +82 -0
- package/lib/kerror/index.js +176 -143
- package/lib/kuzzle/dumpGenerator.js +3 -3
- package/lib/kuzzle/event/kuzzleEventEmitter.js +4 -4
- package/lib/kuzzle/event/pipeRunner.js +1 -1
- package/lib/kuzzle/event/waterfall.js +6 -6
- package/lib/kuzzle/kuzzle.js +59 -9
- package/lib/kuzzle/log.js +3 -3
- package/lib/kuzzle/vault.js +3 -3
- package/lib/model/security/profile.d.ts +54 -0
- package/lib/model/security/profile.js +192 -232
- package/lib/model/security/rights.js +1 -1
- package/lib/model/security/role.d.ts +40 -0
- package/lib/model/security/role.js +174 -190
- package/lib/model/security/user.d.ts +29 -0
- package/lib/model/security/user.js +103 -52
- package/lib/model/storage/apiKey.js +2 -2
- package/lib/model/storage/baseModel.js +3 -3
- package/lib/service/cache/redis.js +7 -7
- package/lib/service/storage/elasticsearch.js +152 -90
- package/lib/service/storage/esWrapper.js +2 -3
- package/lib/types/ControllerDefinition.d.ts +3 -3
- package/lib/types/ControllerRights.d.ts +22 -0
- package/lib/types/ControllerRights.js +23 -0
- package/lib/types/HttpStream.d.ts +32 -0
- package/lib/types/HttpStream.js +70 -0
- package/lib/types/OpenApiDefinition.d.ts +43 -0
- package/lib/types/{config/StorageService/StorageServiceElasticsearchConfiguration.js → OpenApiDefinition.js} +1 -1
- package/lib/types/Plugin.js +20 -4
- package/lib/types/Policy.d.ts +25 -0
- package/lib/types/{InternalLogger.js → Policy.js} +2 -2
- package/lib/types/PolicyRestrictions.d.ts +21 -0
- package/lib/types/PolicyRestrictions.js +23 -0
- package/lib/types/Target.d.ts +15 -0
- package/lib/types/Target.js +23 -0
- package/lib/types/config/KuzzleConfiguration.d.ts +4 -0
- package/lib/types/config/ServicesConfiguration.d.ts +2 -2
- package/lib/types/config/{StorageService/StorageServiceElasticsearchConfiguration.d.ts → storageEngine/StorageEngineElasticsearchConfiguration.d.ts} +10 -3
- package/lib/types/config/storageEngine/StorageEngineElasticsearchConfiguration.js +3 -0
- package/lib/types/errors/ErrorDefinition.d.ts +27 -0
- package/lib/types/errors/ErrorDefinition.js +3 -0
- package/lib/types/errors/ErrorDomains.d.ts +17 -0
- package/lib/types/errors/ErrorDomains.js +3 -0
- package/lib/types/index.d.ts +9 -1
- package/lib/types/index.js +9 -1
- package/lib/util/array.d.ts +11 -0
- package/lib/util/array.js +57 -0
- package/lib/util/assertType.js +6 -6
- package/lib/util/bufferedPassThrough.d.ts +76 -0
- package/lib/util/bufferedPassThrough.js +161 -0
- package/lib/util/deprecate.js +7 -5
- package/lib/util/didYouMean.js +1 -1
- package/lib/util/dump-collection.d.ts +3 -0
- package/lib/util/dump-collection.js +284 -0
- package/lib/util/extractFields.js +2 -2
- package/lib/util/inflector.d.ts +8 -0
- package/lib/util/inflector.js +16 -0
- package/lib/util/mutex.js +21 -2
- package/lib/util/requestAssertions.js +7 -7
- package/lib/util/wildcard.js +55 -0
- package/package-lock.json +535 -75
- package/package.json +5 -3
- package/lib/api/openApiGenerator.d.ts +0 -7
- package/lib/api/openApiGenerator.js +0 -197
- package/lib/types/InternalLogger.d.ts +0 -25
|
@@ -31,7 +31,7 @@ const { Mutex } = require('../../util/mutex');
|
|
|
31
31
|
* @class AdminController
|
|
32
32
|
*/
|
|
33
33
|
class AdminController extends NativeController {
|
|
34
|
-
constructor() {
|
|
34
|
+
constructor () {
|
|
35
35
|
super([
|
|
36
36
|
'dump',
|
|
37
37
|
'loadFixtures',
|
|
@@ -77,7 +77,7 @@ class AdminController extends NativeController {
|
|
|
77
77
|
async resetSecurity () {
|
|
78
78
|
const mutex = new Mutex('resetSecurity', { timeout: 0 });
|
|
79
79
|
|
|
80
|
-
if (!await mutex.lock()) {
|
|
80
|
+
if (! await mutex.lock()) {
|
|
81
81
|
throw kerror.get('api', 'process', 'action_locked', 'Kuzzle is already reseting roles, profiles and users.');
|
|
82
82
|
}
|
|
83
83
|
|
|
@@ -111,7 +111,7 @@ class AdminController extends NativeController {
|
|
|
111
111
|
async resetDatabase () {
|
|
112
112
|
const mutex = new Mutex('resetDatabase', { timeout: 0 });
|
|
113
113
|
|
|
114
|
-
if (!await mutex.lock()) {
|
|
114
|
+
if (! await mutex.lock()) {
|
|
115
115
|
throw kerror.get('api', 'process', 'action_locked', 'Kuzzle is already reseting all indexes.');
|
|
116
116
|
}
|
|
117
117
|
|
|
@@ -33,7 +33,7 @@ const kerror = require('../../kerror');
|
|
|
33
33
|
const { has } = require('../../util/safeObject');
|
|
34
34
|
const { NativeController } = require('./baseController');
|
|
35
35
|
const formatProcessing = require('../../core/auth/formatProcessing');
|
|
36
|
-
const User = require('../../model/security/user');
|
|
36
|
+
const { User } = require('../../model/security/user');
|
|
37
37
|
const ApiKey = require('../../model/storage/apiKey');
|
|
38
38
|
|
|
39
39
|
/**
|
|
@@ -44,7 +44,7 @@ class AuthController extends NativeController {
|
|
|
44
44
|
* @param {Kuzzle} kuzzle
|
|
45
45
|
* @constructor
|
|
46
46
|
*/
|
|
47
|
-
constructor() {
|
|
47
|
+
constructor () {
|
|
48
48
|
super([
|
|
49
49
|
'checkRights',
|
|
50
50
|
'checkToken',
|
|
@@ -110,7 +110,7 @@ class AuthController extends NativeController {
|
|
|
110
110
|
async createApiKey (request) {
|
|
111
111
|
const expiresIn = request.input.args.expiresIn || -1;
|
|
112
112
|
const refresh = request.getRefresh('wait_for');
|
|
113
|
-
const apiKeyId = request.getId({ ifMissing: '
|
|
113
|
+
const apiKeyId = request.getId({ ifMissing: 'generate' });
|
|
114
114
|
const description = request.getBodyString('description');
|
|
115
115
|
|
|
116
116
|
const user = request.context.user;
|
|
@@ -176,8 +176,8 @@ class AuthController extends NativeController {
|
|
|
176
176
|
* @returns {Promise<object>}
|
|
177
177
|
*/
|
|
178
178
|
async logout (request) {
|
|
179
|
-
if ( !global.kuzzle.config.http.cookieAuthentication
|
|
180
|
-
|| !request.getBoolean('cookieAuth')
|
|
179
|
+
if ( ! global.kuzzle.config.http.cookieAuthentication
|
|
180
|
+
|| ! request.getBoolean('cookieAuth')
|
|
181
181
|
) {
|
|
182
182
|
this.assertIsAuthenticated(request);
|
|
183
183
|
}
|
|
@@ -195,7 +195,7 @@ class AuthController extends NativeController {
|
|
|
195
195
|
await global.kuzzle.ask(
|
|
196
196
|
'core:security:token:deleteByKuid',
|
|
197
197
|
request.getKuid(),
|
|
198
|
-
{keepApiKeys: true});
|
|
198
|
+
{ keepApiKeys: true });
|
|
199
199
|
}
|
|
200
200
|
else if ( request.context.token
|
|
201
201
|
&& request.context.token.type !== 'apiKey'
|
|
@@ -219,18 +219,18 @@ class AuthController extends NativeController {
|
|
|
219
219
|
{
|
|
220
220
|
httpOnly: true,
|
|
221
221
|
path: '/',
|
|
222
|
-
sameSite:'strict',
|
|
222
|
+
sameSite: 'strict',
|
|
223
223
|
}
|
|
224
224
|
)
|
|
225
225
|
}
|
|
226
226
|
});
|
|
227
227
|
}
|
|
228
228
|
|
|
229
|
-
return {acknowledged: true};
|
|
229
|
+
return { acknowledged: true };
|
|
230
230
|
}
|
|
231
231
|
|
|
232
232
|
// Used to send the Token using different ways when in cookieAuth mode. (DRY)
|
|
233
|
-
async _sendToken(token, request) {
|
|
233
|
+
async _sendToken (token, request) {
|
|
234
234
|
// Only if the support of Browser Cookie as Authentication Token is enabled
|
|
235
235
|
// otherwise we should send a normal response because
|
|
236
236
|
// even if the SDK / Browser can handle the cookie,
|
|
@@ -300,7 +300,7 @@ class AuthController extends NativeController {
|
|
|
300
300
|
}
|
|
301
301
|
passportRequest.original = request;
|
|
302
302
|
|
|
303
|
-
if (!has(global.kuzzle.pluginsManager.strategies, strategy)) {
|
|
303
|
+
if (! has(global.kuzzle.pluginsManager.strategies, strategy)) {
|
|
304
304
|
throw kerror.get('security', 'credentials', 'unknown_strategy', strategy);
|
|
305
305
|
}
|
|
306
306
|
|
|
@@ -651,8 +651,8 @@ class AuthController extends NativeController {
|
|
|
651
651
|
}
|
|
652
652
|
}
|
|
653
653
|
|
|
654
|
-
function wrapPluginError(error) {
|
|
655
|
-
if (!(error instanceof KuzzleError)) {
|
|
654
|
+
function wrapPluginError (error) {
|
|
655
|
+
if (! (error instanceof KuzzleError)) {
|
|
656
656
|
throw kerror.getFrom(
|
|
657
657
|
error,
|
|
658
658
|
'plugin',
|
|
@@ -30,11 +30,11 @@ const assertionError = kerror.wrap('api', 'assert');
|
|
|
30
30
|
|
|
31
31
|
// Base class for all controllers
|
|
32
32
|
class BaseController {
|
|
33
|
-
constructor() {
|
|
33
|
+
constructor () {
|
|
34
34
|
this.__actions = new Set();
|
|
35
35
|
}
|
|
36
36
|
|
|
37
|
-
get _actions() {
|
|
37
|
+
get _actions () {
|
|
38
38
|
return this.__actions;
|
|
39
39
|
}
|
|
40
40
|
|
|
@@ -57,7 +57,7 @@ class BaseController {
|
|
|
57
57
|
}
|
|
58
58
|
|
|
59
59
|
class NativeController extends BaseController {
|
|
60
|
-
constructor(actions = []) {
|
|
60
|
+
constructor (actions = []) {
|
|
61
61
|
super();
|
|
62
62
|
|
|
63
63
|
this.ask = global.kuzzle.ask.bind(global.kuzzle);
|
|
@@ -135,6 +135,63 @@ class NativeController extends BaseController {
|
|
|
135
135
|
}
|
|
136
136
|
}
|
|
137
137
|
|
|
138
|
+
/**
|
|
139
|
+
* Throw if some target have:
|
|
140
|
+
* - missing properties
|
|
141
|
+
* - invalid types
|
|
142
|
+
* - unauthorized values
|
|
143
|
+
*
|
|
144
|
+
* @param {Array<{index:string, collections?: string[]}>} targets Array of targets
|
|
145
|
+
* @param {*} options
|
|
146
|
+
*/
|
|
147
|
+
assertTargetsAreValid (targets, { allowEmptyCollections } = {}) {
|
|
148
|
+
for (let i = 0; i < targets.length; i++) {
|
|
149
|
+
const target = targets[i];
|
|
150
|
+
|
|
151
|
+
if (! target.index) {
|
|
152
|
+
throw kerror.get('api', 'assert', 'missing_argument', `targets[${i}].index`);
|
|
153
|
+
}
|
|
154
|
+
if (this._hasMultiTargets(target.index)) {
|
|
155
|
+
throw kerror.get('services', 'storage', 'invalid_target_format', `targets[${i}].index`, target.index);
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
if (! allowEmptyCollections && ! target.collections) {
|
|
159
|
+
throw kerror.get('api', 'assert', 'missing_argument', `targets[${i}].collections`);
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
if (target.collections && ! Array.isArray(target.collections)) {
|
|
163
|
+
throw kerror.get('api', 'assert', 'invalid_type', `targets[${i}].collections`, 'array');
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
if (! allowEmptyCollections && target.collections.length === 0) {
|
|
167
|
+
throw kerror.get('api', 'assert', 'empty_argument', `targets[${i}].collections`);
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
if (allowEmptyCollections
|
|
171
|
+
&& (! target.collections
|
|
172
|
+
|| target.collections.length === 0)
|
|
173
|
+
) {
|
|
174
|
+
continue;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
for (let j = 0; j < target.collections.length; j++) {
|
|
178
|
+
const collection = target.collections[j];
|
|
179
|
+
|
|
180
|
+
if (typeof collection !== 'string') {
|
|
181
|
+
throw kerror.get('api', 'assert', 'invalid_type', `targets[${i}].collections[${j}]`, 'string');
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
if (this._hasMultiTargets(collection)) {
|
|
185
|
+
throw kerror.get('services', 'storage', 'invalid_target_format', `targets[${i}].collections[${j}]`, collection);
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
_hasMultiTargets (str) {
|
|
192
|
+
return [',', '*', '+'].some(chr => str.includes(chr)) || str === '_all';
|
|
193
|
+
}
|
|
194
|
+
|
|
138
195
|
/**
|
|
139
196
|
* Throws if page size exceeed Kuzzle limits
|
|
140
197
|
*
|
|
@@ -29,7 +29,7 @@ const { NativeController } = require('./baseController');
|
|
|
29
29
|
* @class CollectionController
|
|
30
30
|
*/
|
|
31
31
|
class CollectionController extends NativeController {
|
|
32
|
-
constructor() {
|
|
32
|
+
constructor () {
|
|
33
33
|
super([
|
|
34
34
|
'create',
|
|
35
35
|
'delete',
|
|
@@ -128,7 +128,7 @@ class CollectionController extends NativeController {
|
|
|
128
128
|
async searchSpecifications (request) {
|
|
129
129
|
const { from, size, scrollTTL, searchBody } = request.getSearchParams();
|
|
130
130
|
|
|
131
|
-
if (!isPlainObject(searchBody)) {
|
|
131
|
+
if (! isPlainObject(searchBody)) {
|
|
132
132
|
throw kerror.get(
|
|
133
133
|
'api',
|
|
134
134
|
'assert',
|
|
@@ -218,7 +218,7 @@ class CollectionController extends NativeController {
|
|
|
218
218
|
try {
|
|
219
219
|
await global.kuzzle.internalIndex.delete('validations', specificationsId);
|
|
220
220
|
}
|
|
221
|
-
catch(error) {
|
|
221
|
+
catch (error) {
|
|
222
222
|
if (error.status === 404) {
|
|
223
223
|
return {
|
|
224
224
|
acknowledged: true,
|
|
@@ -435,7 +435,8 @@ class CollectionController extends NativeController {
|
|
|
435
435
|
if (from || size) {
|
|
436
436
|
if (from) {
|
|
437
437
|
response.from = Number.parseInt(from);
|
|
438
|
-
}
|
|
438
|
+
}
|
|
439
|
+
else {
|
|
439
440
|
response.from = 0;
|
|
440
441
|
}
|
|
441
442
|
|
|
@@ -446,7 +447,8 @@ class CollectionController extends NativeController {
|
|
|
446
447
|
response.from,
|
|
447
448
|
response.from + response.size
|
|
448
449
|
);
|
|
449
|
-
}
|
|
450
|
+
}
|
|
451
|
+
else {
|
|
450
452
|
response.collections = response.collections.slice(response.from);
|
|
451
453
|
}
|
|
452
454
|
}
|
|
@@ -29,12 +29,12 @@ const {
|
|
|
29
29
|
assertHasIndexAndCollection,
|
|
30
30
|
} = require('../../util/requestAssertions');
|
|
31
31
|
const extractFields = require('../../util/extractFields');
|
|
32
|
-
|
|
32
|
+
const { dumpCollectionDocuments } = require('../../util/dump-collection');
|
|
33
33
|
/**
|
|
34
34
|
* @class DocumentController
|
|
35
35
|
*/
|
|
36
36
|
class DocumentController extends NativeController {
|
|
37
|
-
constructor() {
|
|
37
|
+
constructor () {
|
|
38
38
|
super([
|
|
39
39
|
'count',
|
|
40
40
|
'create',
|
|
@@ -43,10 +43,12 @@ class DocumentController extends NativeController {
|
|
|
43
43
|
'deleteByQuery',
|
|
44
44
|
'deleteFields',
|
|
45
45
|
'exists',
|
|
46
|
+
'export',
|
|
46
47
|
'get',
|
|
47
48
|
'mCreate',
|
|
48
49
|
'mCreateOrReplace',
|
|
49
50
|
'mDelete',
|
|
51
|
+
'mExists',
|
|
50
52
|
'mGet',
|
|
51
53
|
'mReplace',
|
|
52
54
|
'mUpdate',
|
|
@@ -67,15 +69,31 @@ class DocumentController extends NativeController {
|
|
|
67
69
|
*/
|
|
68
70
|
async search (request) {
|
|
69
71
|
const { from, size, scrollTTL, searchBody } = request.getSearchParams();
|
|
70
|
-
const
|
|
72
|
+
const index = request.input.args.index;
|
|
73
|
+
const collection = request.input.args.collection;
|
|
74
|
+
const targets = request.getArray('targets', []);
|
|
71
75
|
const lang = request.getLangParam();
|
|
72
76
|
|
|
73
|
-
if (
|
|
74
|
-
|
|
77
|
+
if ( ! index
|
|
78
|
+
&& ! collection
|
|
79
|
+
&& (! targets || targets.length === 0)
|
|
80
|
+
) {
|
|
81
|
+
throw kerror.get('api', 'assert', 'missing_argument', 'index, collection or targets');
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
if ( index
|
|
85
|
+
&& collection
|
|
86
|
+
&& (hasMultiTargets(index)
|
|
87
|
+
|| hasMultiTargets(collection))
|
|
88
|
+
) {
|
|
89
|
+
throw kerror.get('services', 'storage', 'invalid_multi_index_collection_usage');
|
|
75
90
|
}
|
|
76
91
|
|
|
77
|
-
if (
|
|
78
|
-
|
|
92
|
+
if (targets.length > 0) {
|
|
93
|
+
// Index and Collections from a target should not contains any characters for multi targetting or _all
|
|
94
|
+
// Otherwise it might be possible to bypass some checks and access data that should be accessed
|
|
95
|
+
// We should also verify that each target has an index and collections specified before further processing
|
|
96
|
+
this.assertTargetsAreValid(targets);
|
|
79
97
|
}
|
|
80
98
|
|
|
81
99
|
this.assertNotExceedMaxFetch(size - from);
|
|
@@ -84,13 +102,23 @@ class DocumentController extends NativeController {
|
|
|
84
102
|
searchBody.query = await this.translateKoncorde(searchBody.query || {});
|
|
85
103
|
}
|
|
86
104
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
105
|
+
let result;
|
|
106
|
+
if (targets.length > 0) {
|
|
107
|
+
result = await this.ask(
|
|
108
|
+
'core:storage:public:document:multiSearch',
|
|
109
|
+
targets,
|
|
110
|
+
searchBody,
|
|
111
|
+
{ from, scroll: scrollTTL, size });
|
|
112
|
+
}
|
|
113
|
+
else {
|
|
114
|
+
result = await this.ask(
|
|
115
|
+
'core:storage:public:document:search',
|
|
116
|
+
index,
|
|
117
|
+
collection,
|
|
118
|
+
searchBody,
|
|
119
|
+
{ from, scroll: scrollTTL, size });
|
|
120
|
+
}
|
|
121
|
+
|
|
94
122
|
return {
|
|
95
123
|
aggregations: result.aggregations,
|
|
96
124
|
hits: result.hits,
|
|
@@ -133,6 +161,91 @@ class DocumentController extends NativeController {
|
|
|
133
161
|
return this.ask('core:storage:public:document:exist', index, collection, id);
|
|
134
162
|
}
|
|
135
163
|
|
|
164
|
+
/**
|
|
165
|
+
* @param {Request} request
|
|
166
|
+
*/
|
|
167
|
+
async mExists (request) {
|
|
168
|
+
let ids;
|
|
169
|
+
if ( request.input.body
|
|
170
|
+
&& request.input.body.ids
|
|
171
|
+
&& Object.keys(request.input.body.ids).length
|
|
172
|
+
) {
|
|
173
|
+
ids = request.getBodyArray('ids');
|
|
174
|
+
}
|
|
175
|
+
else {
|
|
176
|
+
ids = request.getArray('ids');
|
|
177
|
+
}
|
|
178
|
+
const { index, collection } = request.getIndexAndCollection();
|
|
179
|
+
|
|
180
|
+
const strict = request.getBoolean('strict');
|
|
181
|
+
this.assertNotExceedMaxFetch(ids.length);
|
|
182
|
+
|
|
183
|
+
const { items, errors } = await this.ask(
|
|
184
|
+
'core:storage:public:document:mExists',
|
|
185
|
+
index, collection,
|
|
186
|
+
ids);
|
|
187
|
+
|
|
188
|
+
if (strict && errors.length) {
|
|
189
|
+
throw kerror.get(
|
|
190
|
+
'api',
|
|
191
|
+
'process',
|
|
192
|
+
'incomplete_multiple_request',
|
|
193
|
+
'get',
|
|
194
|
+
errors);
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
return {
|
|
198
|
+
errors,
|
|
199
|
+
successes: items
|
|
200
|
+
};
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
async export (request) {
|
|
204
|
+
const { index, collection } = request.getIndexAndCollection();
|
|
205
|
+
const { size, scrollTTL, searchBody } = request.getSearchParams();
|
|
206
|
+
const format = request.getString('format', 'jsonl');
|
|
207
|
+
const fields = request.getBodyArray('fields', []);
|
|
208
|
+
const lang = request.getLangParam();
|
|
209
|
+
const separator = request.getString('separator', ',');
|
|
210
|
+
const fieldsName = request.getBodyObject('fieldsName', {});
|
|
211
|
+
|
|
212
|
+
// Remove "fields" and "fieldsName" from searchBody to avoid ES throwing an error
|
|
213
|
+
// since those properties are not allowed in the searchBody
|
|
214
|
+
searchBody.fields = undefined;
|
|
215
|
+
searchBody.fieldsName = undefined;
|
|
216
|
+
|
|
217
|
+
if (request.context.connection.protocol !== 'http') {
|
|
218
|
+
throw kerror.get('api', 'assert', 'unsupported_protocol', request.context.connection.protocol, 'document:export');
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
if (lang === 'koncorde') {
|
|
222
|
+
searchBody.query = await this.translateKoncorde(searchBody.query || {});
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
let mimeType = 'html/text';
|
|
226
|
+
|
|
227
|
+
if (format.toLowerCase() === 'csv') {
|
|
228
|
+
mimeType = 'text/csv';
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
request.response.setHeader('Content-Type', mimeType);
|
|
232
|
+
request.response.setHeader('Content-Disposition', `attachment; filename="${index}-${collection}.${format}"`);
|
|
233
|
+
|
|
234
|
+
return dumpCollectionDocuments(
|
|
235
|
+
index,
|
|
236
|
+
collection,
|
|
237
|
+
searchBody,
|
|
238
|
+
format,
|
|
239
|
+
fields,
|
|
240
|
+
{
|
|
241
|
+
fieldsName,
|
|
242
|
+
lang,
|
|
243
|
+
scroll: scrollTTL || '5s',
|
|
244
|
+
separator,
|
|
245
|
+
size,
|
|
246
|
+
});
|
|
247
|
+
}
|
|
248
|
+
|
|
136
249
|
/**
|
|
137
250
|
* @param {Request} request
|
|
138
251
|
* @returns {Promise<Object>}
|
|
@@ -226,7 +339,7 @@ class DocumentController extends NativeController {
|
|
|
226
339
|
'core:storage:public:document:create',
|
|
227
340
|
index,
|
|
228
341
|
collection,
|
|
229
|
-
|
|
342
|
+
validated.getBody(),
|
|
230
343
|
{ id, refresh, userId });
|
|
231
344
|
|
|
232
345
|
if (! silent) {
|
|
@@ -685,7 +798,7 @@ class DocumentController extends NativeController {
|
|
|
685
798
|
})));
|
|
686
799
|
}
|
|
687
800
|
|
|
688
|
-
if (!source) {
|
|
801
|
+
if (! source) {
|
|
689
802
|
result.successes.forEach(d => (d._source = undefined));
|
|
690
803
|
}
|
|
691
804
|
|
|
@@ -773,7 +886,7 @@ class DocumentController extends NativeController {
|
|
|
773
886
|
request,
|
|
774
887
|
action,
|
|
775
888
|
response.items.map(item => {
|
|
776
|
-
if (!item.created) {
|
|
889
|
+
if (! item.created) {
|
|
777
890
|
item._updatedFields = extractFields(
|
|
778
891
|
documentsDictionnary[item._id],
|
|
779
892
|
{ fieldsToIgnore: ['_kuzzle_info'] });
|