kuzzle 2.19.2 → 2.19.3
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 +94 -80
- package/lib/api/controllers/authController.js +239 -212
- package/lib/api/controllers/baseController.js +89 -51
- package/lib/api/controllers/bulkController.js +62 -49
- package/lib/api/controllers/clusterController.js +6 -8
- package/lib/api/controllers/collectionController.js +140 -129
- package/lib/api/controllers/debugController.d.ts +2 -2
- package/lib/api/controllers/debugController.js +33 -31
- package/lib/api/controllers/documentController.js +365 -274
- package/lib/api/controllers/index.js +13 -13
- package/lib/api/controllers/indexController.js +46 -50
- package/lib/api/controllers/memoryStorageController.js +410 -360
- package/lib/api/controllers/realtimeController.js +37 -36
- package/lib/api/controllers/securityController.js +553 -412
- package/lib/api/controllers/serverController.js +111 -104
- package/lib/api/documentExtractor.js +75 -68
- package/lib/api/funnel.js +411 -312
- package/lib/api/httpRoutes.js +1493 -324
- package/lib/api/openapi/OpenApiManager.d.ts +1 -1
- package/lib/api/openapi/OpenApiManager.js +22 -22
- package/lib/api/openapi/components/document/count.yaml +1 -1
- package/lib/api/openapi/components/document/create.yaml +2 -2
- package/lib/api/openapi/components/document/delete.yaml +1 -1
- package/lib/api/openapi/components/document/deleteByQuery.yaml +1 -1
- package/lib/api/openapi/components/document/exists.yaml +1 -1
- package/lib/api/openapi/components/document/get.yaml +2 -2
- package/lib/api/openapi/components/document/index.js +12 -12
- package/lib/api/openapi/components/document/replace.yaml +1 -1
- package/lib/api/openapi/components/document/scroll.yaml +1 -1
- package/lib/api/openapi/components/document/validate.yaml +1 -1
- package/lib/api/openapi/components/index.d.ts +2 -2
- package/lib/api/openapi/components/index.js +1 -1
- package/lib/api/openapi/components/security/index.js +1 -1
- package/lib/api/openapi/components/security/upsertUser.yaml +2 -3
- package/lib/api/openapi/index.d.ts +1 -1
- package/lib/api/openapi/openApiGenerator.d.ts +1 -1
- package/lib/api/openapi/openApiGenerator.js +7 -7
- package/lib/api/rateLimiter.js +12 -13
- package/lib/api/request/index.d.ts +4 -4
- package/lib/api/request/kuzzleRequest.d.ts +9 -9
- package/lib/api/request/kuzzleRequest.js +89 -87
- package/lib/api/request/requestContext.d.ts +2 -2
- package/lib/api/request/requestContext.js +17 -17
- package/lib/api/request/requestInput.d.ts +1 -1
- package/lib/api/request/requestInput.js +19 -19
- package/lib/api/request/requestResponse.d.ts +4 -4
- package/lib/api/request/requestResponse.js +31 -33
- package/lib/cluster/command.js +48 -44
- package/lib/cluster/idCardHandler.d.ts +1 -1
- package/lib/cluster/idCardHandler.js +15 -15
- package/lib/cluster/index.js +2 -2
- package/lib/cluster/node.js +301 -269
- package/lib/cluster/publisher.js +45 -46
- package/lib/cluster/state.d.ts +5 -5
- package/lib/cluster/state.js +8 -8
- package/lib/cluster/subscriber.js +163 -113
- package/lib/cluster/workers/IDCardRenewer.js +33 -32
- package/lib/config/default.config.d.ts +1 -1
- package/lib/config/default.config.js +212 -171
- package/lib/config/documentEventAliases.js +6 -6
- package/lib/config/index.js +161 -98
- package/lib/config/sdkCompatibility.json +8 -8
- package/lib/core/auth/formatProcessing.js +7 -7
- package/lib/core/auth/passportResponse.js +7 -7
- package/lib/core/auth/passportWrapper.js +34 -30
- package/lib/core/auth/tokenManager.d.ts +2 -2
- package/lib/core/auth/tokenManager.js +11 -10
- package/lib/core/backend/applicationManager.d.ts +1 -1
- package/lib/core/backend/applicationManager.js +2 -2
- package/lib/core/backend/backend.d.ts +3 -3
- package/lib/core/backend/backend.js +34 -31
- package/lib/core/backend/backendCluster.d.ts +2 -2
- package/lib/core/backend/backendCluster.js +5 -5
- package/lib/core/backend/backendConfig.d.ts +2 -2
- package/lib/core/backend/backendConfig.js +3 -3
- package/lib/core/backend/backendController.d.ts +2 -2
- package/lib/core/backend/backendController.js +9 -10
- package/lib/core/backend/backendErrors.d.ts +3 -3
- package/lib/core/backend/backendErrors.js +2 -1
- package/lib/core/backend/backendHook.d.ts +2 -2
- package/lib/core/backend/backendHook.js +5 -5
- package/lib/core/backend/backendImport.d.ts +3 -3
- package/lib/core/backend/backendImport.js +23 -23
- package/lib/core/backend/backendOpenApi.d.ts +2 -2
- package/lib/core/backend/backendOpenApi.js +16 -16
- package/lib/core/backend/backendPipe.d.ts +2 -2
- package/lib/core/backend/backendPipe.js +6 -6
- package/lib/core/backend/backendPlugin.d.ts +4 -4
- package/lib/core/backend/backendPlugin.js +14 -14
- package/lib/core/backend/backendStorage.d.ts +2 -2
- package/lib/core/backend/backendStorage.js +1 -2
- package/lib/core/backend/backendVault.d.ts +2 -2
- package/lib/core/backend/backendVault.js +3 -3
- package/lib/core/backend/index.d.ts +14 -14
- package/lib/core/backend/internalLogger.d.ts +1 -1
- package/lib/core/backend/internalLogger.js +5 -5
- package/lib/core/cache/cacheDbEnum.js +4 -4
- package/lib/core/cache/cacheEngine.js +79 -85
- package/lib/core/network/accessLogger.js +126 -120
- package/lib/core/network/clientConnection.js +5 -5
- package/lib/core/network/context.js +8 -8
- package/lib/core/network/entryPoint.js +100 -85
- package/lib/core/network/httpRouter/index.js +63 -60
- package/lib/core/network/httpRouter/routeHandler.js +18 -19
- package/lib/core/network/httpRouter/routePart.js +23 -19
- package/lib/core/network/protocolManifest.js +3 -3
- package/lib/core/network/protocols/httpMessage.js +8 -10
- package/lib/core/network/protocols/httpwsProtocol.js +305 -250
- package/lib/core/network/protocols/internalProtocol.js +27 -24
- package/lib/core/network/protocols/mqttProtocol.js +106 -96
- package/lib/core/network/protocols/protocol.js +20 -17
- package/lib/core/network/router.js +56 -46
- package/lib/core/plugin/plugin.js +151 -120
- package/lib/core/plugin/pluginContext.d.ts +7 -7
- package/lib/core/plugin/pluginContext.js +48 -44
- package/lib/core/plugin/pluginManifest.js +13 -12
- package/lib/core/plugin/pluginRepository.js +26 -27
- package/lib/core/plugin/pluginsManager.js +425 -304
- package/lib/core/plugin/privilegedContext.js +3 -3
- package/lib/core/realtime/actionEnum.js +1 -1
- package/lib/core/realtime/channel.d.ts +1 -1
- package/lib/core/realtime/channel.js +22 -22
- package/lib/core/realtime/connectionRooms.d.ts +1 -1
- package/lib/core/realtime/hotelClerk.d.ts +2 -2
- package/lib/core/realtime/hotelClerk.js +53 -50
- package/lib/core/realtime/index.js +5 -5
- package/lib/core/realtime/notification/document.js +25 -25
- package/lib/core/realtime/notification/index.js +4 -4
- package/lib/core/realtime/notification/server.js +3 -3
- package/lib/core/realtime/notification/user.js +4 -4
- package/lib/core/realtime/notifier.js +113 -75
- package/lib/core/realtime/room.d.ts +1 -1
- package/lib/core/realtime/subscription.d.ts +1 -1
- package/lib/core/realtime/subscription.js +1 -1
- package/lib/core/security/index.js +8 -8
- package/lib/core/security/profileRepository.d.ts +6 -6
- package/lib/core/security/profileRepository.js +48 -45
- package/lib/core/security/roleRepository.js +127 -115
- package/lib/core/security/securityLoader.js +70 -63
- package/lib/core/security/tokenRepository.js +132 -118
- package/lib/core/security/userRepository.js +104 -88
- package/lib/core/shared/KoncordeWrapper.d.ts +1 -1
- package/lib/core/shared/KoncordeWrapper.js +3 -1
- package/lib/core/shared/abstractManifest.js +22 -23
- package/lib/core/shared/repository.js +69 -67
- package/lib/core/shared/sdk/embeddedSdk.d.ts +2 -2
- package/lib/core/shared/sdk/embeddedSdk.js +36 -32
- package/lib/core/shared/sdk/funnelProtocol.d.ts +1 -1
- package/lib/core/shared/sdk/funnelProtocol.js +11 -11
- package/lib/core/shared/sdk/impersonatedSdk.js +19 -18
- package/lib/core/shared/store.js +127 -32
- package/lib/core/statistics/index.js +2 -2
- package/lib/core/statistics/statistics.js +99 -85
- package/lib/core/storage/clientAdapter.js +219 -136
- package/lib/core/storage/indexCache.js +3 -3
- package/lib/core/storage/storageEngine.js +10 -13
- package/lib/core/storage/storeScopeEnum.js +3 -3
- package/lib/core/validation/baseType.js +12 -10
- package/lib/core/validation/index.js +2 -2
- package/lib/core/validation/types/anything.js +4 -4
- package/lib/core/validation/types/boolean.js +7 -7
- package/lib/core/validation/types/date.js +165 -131
- package/lib/core/validation/types/email.js +18 -21
- package/lib/core/validation/types/enum.js +34 -21
- package/lib/core/validation/types/geoPoint.js +7 -7
- package/lib/core/validation/types/geoShape.js +148 -125
- package/lib/core/validation/types/integer.js +9 -9
- package/lib/core/validation/types/ipAddress.js +17 -19
- package/lib/core/validation/types/numeric.js +36 -29
- package/lib/core/validation/types/object.js +19 -19
- package/lib/core/validation/types/string.js +36 -29
- package/lib/core/validation/types/url.js +17 -19
- package/lib/core/validation/validation.js +422 -378
- package/lib/kerror/codes/1-services.json +7 -1
- package/lib/kerror/codes/4-plugin.json +2 -2
- package/lib/kerror/codes/index.js +85 -63
- package/lib/kerror/errors/badRequestError.d.ts +1 -1
- package/lib/kerror/errors/externalServiceError.d.ts +1 -1
- package/lib/kerror/errors/forbiddenError.d.ts +1 -1
- package/lib/kerror/errors/gatewayTimeoutError.d.ts +1 -1
- package/lib/kerror/errors/index.d.ts +15 -15
- package/lib/kerror/errors/internalError.d.ts +1 -1
- package/lib/kerror/errors/kuzzleError.d.ts +1 -1
- package/lib/kerror/errors/multipleErrorsError.d.ts +1 -1
- package/lib/kerror/errors/multipleErrorsError.js +1 -1
- package/lib/kerror/errors/notFoundError.d.ts +1 -1
- package/lib/kerror/errors/partialError.d.ts +1 -1
- package/lib/kerror/errors/partialError.js +1 -1
- package/lib/kerror/errors/pluginImplementationError.d.ts +1 -1
- package/lib/kerror/errors/pluginImplementationError.js +2 -1
- package/lib/kerror/errors/preconditionError.d.ts +1 -1
- package/lib/kerror/errors/serviceUnavailableError.d.ts +1 -1
- package/lib/kerror/errors/sizeLimitError.d.ts +1 -1
- package/lib/kerror/errors/tooManyRequestsError.d.ts +1 -1
- package/lib/kerror/errors/unauthorizedError.d.ts +1 -1
- package/lib/kerror/index.d.ts +3 -3
- package/lib/kerror/index.js +17 -16
- package/lib/kuzzle/dumpGenerator.js +130 -114
- package/lib/kuzzle/event/kuzzleEventEmitter.js +96 -70
- package/lib/kuzzle/event/pipeRunner.js +25 -24
- package/lib/kuzzle/event/waterfall.js +13 -15
- package/lib/kuzzle/index.js +2 -2
- package/lib/kuzzle/internalIndexHandler.js +80 -59
- package/lib/kuzzle/kuzzle.js +99 -99
- package/lib/kuzzle/kuzzleStateEnum.js +1 -1
- package/lib/kuzzle/log.js +23 -18
- package/lib/kuzzle/vault.js +34 -19
- package/lib/model/security/profile.d.ts +3 -3
- package/lib/model/security/profile.js +38 -37
- package/lib/model/security/rights.js +5 -5
- package/lib/model/security/role.d.ts +3 -3
- package/lib/model/security/role.js +25 -26
- package/lib/model/security/token.d.ts +1 -1
- package/lib/model/security/token.js +4 -4
- package/lib/model/security/user.d.ts +2 -2
- package/lib/model/security/user.js +9 -9
- package/lib/model/storage/apiKey.js +43 -33
- package/lib/model/storage/baseModel.js +49 -45
- package/lib/service/cache/redis.js +60 -55
- package/lib/service/service.js +17 -17
- package/lib/service/storage/elasticsearch.js +839 -755
- package/lib/service/storage/esWrapper.js +103 -86
- package/lib/service/storage/queryTranslator.js +52 -59
- package/lib/types/Controller.d.ts +3 -3
- package/lib/types/ControllerDefinition.d.ts +3 -3
- package/lib/types/DebugModule.d.ts +2 -2
- package/lib/types/DebugModule.js +1 -1
- package/lib/types/Global.d.ts +1 -1
- package/lib/types/HttpStream.d.ts +2 -1
- package/lib/types/HttpStream.js +7 -5
- package/lib/types/Kuzzle.d.ts +1 -1
- package/lib/types/KuzzleDocument.d.ts +1 -1
- package/lib/types/OpenApiDefinition.d.ts +1 -1
- package/lib/types/PasswordPolicy.d.ts +1 -1
- package/lib/types/Plugin.d.ts +6 -6
- package/lib/types/Plugin.js +2 -2
- package/lib/types/Policy.d.ts +1 -1
- package/lib/types/RequestPayload.d.ts +1 -1
- package/lib/types/ResponsePayload.d.ts +1 -1
- package/lib/types/Token.d.ts +1 -1
- package/lib/types/User.d.ts +1 -1
- package/lib/types/config/DumpConfiguration.d.ts +8 -8
- package/lib/types/config/HttpConfiguration.d.ts +1 -1
- package/lib/types/config/KuzzleConfiguration.d.ts +1 -1
- package/lib/types/config/LimitsConfiguration.d.ts +8 -8
- package/lib/types/config/PluginsConfiguration.d.ts +4 -4
- package/lib/types/config/SecurityConfiguration.d.ts +62 -62
- package/lib/types/config/ServerConfiguration.d.ts +55 -55
- package/lib/types/config/ServicesConfiguration.d.ts +2 -2
- package/lib/types/config/internalCache/InternalCacheRedisConfiguration.d.ts +10 -10
- package/lib/types/config/publicCache/PublicCacheRedisConfiguration.d.ts +3 -3
- package/lib/types/config/storageEngine/StorageEngineElasticsearchConfiguration.d.ts +194 -110
- package/lib/types/errors/ErrorDefinition.d.ts +1 -1
- package/lib/types/errors/ErrorDomains.d.ts +1 -1
- package/lib/types/index.d.ts +38 -38
- package/lib/types/realtime/RealtimeScope.d.ts +1 -1
- package/lib/types/realtime/RealtimeUsers.d.ts +1 -1
- package/lib/util/assertType.js +13 -11
- package/lib/util/async.d.ts +1 -0
- package/lib/util/async.js +61 -0
- package/lib/util/asyncStore.js +19 -21
- package/lib/util/bufferedPassThrough.d.ts +2 -2
- package/lib/util/bufferedPassThrough.js +4 -4
- package/lib/util/bytes.js +9 -13
- package/lib/util/crypto.js +1 -1
- package/lib/util/debug.js +5 -5
- package/lib/util/deprecate.js +24 -21
- package/lib/util/didYouMean.js +7 -7
- package/lib/util/dump-collection.d.ts +2 -2
- package/lib/util/dump-collection.js +26 -26
- package/lib/util/esRequest.d.ts +1 -0
- package/lib/util/esRequest.js +62 -0
- package/lib/util/extractFields.js +24 -25
- package/lib/util/inflector.js +5 -5
- package/lib/util/koncordeCompat.d.ts +2 -2
- package/lib/util/koncordeCompat.js +5 -5
- package/lib/util/memoize.js +3 -5
- package/lib/util/mutex.d.ts +19 -1
- package/lib/util/mutex.js +39 -12
- package/lib/util/name-generator.js +1331 -1331
- package/lib/util/promback.js +8 -10
- package/lib/util/readYamlFile.d.ts +1 -1
- package/lib/util/readYamlFile.js +1 -1
- package/lib/util/requestAssertions.js +34 -34
- package/lib/util/safeObject.js +5 -5
- package/lib/util/stackTrace.js +20 -22
- package/lib/util/wildcard.js +15 -15
- package/package.json +6 -6
- package/npm-shrinkwrap.json +0 -19422
|
@@ -19,39 +19,42 @@
|
|
|
19
19
|
* limitations under the License.
|
|
20
20
|
*/
|
|
21
21
|
|
|
22
|
-
|
|
22
|
+
"use strict";
|
|
23
23
|
|
|
24
|
-
const assert = require(
|
|
25
|
-
const path = require(
|
|
26
|
-
const fs = require(
|
|
24
|
+
const assert = require("assert");
|
|
25
|
+
const path = require("path");
|
|
26
|
+
const fs = require("fs");
|
|
27
27
|
|
|
28
|
-
const Bluebird = require(
|
|
29
|
-
const _ = require(
|
|
28
|
+
const Bluebird = require("bluebird");
|
|
29
|
+
const _ = require("lodash");
|
|
30
30
|
|
|
31
|
-
const kerror = require(
|
|
32
|
-
const didYouMean = require(
|
|
33
|
-
const { Inflector } = require(
|
|
34
|
-
const debug = require(
|
|
35
|
-
const { KuzzleError } = require(
|
|
36
|
-
const { has, get, isPlainObject } = require(
|
|
37
|
-
const { BaseController } = require(
|
|
38
|
-
const Plugin = require(
|
|
31
|
+
const kerror = require("../../kerror");
|
|
32
|
+
const didYouMean = require("../../util/didYouMean");
|
|
33
|
+
const { Inflector } = require("../../util/inflector");
|
|
34
|
+
const debug = require("../../util/debug")("kuzzle:plugins");
|
|
35
|
+
const { KuzzleError } = require("../../kerror/errors");
|
|
36
|
+
const { has, get, isPlainObject } = require("../../util/safeObject");
|
|
37
|
+
const { BaseController } = require("../../api/controllers/baseController");
|
|
38
|
+
const Plugin = require("./plugin");
|
|
39
39
|
|
|
40
|
-
const assertionError = kerror.wrap(
|
|
41
|
-
const runtimeError = kerror.wrap(
|
|
42
|
-
const strategyError = kerror.wrap(
|
|
43
|
-
const controllerError = kerror.wrap(
|
|
40
|
+
const assertionError = kerror.wrap("plugin", "assert");
|
|
41
|
+
const runtimeError = kerror.wrap("plugin", "runtime");
|
|
42
|
+
const strategyError = kerror.wrap("plugin", "strategy");
|
|
43
|
+
const controllerError = kerror.wrap("plugin", "controller");
|
|
44
44
|
|
|
45
45
|
// Without those plugins, Kuzzle won't start at all.
|
|
46
|
-
const CORE_PLUGINS = [
|
|
46
|
+
const CORE_PLUGINS = [
|
|
47
|
+
"kuzzle-plugin-logger",
|
|
48
|
+
"kuzzle-plugin-auth-passport-local",
|
|
49
|
+
];
|
|
47
50
|
|
|
48
51
|
/**
|
|
49
52
|
* @class PluginsManager
|
|
50
53
|
* @param {Kuzzle} kuzzle
|
|
51
54
|
*/
|
|
52
55
|
class PluginsManager {
|
|
53
|
-
constructor
|
|
54
|
-
Reflect.defineProperty(this,
|
|
56
|
+
constructor() {
|
|
57
|
+
Reflect.defineProperty(this, "kuzzle", {
|
|
55
58
|
value: global.kuzzle,
|
|
56
59
|
});
|
|
57
60
|
|
|
@@ -64,9 +67,11 @@ class PluginsManager {
|
|
|
64
67
|
this.routes = [];
|
|
65
68
|
|
|
66
69
|
this.pluginsEnabledDir = path.resolve(
|
|
67
|
-
path.join(global.kuzzle.rootPath,
|
|
70
|
+
path.join(global.kuzzle.rootPath, "plugins", "enabled")
|
|
71
|
+
);
|
|
68
72
|
this.pluginsAvailableDir = path.resolve(
|
|
69
|
-
path.join(global.kuzzle.rootPath,
|
|
73
|
+
path.join(global.kuzzle.rootPath, "plugins", "available")
|
|
74
|
+
);
|
|
70
75
|
|
|
71
76
|
/**
|
|
72
77
|
* @example
|
|
@@ -90,26 +95,37 @@ class PluginsManager {
|
|
|
90
95
|
|
|
91
96
|
// @deprecated - Warn about the pipeTimeout configuration being obsolete
|
|
92
97
|
if (this.config.common.pipeTimeout) {
|
|
93
|
-
global.kuzzle.log.warn(
|
|
98
|
+
global.kuzzle.log.warn(
|
|
99
|
+
'The configuration "plugins.common.pipeTimeout" has been deprecated and is now unused. It can be safely removed from configuration files'
|
|
100
|
+
);
|
|
94
101
|
}
|
|
95
102
|
|
|
96
103
|
this.loadedPlugins = [];
|
|
97
104
|
}
|
|
98
105
|
|
|
99
|
-
set application
|
|
100
|
-
assert(
|
|
101
|
-
|
|
106
|
+
set application(plugin) {
|
|
107
|
+
assert(
|
|
108
|
+
this._plugins.size === 0,
|
|
109
|
+
"The application plugin can only be set before every other plugins are loaded"
|
|
110
|
+
);
|
|
111
|
+
assert(
|
|
112
|
+
plugin.application,
|
|
113
|
+
'The application plugin must have the "application" property equals to true'
|
|
114
|
+
);
|
|
102
115
|
|
|
103
116
|
this._plugins.set(plugin.name, plugin);
|
|
104
117
|
}
|
|
105
118
|
|
|
106
|
-
get plugins
|
|
107
|
-
return Array.from(this._plugins.values())
|
|
108
|
-
|
|
119
|
+
get plugins() {
|
|
120
|
+
return Array.from(this._plugins.values()).filter(
|
|
121
|
+
(plugin) => !plugin.application
|
|
122
|
+
);
|
|
109
123
|
}
|
|
110
124
|
|
|
111
|
-
get application
|
|
112
|
-
return Array.from(this._plugins.values()).find(
|
|
125
|
+
get application() {
|
|
126
|
+
return Array.from(this._plugins.values()).find(
|
|
127
|
+
(plugin) => plugin.application
|
|
128
|
+
);
|
|
113
129
|
}
|
|
114
130
|
|
|
115
131
|
/**
|
|
@@ -118,7 +134,7 @@ class PluginsManager {
|
|
|
118
134
|
* @param {string} controller
|
|
119
135
|
* @returns {Boolean}
|
|
120
136
|
*/
|
|
121
|
-
isController
|
|
137
|
+
isController(controller) {
|
|
122
138
|
return this.controllers.has(controller);
|
|
123
139
|
}
|
|
124
140
|
|
|
@@ -129,7 +145,7 @@ class PluginsManager {
|
|
|
129
145
|
* @param {string} action
|
|
130
146
|
* @returns {Boolean}
|
|
131
147
|
*/
|
|
132
|
-
isAction
|
|
148
|
+
isAction(controller, action) {
|
|
133
149
|
return this.getActions(controller).includes(action);
|
|
134
150
|
}
|
|
135
151
|
|
|
@@ -139,7 +155,7 @@ class PluginsManager {
|
|
|
139
155
|
* @param {string} controller
|
|
140
156
|
* @returns {Array}
|
|
141
157
|
*/
|
|
142
|
-
getActions
|
|
158
|
+
getActions(controller) {
|
|
143
159
|
return Array.from(this.controllers.get(controller)._actions);
|
|
144
160
|
}
|
|
145
161
|
|
|
@@ -148,7 +164,7 @@ class PluginsManager {
|
|
|
148
164
|
*
|
|
149
165
|
* @returns {Array}
|
|
150
166
|
*/
|
|
151
|
-
getControllerNames
|
|
167
|
+
getControllerNames() {
|
|
152
168
|
return Array.from(this.controllers.keys());
|
|
153
169
|
}
|
|
154
170
|
|
|
@@ -159,7 +175,7 @@ class PluginsManager {
|
|
|
159
175
|
* @returns {boolean}
|
|
160
176
|
*/
|
|
161
177
|
|
|
162
|
-
exists
|
|
178
|
+
exists(pluginName) {
|
|
163
179
|
return this._plugins.has(pluginName);
|
|
164
180
|
}
|
|
165
181
|
|
|
@@ -168,13 +184,17 @@ class PluginsManager {
|
|
|
168
184
|
*
|
|
169
185
|
* @returns {object}
|
|
170
186
|
*/
|
|
171
|
-
getPluginsDescription
|
|
187
|
+
getPluginsDescription() {
|
|
172
188
|
const pluginsDescription = {};
|
|
173
189
|
|
|
174
190
|
for (const plugin of this.plugins) {
|
|
175
191
|
pluginsDescription[plugin.name] = plugin.info();
|
|
176
192
|
|
|
177
|
-
debug(
|
|
193
|
+
debug(
|
|
194
|
+
"[%s] reading plugin configuration: %a",
|
|
195
|
+
plugin,
|
|
196
|
+
pluginsDescription[plugin.name]
|
|
197
|
+
);
|
|
178
198
|
}
|
|
179
199
|
|
|
180
200
|
return pluginsDescription;
|
|
@@ -187,25 +207,32 @@ class PluginsManager {
|
|
|
187
207
|
*
|
|
188
208
|
* @throws PluginImplementationError - Throws when an error occurs when registering a plugin
|
|
189
209
|
*/
|
|
190
|
-
init
|
|
191
|
-
this._plugins = new Map([
|
|
192
|
-
...this.loadPlugins(plugins),
|
|
193
|
-
...this._plugins]);
|
|
210
|
+
init(plugins = {}) {
|
|
211
|
+
this._plugins = new Map([...this.loadPlugins(plugins), ...this._plugins]);
|
|
194
212
|
|
|
195
|
-
global.kuzzle.on(
|
|
196
|
-
global.kuzzle.log.error(
|
|
213
|
+
global.kuzzle.on("plugin:hook:loop-error", ({ error, pluginName }) => {
|
|
214
|
+
global.kuzzle.log.error(
|
|
215
|
+
`[${pluginName}] Infinite loop detected on event "hook:onError": ${error}`
|
|
216
|
+
);
|
|
197
217
|
});
|
|
198
218
|
|
|
199
|
-
global.kuzzle.on(
|
|
200
|
-
global.kuzzle.log.error(
|
|
219
|
+
global.kuzzle.on("hook:onError", ({ error, event, pluginName }) => {
|
|
220
|
+
global.kuzzle.log.error(
|
|
221
|
+
`[${pluginName}] Error executing hook on "${event}": ${error}${error.stack}`
|
|
222
|
+
);
|
|
201
223
|
});
|
|
202
224
|
|
|
203
225
|
// register regular plugins features
|
|
204
226
|
const loadPlugins = [];
|
|
205
227
|
|
|
206
228
|
for (const plugin of this._plugins.values()) {
|
|
207
|
-
if (
|
|
208
|
-
|
|
229
|
+
if (
|
|
230
|
+
this.config.common.failsafeMode &&
|
|
231
|
+
!CORE_PLUGINS.includes(plugin.name)
|
|
232
|
+
) {
|
|
233
|
+
global.kuzzle.log.info(
|
|
234
|
+
`Failsafe mode activated, skipping plugin "${plugin.name}"`
|
|
235
|
+
);
|
|
209
236
|
continue;
|
|
210
237
|
}
|
|
211
238
|
|
|
@@ -218,53 +245,59 @@ class PluginsManager {
|
|
|
218
245
|
debug(
|
|
219
246
|
'[%s] starting plugin in "%s" mode',
|
|
220
247
|
plugin.name,
|
|
221
|
-
plugin.config.privileged ?
|
|
248
|
+
plugin.config.privileged ? "privileged" : "standard"
|
|
249
|
+
);
|
|
222
250
|
|
|
223
|
-
const promise = Bluebird
|
|
224
|
-
|
|
251
|
+
const promise = Bluebird.resolve(
|
|
252
|
+
(async () => {
|
|
225
253
|
try {
|
|
226
254
|
await plugin.instance.init(plugin.config, plugin.context);
|
|
255
|
+
} catch (error) {
|
|
256
|
+
throw runtimeError.get("failed_init", plugin.name, error);
|
|
227
257
|
}
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
258
|
+
})()
|
|
259
|
+
)
|
|
260
|
+
.timeout(
|
|
261
|
+
initTimeout,
|
|
262
|
+
`${plugin.logPrefix} Initialization timed out after ${initTimeout}ms. Try to increase the configuration "plugins.common.initTimeout".`
|
|
263
|
+
)
|
|
233
264
|
.then(async () => {
|
|
234
265
|
plugin.initCalled = true;
|
|
235
266
|
|
|
236
|
-
if (
|
|
237
|
-
|
|
238
|
-
|
|
267
|
+
if (
|
|
268
|
+
!_.isEmpty(plugin.instance.controllers) &&
|
|
269
|
+
!_.isEmpty(plugin.instance.api)
|
|
270
|
+
) {
|
|
271
|
+
throw assertionError.get("duplicated_api_definition");
|
|
239
272
|
}
|
|
240
273
|
|
|
241
|
-
if (!
|
|
274
|
+
if (!_.isEmpty(plugin.instance.controllers)) {
|
|
242
275
|
this._initControllers(plugin);
|
|
243
276
|
}
|
|
244
277
|
|
|
245
|
-
if (!
|
|
278
|
+
if (!_.isEmpty(plugin.instance.api)) {
|
|
246
279
|
await this._initApi(plugin);
|
|
247
280
|
}
|
|
248
281
|
|
|
249
|
-
if (!
|
|
282
|
+
if (!_.isEmpty(plugin.instance.authenticators)) {
|
|
250
283
|
this._initAuthenticators(plugin);
|
|
251
284
|
}
|
|
252
285
|
|
|
253
|
-
if (!
|
|
286
|
+
if (!_.isEmpty(plugin.instance.strategies)) {
|
|
254
287
|
this._initStrategies(plugin);
|
|
255
288
|
}
|
|
256
289
|
|
|
257
|
-
if (!
|
|
290
|
+
if (!_.isEmpty(plugin.instance.hooks)) {
|
|
258
291
|
this._initHooks(plugin);
|
|
259
292
|
}
|
|
260
293
|
|
|
261
|
-
if (!
|
|
294
|
+
if (!_.isEmpty(plugin.instance.pipes)) {
|
|
262
295
|
this._initPipes(plugin);
|
|
263
296
|
}
|
|
264
297
|
|
|
265
|
-
debug(
|
|
298
|
+
debug("[%s] plugin started", plugin.name);
|
|
266
299
|
|
|
267
|
-
if (!
|
|
300
|
+
if (!plugin.application) {
|
|
268
301
|
this.loadedPlugins.push(plugin.name);
|
|
269
302
|
}
|
|
270
303
|
|
|
@@ -281,7 +314,7 @@ class PluginsManager {
|
|
|
281
314
|
* @param {string} strategyName
|
|
282
315
|
* @returns {string[]}
|
|
283
316
|
*/
|
|
284
|
-
getStrategyFields
|
|
317
|
+
getStrategyFields(strategyName) {
|
|
285
318
|
return this.strategies[strategyName].strategy.config.fields || [];
|
|
286
319
|
}
|
|
287
320
|
|
|
@@ -290,7 +323,7 @@ class PluginsManager {
|
|
|
290
323
|
* @param {string} methodName
|
|
291
324
|
* @returns {boolean}
|
|
292
325
|
*/
|
|
293
|
-
hasStrategyMethod
|
|
326
|
+
hasStrategyMethod(strategyName, methodName) {
|
|
294
327
|
const strategy = get(this.strategies, strategyName);
|
|
295
328
|
return strategy && has(strategy.methods, methodName);
|
|
296
329
|
}
|
|
@@ -300,7 +333,7 @@ class PluginsManager {
|
|
|
300
333
|
* @param {string} methodName
|
|
301
334
|
* @returns {function}
|
|
302
335
|
*/
|
|
303
|
-
getStrategyMethod
|
|
336
|
+
getStrategyMethod(strategyName, methodName) {
|
|
304
337
|
return this.strategies[strategyName].methods[methodName];
|
|
305
338
|
}
|
|
306
339
|
|
|
@@ -308,7 +341,7 @@ class PluginsManager {
|
|
|
308
341
|
* Returns the list of registered passport strategies
|
|
309
342
|
* @returns {string[]}
|
|
310
343
|
*/
|
|
311
|
-
listStrategies
|
|
344
|
+
listStrategies() {
|
|
312
345
|
return Object.keys(this.strategies);
|
|
313
346
|
}
|
|
314
347
|
|
|
@@ -320,88 +353,108 @@ class PluginsManager {
|
|
|
320
353
|
* @param {object} strategy
|
|
321
354
|
* @throws {PluginImplementationError} If the strategy is invalid
|
|
322
355
|
*/
|
|
323
|
-
validateStrategy
|
|
356
|
+
validateStrategy(pluginName, strategyName, strategy) {
|
|
324
357
|
const errorPrefix = `[${pluginName}] Strategy ${strategyName}:`;
|
|
325
358
|
|
|
326
|
-
if (!
|
|
327
|
-
throw strategyError.get(
|
|
359
|
+
if (!isPlainObject(strategy)) {
|
|
360
|
+
throw strategyError.get("invalid_description", errorPrefix, strategy);
|
|
328
361
|
}
|
|
329
362
|
|
|
330
|
-
if (!
|
|
331
|
-
throw strategyError.get(
|
|
363
|
+
if (!isPlainObject(strategy.methods)) {
|
|
364
|
+
throw strategyError.get("invalid_methods", errorPrefix, strategy.methods);
|
|
332
365
|
}
|
|
333
366
|
|
|
334
367
|
const plugin = this._plugins.get(pluginName.toLowerCase());
|
|
335
368
|
|
|
336
369
|
// required methods check
|
|
337
|
-
[
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
370
|
+
["exists", "create", "update", "delete", "validate", "verify"].forEach(
|
|
371
|
+
(methodName) => {
|
|
372
|
+
if (!_.isString(strategy.methods[methodName])) {
|
|
373
|
+
throw strategyError.get(
|
|
374
|
+
"invalid_method_type",
|
|
375
|
+
errorPrefix,
|
|
376
|
+
methodName,
|
|
377
|
+
strategy.methods[methodName]
|
|
378
|
+
);
|
|
379
|
+
}
|
|
345
380
|
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
381
|
+
if (!_.isFunction(plugin.instance[strategy.methods[methodName]])) {
|
|
382
|
+
throw strategyError.get(
|
|
383
|
+
"missing_method_function",
|
|
384
|
+
errorPrefix,
|
|
385
|
+
strategy.methods[methodName]
|
|
386
|
+
);
|
|
387
|
+
}
|
|
351
388
|
}
|
|
352
|
-
|
|
389
|
+
);
|
|
353
390
|
|
|
354
391
|
// optional methods check
|
|
355
|
-
[
|
|
392
|
+
["getInfo", "getById", "afterRegister"].forEach((name) => {
|
|
356
393
|
const optionalMethodName = strategy.methods[name];
|
|
357
394
|
|
|
358
|
-
if (!
|
|
359
|
-
if (!
|
|
395
|
+
if (!_.isNil(optionalMethodName)) {
|
|
396
|
+
if (!_.isString(optionalMethodName)) {
|
|
360
397
|
throw strategyError.get(
|
|
361
|
-
|
|
398
|
+
"invalid_method_type",
|
|
362
399
|
errorPrefix,
|
|
363
400
|
name,
|
|
364
|
-
optionalMethodName
|
|
401
|
+
optionalMethodName
|
|
402
|
+
);
|
|
365
403
|
}
|
|
366
404
|
|
|
367
|
-
if (!
|
|
405
|
+
if (!_.isFunction(plugin.instance[optionalMethodName])) {
|
|
368
406
|
throw strategyError.get(
|
|
369
|
-
|
|
407
|
+
"missing_method_function",
|
|
370
408
|
errorPrefix,
|
|
371
|
-
optionalMethodName
|
|
409
|
+
optionalMethodName
|
|
410
|
+
);
|
|
372
411
|
}
|
|
373
412
|
}
|
|
374
413
|
});
|
|
375
414
|
|
|
376
|
-
if (!
|
|
377
|
-
throw strategyError.get(
|
|
415
|
+
if (!isPlainObject(strategy.config)) {
|
|
416
|
+
throw strategyError.get("invalid_config", errorPrefix, strategy.config);
|
|
378
417
|
}
|
|
379
418
|
|
|
380
|
-
if (typeof strategy.config.authenticator !==
|
|
419
|
+
if (typeof strategy.config.authenticator !== "string") {
|
|
381
420
|
throw strategyError.get(
|
|
382
|
-
|
|
421
|
+
"invalid_authenticator",
|
|
383
422
|
errorPrefix,
|
|
384
|
-
strategy.config.authenticator
|
|
385
|
-
|
|
386
|
-
else if (
|
|
387
|
-
|
|
423
|
+
strategy.config.authenticator
|
|
424
|
+
);
|
|
425
|
+
} else if (
|
|
426
|
+
!this.authenticators[pluginName] ||
|
|
427
|
+
!this.authenticators[pluginName][strategy.config.authenticator]
|
|
388
428
|
) {
|
|
389
429
|
throw strategyError.get(
|
|
390
|
-
|
|
430
|
+
"unknown_authenticator",
|
|
391
431
|
errorPrefix,
|
|
392
|
-
strategy.config.authenticator
|
|
432
|
+
strategy.config.authenticator
|
|
433
|
+
);
|
|
393
434
|
}
|
|
394
435
|
|
|
395
|
-
for (const optionName of [
|
|
436
|
+
for (const optionName of ["strategyOptions", "authenticateOptions"]) {
|
|
396
437
|
const options = strategy.config[optionName];
|
|
397
438
|
|
|
398
|
-
if (!
|
|
399
|
-
throw strategyError.get(
|
|
439
|
+
if (!_.isNil(options) && !isPlainObject(options)) {
|
|
440
|
+
throw strategyError.get(
|
|
441
|
+
"invalid_option",
|
|
442
|
+
errorPrefix,
|
|
443
|
+
optionName,
|
|
444
|
+
options
|
|
445
|
+
);
|
|
400
446
|
}
|
|
401
447
|
}
|
|
402
448
|
|
|
403
|
-
if (
|
|
404
|
-
|
|
449
|
+
if (
|
|
450
|
+
!_.isNil(strategy.config.fields) &&
|
|
451
|
+
!Array.isArray(strategy.config.fields)
|
|
452
|
+
) {
|
|
453
|
+
throw strategyError.get(
|
|
454
|
+
"invalid_fields",
|
|
455
|
+
errorPrefix,
|
|
456
|
+
strategy.config.fields
|
|
457
|
+
);
|
|
405
458
|
}
|
|
406
459
|
}
|
|
407
460
|
|
|
@@ -415,12 +468,13 @@ class PluginsManager {
|
|
|
415
468
|
*
|
|
416
469
|
* @returns {string} pipeId
|
|
417
470
|
*/
|
|
418
|
-
registerPipe
|
|
471
|
+
registerPipe(plugin, event, handler) {
|
|
419
472
|
debug('[%s] registering pipe on event "%s"', plugin.name, event);
|
|
420
473
|
|
|
421
|
-
const warnDelay =
|
|
422
|
-
|
|
423
|
-
|
|
474
|
+
const warnDelay =
|
|
475
|
+
plugin.config.pipeWarnTime !== undefined
|
|
476
|
+
? plugin.config.pipeWarnTime
|
|
477
|
+
: this.config.common.pipeWarnTime;
|
|
424
478
|
|
|
425
479
|
const wrapper = (...data) => {
|
|
426
480
|
const now = warnDelay ? Date.now() : null;
|
|
@@ -431,7 +485,9 @@ class PluginsManager {
|
|
|
431
485
|
const elapsed = Date.now() - now;
|
|
432
486
|
|
|
433
487
|
if (elapsed > warnDelay) {
|
|
434
|
-
global.kuzzle.log.warn(
|
|
488
|
+
global.kuzzle.log.warn(
|
|
489
|
+
`${plugin.logPrefix} pipe for event '${event}' is slow (${elapsed}ms)`
|
|
490
|
+
);
|
|
435
491
|
}
|
|
436
492
|
}
|
|
437
493
|
|
|
@@ -439,34 +495,35 @@ class PluginsManager {
|
|
|
439
495
|
};
|
|
440
496
|
|
|
441
497
|
try {
|
|
442
|
-
const pipeResponse =
|
|
443
|
-
? handler(null, cb)
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
498
|
+
const pipeResponse =
|
|
499
|
+
data.length === 0 ? handler(null, cb) : handler(...data, cb);
|
|
500
|
+
|
|
501
|
+
if (
|
|
502
|
+
typeof pipeResponse === "object" &&
|
|
503
|
+
pipeResponse !== null &&
|
|
504
|
+
typeof pipeResponse.then === "function" &&
|
|
505
|
+
typeof pipeResponse.catch === "function"
|
|
450
506
|
) {
|
|
451
507
|
pipeResponse
|
|
452
|
-
.then(result => {
|
|
508
|
+
.then((result) => {
|
|
453
509
|
cb(null, result);
|
|
454
510
|
return null; // prevents a false-positive bluebird warning
|
|
455
511
|
})
|
|
456
|
-
.catch(error => cb(error));
|
|
512
|
+
.catch((error) => cb(error));
|
|
457
513
|
}
|
|
458
|
-
}
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
514
|
+
} catch (error) {
|
|
515
|
+
cb(
|
|
516
|
+
error instanceof KuzzleError
|
|
517
|
+
? error
|
|
518
|
+
: runtimeError.getFrom(error, "unexpected_error", error.message)
|
|
519
|
+
);
|
|
463
520
|
}
|
|
464
521
|
};
|
|
465
522
|
|
|
466
523
|
return global.kuzzle.registerPluginPipe(event, wrapper);
|
|
467
524
|
}
|
|
468
525
|
|
|
469
|
-
unregisterPipe
|
|
526
|
+
unregisterPipe(pipeId) {
|
|
470
527
|
global.kuzzle.unregisterPluginPipe(pipeId);
|
|
471
528
|
}
|
|
472
529
|
|
|
@@ -481,13 +538,13 @@ class PluginsManager {
|
|
|
481
538
|
* @throws {PluginImplementationError} If the strategy is invalid or if
|
|
482
539
|
* registration fails
|
|
483
540
|
*/
|
|
484
|
-
registerStrategy
|
|
541
|
+
registerStrategy(pluginName, strategyName, strategy) {
|
|
485
542
|
// prior to Kaaf, plugin names can contains upper case
|
|
486
543
|
const plugin = this._plugins.get(pluginName.toLowerCase());
|
|
487
544
|
|
|
488
545
|
// only add the strategy to the strategies object if the init method
|
|
489
546
|
// has not been called
|
|
490
|
-
if (!
|
|
547
|
+
if (!plugin.initCalled) {
|
|
491
548
|
plugin.instance.strategies = plugin.instance.strategies || {};
|
|
492
549
|
plugin.instance.strategies[strategyName] = strategy;
|
|
493
550
|
|
|
@@ -506,56 +563,58 @@ class PluginsManager {
|
|
|
506
563
|
// convert uncaught exception into PluginImplementationError
|
|
507
564
|
// promise rejections
|
|
508
565
|
for (const methodName of Object.keys(strategy.methods).filter(
|
|
509
|
-
name => name !==
|
|
510
|
-
) {
|
|
566
|
+
(name) => name !== "verify"
|
|
567
|
+
)) {
|
|
511
568
|
methods[methodName] = async (...args) => {
|
|
512
569
|
try {
|
|
513
|
-
const boundFunction = plugin.instance[
|
|
514
|
-
.
|
|
570
|
+
const boundFunction = plugin.instance[
|
|
571
|
+
strategy.methods[methodName]
|
|
572
|
+
].bind(plugin.instance);
|
|
515
573
|
|
|
516
574
|
return await boundFunction(...args);
|
|
517
|
-
}
|
|
518
|
-
catch (error) {
|
|
575
|
+
} catch (error) {
|
|
519
576
|
if (error instanceof KuzzleError) {
|
|
520
577
|
throw error;
|
|
521
578
|
}
|
|
522
579
|
|
|
523
|
-
throw runtimeError.getFrom(error,
|
|
580
|
+
throw runtimeError.getFrom(error, "unexpected_error", error.message);
|
|
524
581
|
}
|
|
525
582
|
};
|
|
526
583
|
}
|
|
527
584
|
|
|
528
585
|
const opts = {
|
|
529
586
|
...strategy.config.strategyOptions,
|
|
530
|
-
passReqToCallback: true
|
|
587
|
+
passReqToCallback: true,
|
|
531
588
|
};
|
|
532
589
|
|
|
533
590
|
const verifyAdapter = this.wrapStrategyVerify(
|
|
534
591
|
plugin.logPrefix,
|
|
535
592
|
strategyName,
|
|
536
|
-
plugin.instance[strategy.methods.verify].bind(plugin.instance)
|
|
593
|
+
plugin.instance[strategy.methods.verify].bind(plugin.instance)
|
|
594
|
+
);
|
|
537
595
|
|
|
538
596
|
try {
|
|
539
|
-
const
|
|
540
|
-
|
|
597
|
+
const Ctor =
|
|
598
|
+
this.authenticators[plugin.name][strategy.config.authenticator],
|
|
541
599
|
instance = new Ctor(opts, verifyAdapter);
|
|
542
600
|
|
|
543
601
|
this.strategies[strategyName] = { methods, owner: plugin.name, strategy };
|
|
544
602
|
global.kuzzle.passport.use(
|
|
545
603
|
strategyName,
|
|
546
604
|
instance,
|
|
547
|
-
strategy.config.authenticateOptions
|
|
605
|
+
strategy.config.authenticateOptions
|
|
606
|
+
);
|
|
548
607
|
|
|
549
608
|
if (methods.afterRegister) {
|
|
550
609
|
methods.afterRegister(instance);
|
|
551
610
|
}
|
|
552
|
-
}
|
|
553
|
-
catch (e) {
|
|
611
|
+
} catch (e) {
|
|
554
612
|
throw strategyError.getFrom(
|
|
555
613
|
e,
|
|
556
|
-
|
|
614
|
+
"failed_registration",
|
|
557
615
|
strategyName,
|
|
558
|
-
e.message
|
|
616
|
+
e.message
|
|
617
|
+
);
|
|
559
618
|
}
|
|
560
619
|
}
|
|
561
620
|
|
|
@@ -566,19 +625,18 @@ class PluginsManager {
|
|
|
566
625
|
* @throws {PluginImplementationError} If not the owner of the strategy or if strategy
|
|
567
626
|
* does not exist
|
|
568
627
|
*/
|
|
569
|
-
unregisterStrategy
|
|
628
|
+
unregisterStrategy(pluginName, strategyName) {
|
|
570
629
|
const strategy = this.strategies[strategyName];
|
|
571
630
|
|
|
572
631
|
if (strategy) {
|
|
573
632
|
if (strategy.owner !== pluginName) {
|
|
574
|
-
throw strategyError.get(
|
|
633
|
+
throw strategyError.get("unauthorized_removal", strategyName);
|
|
575
634
|
}
|
|
576
635
|
|
|
577
636
|
delete this.strategies[strategyName];
|
|
578
637
|
global.kuzzle.passport.unuse(strategyName);
|
|
579
|
-
}
|
|
580
|
-
|
|
581
|
-
throw strategyError.get('strategy_not_found', strategyName);
|
|
638
|
+
} else {
|
|
639
|
+
throw strategyError.get("strategy_not_found", strategyName);
|
|
582
640
|
}
|
|
583
641
|
}
|
|
584
642
|
|
|
@@ -586,35 +644,37 @@ class PluginsManager {
|
|
|
586
644
|
* @param {object} plugin
|
|
587
645
|
* @param {number} pipeWarnTime
|
|
588
646
|
*/
|
|
589
|
-
_initPipes
|
|
647
|
+
_initPipes(plugin) {
|
|
590
648
|
const methodsList = getMethods(plugin.instance);
|
|
591
649
|
|
|
592
650
|
for (const [event, fn] of Object.entries(plugin.instance.pipes)) {
|
|
593
651
|
const list = Array.isArray(fn) ? fn : [fn];
|
|
594
652
|
|
|
595
653
|
for (const target of list) {
|
|
596
|
-
if (
|
|
597
|
-
|
|
654
|
+
if (
|
|
655
|
+
typeof target !== "function" &&
|
|
656
|
+
typeof plugin.instance[target] !== "function"
|
|
598
657
|
) {
|
|
599
|
-
const message =
|
|
600
|
-
? didYouMean(target, methodsList)
|
|
601
|
-
: '';
|
|
658
|
+
const message =
|
|
659
|
+
typeof target === "string" ? didYouMean(target, methodsList) : "";
|
|
602
660
|
|
|
603
|
-
throw assertionError.get(
|
|
661
|
+
throw assertionError.get("invalid_pipe", event, target, message);
|
|
604
662
|
}
|
|
605
663
|
|
|
606
664
|
let handler = target;
|
|
607
665
|
|
|
608
|
-
if (typeof target ===
|
|
666
|
+
if (typeof target === "string") {
|
|
609
667
|
// @deprecated - warn about using a string representing an instance method
|
|
610
|
-
plugin.printDeprecation(
|
|
668
|
+
plugin.printDeprecation(
|
|
669
|
+
"Defining pipe handler using a string is deprecated. Pass a function instead."
|
|
670
|
+
);
|
|
611
671
|
|
|
612
672
|
handler = plugin.instance[target].bind(plugin.instance);
|
|
613
673
|
}
|
|
614
674
|
|
|
615
675
|
// if the function handler is a plugin instance method,
|
|
616
676
|
// bound the context to the plugin instance
|
|
617
|
-
if (target.name && typeof plugin.instance[target.name] ===
|
|
677
|
+
if (target.name && typeof plugin.instance[target.name] === "function") {
|
|
618
678
|
handler = target.bind(plugin.instance);
|
|
619
679
|
}
|
|
620
680
|
|
|
@@ -626,21 +686,21 @@ class PluginsManager {
|
|
|
626
686
|
/**
|
|
627
687
|
* @param {object} plugin
|
|
628
688
|
*/
|
|
629
|
-
_initHooks
|
|
689
|
+
_initHooks(plugin) {
|
|
630
690
|
const methodsList = getMethods(plugin.instance);
|
|
631
691
|
|
|
632
692
|
for (const [event, fn] of Object.entries(plugin.instance.hooks)) {
|
|
633
693
|
const list = Array.isArray(fn) ? fn : [fn];
|
|
634
694
|
|
|
635
695
|
for (const target of list) {
|
|
636
|
-
if (
|
|
637
|
-
|
|
696
|
+
if (
|
|
697
|
+
typeof target !== "function" &&
|
|
698
|
+
typeof plugin.instance[target] !== "function"
|
|
638
699
|
) {
|
|
639
|
-
const message =
|
|
640
|
-
? didYouMean(target, methodsList)
|
|
641
|
-
: '';
|
|
700
|
+
const message =
|
|
701
|
+
typeof target === "string" ? didYouMean(target, methodsList) : "";
|
|
642
702
|
|
|
643
|
-
throw assertionError.get(
|
|
703
|
+
throw assertionError.get("invalid_hook", event, target, message);
|
|
644
704
|
}
|
|
645
705
|
|
|
646
706
|
debug('[%s] register hook on event "%s"', plugin.name, event);
|
|
@@ -648,15 +708,17 @@ class PluginsManager {
|
|
|
648
708
|
let handler = target;
|
|
649
709
|
|
|
650
710
|
// @deprecated - warn about using a string representing an instance method
|
|
651
|
-
if (typeof target ===
|
|
652
|
-
plugin.printDeprecation(
|
|
711
|
+
if (typeof target === "string") {
|
|
712
|
+
plugin.printDeprecation(
|
|
713
|
+
"Defining hook handler using a string is deprecated. Pass a function instead."
|
|
714
|
+
);
|
|
653
715
|
|
|
654
716
|
handler = plugin.instance[target].bind(plugin.instance);
|
|
655
717
|
}
|
|
656
718
|
|
|
657
719
|
// if the function handler is a plugin instance method,
|
|
658
720
|
// bound the context to the plugin instance
|
|
659
|
-
if (target.name && typeof plugin.instance[target.name] ===
|
|
721
|
+
if (target.name && typeof plugin.instance[target.name] === "function") {
|
|
660
722
|
handler = target.bind(plugin.instance);
|
|
661
723
|
}
|
|
662
724
|
|
|
@@ -665,26 +727,37 @@ class PluginsManager {
|
|
|
665
727
|
}
|
|
666
728
|
}
|
|
667
729
|
|
|
668
|
-
async _initApi
|
|
669
|
-
for (const [controller, definition] of Object.entries(
|
|
730
|
+
async _initApi(plugin) {
|
|
731
|
+
for (const [controller, definition] of Object.entries(
|
|
732
|
+
plugin.instance.api
|
|
733
|
+
)) {
|
|
670
734
|
debug(
|
|
671
|
-
|
|
735
|
+
"[%s][%s] starting api controller registration",
|
|
672
736
|
plugin.name,
|
|
673
|
-
controller
|
|
674
|
-
|
|
675
|
-
|
|
737
|
+
controller
|
|
738
|
+
);
|
|
739
|
+
|
|
740
|
+
if (
|
|
741
|
+
await global.kuzzle.ask(
|
|
742
|
+
"kuzzle:api:funnel:controller:isNative",
|
|
743
|
+
controller
|
|
744
|
+
)
|
|
745
|
+
) {
|
|
676
746
|
throw assertionError.get(
|
|
677
|
-
|
|
747
|
+
"invalid_controller_definition",
|
|
678
748
|
controller,
|
|
679
|
-
|
|
749
|
+
"Native controllers cannot be overriden"
|
|
750
|
+
);
|
|
680
751
|
}
|
|
681
752
|
|
|
682
753
|
Plugin.checkControllerDefinition(controller, definition);
|
|
683
754
|
|
|
684
|
-
for (const [action, actionDefinition
|
|
755
|
+
for (const [action, actionDefinition] of Object.entries(
|
|
756
|
+
definition.actions
|
|
757
|
+
)) {
|
|
685
758
|
let apiController = this.controllers.get(controller);
|
|
686
759
|
|
|
687
|
-
if (!
|
|
760
|
+
if (!apiController) {
|
|
688
761
|
apiController = new BaseController();
|
|
689
762
|
this.controllers.set(controller, apiController);
|
|
690
763
|
}
|
|
@@ -693,7 +766,10 @@ class PluginsManager {
|
|
|
693
766
|
|
|
694
767
|
// if the function handler is a plugin instance method,
|
|
695
768
|
// bind the context to the plugin instance
|
|
696
|
-
if (
|
|
769
|
+
if (
|
|
770
|
+
handler.name &&
|
|
771
|
+
typeof plugin.instance[handler.name] === "function"
|
|
772
|
+
) {
|
|
697
773
|
handler = handler.bind(plugin.instance);
|
|
698
774
|
}
|
|
699
775
|
|
|
@@ -703,12 +779,12 @@ class PluginsManager {
|
|
|
703
779
|
|
|
704
780
|
// Define default HTTP route if none have been provided
|
|
705
781
|
if (httpRoutes.length === 0) {
|
|
706
|
-
httpRoutes.push(
|
|
707
|
-
{
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
);
|
|
782
|
+
httpRoutes.push({
|
|
783
|
+
path: `${Inflector.kebabCase(controller)}/${Inflector.kebabCase(
|
|
784
|
+
action
|
|
785
|
+
)}`,
|
|
786
|
+
verb: "get",
|
|
787
|
+
});
|
|
712
788
|
}
|
|
713
789
|
|
|
714
790
|
for (const httpRoute of httpRoutes) {
|
|
@@ -716,18 +792,20 @@ class PluginsManager {
|
|
|
716
792
|
'[%s] binding HTTP route "%s" to controller "%s"',
|
|
717
793
|
plugin.name,
|
|
718
794
|
httpRoute.path,
|
|
719
|
-
controller
|
|
795
|
+
controller
|
|
796
|
+
);
|
|
720
797
|
|
|
721
|
-
const routePath =
|
|
722
|
-
|
|
723
|
-
|
|
798
|
+
const routePath =
|
|
799
|
+
httpRoute.path.charAt(0) === "/"
|
|
800
|
+
? httpRoute.path
|
|
801
|
+
: `/_/${httpRoute.path}`;
|
|
724
802
|
|
|
725
803
|
this.routes.push({
|
|
726
804
|
action,
|
|
727
805
|
controller,
|
|
728
806
|
openapi: httpRoute.openapi,
|
|
729
807
|
path: routePath,
|
|
730
|
-
verb: httpRoute.verb
|
|
808
|
+
verb: httpRoute.verb,
|
|
731
809
|
});
|
|
732
810
|
}
|
|
733
811
|
}
|
|
@@ -740,130 +818,161 @@ class PluginsManager {
|
|
|
740
818
|
* @param {object} plugin
|
|
741
819
|
* @returns {boolean}
|
|
742
820
|
*/
|
|
743
|
-
_initControllers
|
|
821
|
+
_initControllers(plugin) {
|
|
744
822
|
// @deprecated - warn about using the obsolete "controllers" object
|
|
745
|
-
if (!
|
|
746
|
-
plugin.printDeprecation(
|
|
823
|
+
if (!_.isEmpty(plugin.instance.controllers)) {
|
|
824
|
+
plugin.printDeprecation(
|
|
825
|
+
'Defining controllers using the "controllers" object is deprecated. You should use the "api" object instead.'
|
|
826
|
+
);
|
|
747
827
|
}
|
|
748
828
|
|
|
749
829
|
for (const controller of Object.keys(plugin.instance.controllers)) {
|
|
750
830
|
debug(
|
|
751
|
-
|
|
831
|
+
"[%s][%s] starting controller registration",
|
|
752
832
|
plugin.name,
|
|
753
|
-
controller
|
|
833
|
+
controller
|
|
834
|
+
);
|
|
754
835
|
|
|
755
836
|
const methodsList = getMethods(plugin.instance);
|
|
756
837
|
const controllerName = `${plugin.name}/${controller}`;
|
|
757
838
|
const definition = plugin.instance.controllers[controller];
|
|
758
839
|
const errorControllerPrefix = `Unable to inject controller "${controller}" from plugin "${plugin.name}":`;
|
|
759
840
|
|
|
760
|
-
if (!
|
|
841
|
+
if (!isPlainObject(definition)) {
|
|
761
842
|
// @todo deprecate all those errors and use plugin.assert.invalid_controller_definition
|
|
762
843
|
throw controllerError.get(
|
|
763
|
-
|
|
844
|
+
"invalid_description",
|
|
764
845
|
errorControllerPrefix,
|
|
765
|
-
typeof definition
|
|
846
|
+
typeof definition
|
|
847
|
+
);
|
|
766
848
|
}
|
|
767
849
|
|
|
768
850
|
for (const action of Object.keys(definition)) {
|
|
769
851
|
debug(
|
|
770
|
-
|
|
852
|
+
"[%s][%s][%s] starting action controller registration",
|
|
771
853
|
plugin.name,
|
|
772
854
|
controller,
|
|
773
|
-
action
|
|
855
|
+
action
|
|
856
|
+
);
|
|
774
857
|
|
|
775
|
-
if (
|
|
776
|
-
|
|
858
|
+
if (
|
|
859
|
+
typeof definition[action] !== "function" &&
|
|
860
|
+
typeof plugin.instance[definition[action]] !== "function"
|
|
777
861
|
) {
|
|
778
|
-
const suggestion =
|
|
779
|
-
|
|
780
|
-
|
|
862
|
+
const suggestion =
|
|
863
|
+
typeof definition[action] === "string"
|
|
864
|
+
? didYouMean(definition[action], methodsList)
|
|
865
|
+
: "";
|
|
781
866
|
|
|
782
867
|
throw controllerError.get(
|
|
783
|
-
|
|
868
|
+
"invalid_action",
|
|
784
869
|
errorControllerPrefix,
|
|
785
870
|
controller,
|
|
786
871
|
action,
|
|
787
|
-
suggestion
|
|
872
|
+
suggestion
|
|
873
|
+
);
|
|
788
874
|
}
|
|
789
875
|
|
|
790
876
|
let apiController = this.controllers.get(controllerName);
|
|
791
877
|
|
|
792
|
-
if (!
|
|
878
|
+
if (!apiController) {
|
|
793
879
|
apiController = new BaseController();
|
|
794
880
|
this.controllers.set(controllerName, apiController);
|
|
795
881
|
}
|
|
796
882
|
|
|
797
|
-
if (typeof definition[action] ===
|
|
883
|
+
if (typeof definition[action] === "function") {
|
|
798
884
|
apiController._addAction(action, definition[action]);
|
|
799
|
-
}
|
|
800
|
-
else {
|
|
885
|
+
} else {
|
|
801
886
|
apiController._addAction(
|
|
802
887
|
action,
|
|
803
|
-
plugin.instance[definition[action]].bind(plugin.instance)
|
|
888
|
+
plugin.instance[definition[action]].bind(plugin.instance)
|
|
889
|
+
);
|
|
804
890
|
}
|
|
805
891
|
}
|
|
806
892
|
}
|
|
807
893
|
|
|
808
|
-
const httpVerbs = [
|
|
809
|
-
|
|
894
|
+
const httpVerbs = [
|
|
895
|
+
"get",
|
|
896
|
+
"head",
|
|
897
|
+
"post",
|
|
898
|
+
"put",
|
|
899
|
+
"delete",
|
|
900
|
+
"patch",
|
|
901
|
+
"options",
|
|
902
|
+
];
|
|
903
|
+
const routeProperties = ["verb", "url", "controller", "action", "path"];
|
|
810
904
|
const controllerNames = Object.keys(plugin.instance.controllers);
|
|
811
905
|
|
|
812
906
|
// @deprecated - warn about using the obsolete "routes" object
|
|
813
|
-
if (!
|
|
814
|
-
plugin.printDeprecation(
|
|
907
|
+
if (!_.isEmpty(plugin.instance.routes)) {
|
|
908
|
+
plugin.printDeprecation(
|
|
909
|
+
'Defining routes using the "routes" object is deprecated. You should use the "api" object instead.'
|
|
910
|
+
);
|
|
815
911
|
}
|
|
816
912
|
|
|
817
|
-
for (const route of
|
|
913
|
+
for (const route of plugin.instance.routes || []) {
|
|
818
914
|
const controller = `${plugin.name}/${route.controller}`;
|
|
819
|
-
const errorRoutePrefix = `Unable to inject API route "${JSON.stringify(
|
|
915
|
+
const errorRoutePrefix = `Unable to inject API route "${JSON.stringify(
|
|
916
|
+
route
|
|
917
|
+
)}" from plugin "${plugin.name}":`;
|
|
820
918
|
|
|
821
919
|
for (const key of Object.keys(route)) {
|
|
822
920
|
if (routeProperties.indexOf(key) === -1) {
|
|
823
921
|
throw controllerError.get(
|
|
824
|
-
|
|
922
|
+
"unexpected_route_property",
|
|
825
923
|
errorRoutePrefix,
|
|
826
924
|
key,
|
|
827
|
-
didYouMean(key, routeProperties)
|
|
925
|
+
didYouMean(key, routeProperties)
|
|
926
|
+
);
|
|
828
927
|
}
|
|
829
928
|
|
|
830
|
-
if (
|
|
831
|
-
|
|
929
|
+
if (
|
|
930
|
+
typeof route[key] !== "string" ||
|
|
931
|
+
(route[key].length === 0 && key !== "url")
|
|
832
932
|
) {
|
|
833
|
-
throw controllerError.get(
|
|
933
|
+
throw controllerError.get(
|
|
934
|
+
"invalid_route_property",
|
|
935
|
+
errorRoutePrefix,
|
|
936
|
+
key
|
|
937
|
+
);
|
|
834
938
|
}
|
|
835
939
|
}
|
|
836
940
|
|
|
837
941
|
const apiController = this.controllers.get(controller);
|
|
838
942
|
|
|
839
|
-
if (!
|
|
943
|
+
if (!apiController) {
|
|
840
944
|
throw controllerError.get(
|
|
841
|
-
|
|
945
|
+
"undefined_controller",
|
|
842
946
|
errorRoutePrefix,
|
|
843
947
|
route.controller,
|
|
844
|
-
didYouMean(route.controller, controllerNames)
|
|
948
|
+
didYouMean(route.controller, controllerNames)
|
|
949
|
+
);
|
|
845
950
|
}
|
|
846
951
|
|
|
847
|
-
if (!
|
|
952
|
+
if (!apiController._isAction(route.action)) {
|
|
848
953
|
const actionNames = Array.from(apiController._actions);
|
|
849
954
|
throw controllerError.get(
|
|
850
|
-
|
|
955
|
+
"undefined_action",
|
|
851
956
|
errorRoutePrefix,
|
|
852
957
|
route.action,
|
|
853
|
-
didYouMean(route.action, actionNames)
|
|
958
|
+
didYouMean(route.action, actionNames)
|
|
959
|
+
);
|
|
854
960
|
}
|
|
855
961
|
|
|
856
962
|
if (httpVerbs.indexOf(route.verb.toLowerCase()) === -1) {
|
|
857
963
|
throw controllerError.get(
|
|
858
|
-
|
|
964
|
+
"unsupported_verb",
|
|
859
965
|
errorRoutePrefix,
|
|
860
|
-
httpVerbs.join(
|
|
861
|
-
didYouMean(route.verb, httpVerbs)
|
|
966
|
+
httpVerbs.join(", "),
|
|
967
|
+
didYouMean(route.verb, httpVerbs)
|
|
968
|
+
);
|
|
862
969
|
}
|
|
863
970
|
|
|
864
971
|
// @deprecated route.url is deprecated
|
|
865
972
|
if (route.url) {
|
|
866
|
-
plugin.printDeprecation(
|
|
973
|
+
plugin.printDeprecation(
|
|
974
|
+
'Usage of "url" property for routes is deprecated. Use "path" instead.'
|
|
975
|
+
);
|
|
867
976
|
}
|
|
868
977
|
route.path = route.path || route.url;
|
|
869
978
|
|
|
@@ -871,25 +980,27 @@ class PluginsManager {
|
|
|
871
980
|
'[%s] binding HTTP route "%s" to controller "%s"',
|
|
872
981
|
plugin.name,
|
|
873
982
|
route.path,
|
|
874
|
-
route.controller
|
|
983
|
+
route.controller
|
|
984
|
+
);
|
|
875
985
|
|
|
876
986
|
// @deprecated "/_plugin" prefix is deprecated for plugin routes
|
|
877
987
|
this.routes.push({
|
|
878
988
|
action: route.action,
|
|
879
989
|
controller,
|
|
880
990
|
path: `/_plugin/${plugin.name}${route.path}`,
|
|
881
|
-
verb: route.verb
|
|
991
|
+
verb: route.verb,
|
|
882
992
|
});
|
|
883
993
|
|
|
884
|
-
const routePath =
|
|
885
|
-
|
|
886
|
-
|
|
994
|
+
const routePath =
|
|
995
|
+
route.path.charAt(0) === "/"
|
|
996
|
+
? `/_${route.path}`
|
|
997
|
+
: `/_/${plugin.name}/${route.path}`;
|
|
887
998
|
|
|
888
999
|
this.routes.push({
|
|
889
1000
|
action: route.action,
|
|
890
1001
|
controller,
|
|
891
1002
|
path: routePath,
|
|
892
|
-
verb: route.verb
|
|
1003
|
+
verb: route.verb,
|
|
893
1004
|
});
|
|
894
1005
|
}
|
|
895
1006
|
}
|
|
@@ -898,18 +1009,20 @@ class PluginsManager {
|
|
|
898
1009
|
* @param {object} plugin
|
|
899
1010
|
* @throws {PluginImplementationError} If strategies registration fails
|
|
900
1011
|
*/
|
|
901
|
-
_initStrategies
|
|
902
|
-
if (
|
|
903
|
-
|
|
1012
|
+
_initStrategies(plugin) {
|
|
1013
|
+
if (
|
|
1014
|
+
!isPlainObject(plugin.instance.strategies) ||
|
|
1015
|
+
_.isEmpty(plugin.instance.strategies)
|
|
904
1016
|
) {
|
|
905
|
-
throw strategyError.get(
|
|
1017
|
+
throw strategyError.get("invalid_definition", plugin.logPrefix);
|
|
906
1018
|
}
|
|
907
1019
|
|
|
908
1020
|
for (const name of Object.keys(plugin.instance.strategies)) {
|
|
909
1021
|
this.registerStrategy(
|
|
910
1022
|
plugin.name,
|
|
911
1023
|
name,
|
|
912
|
-
plugin.instance.strategies[name]
|
|
1024
|
+
plugin.instance.strategies[name]
|
|
1025
|
+
);
|
|
913
1026
|
}
|
|
914
1027
|
}
|
|
915
1028
|
|
|
@@ -917,25 +1030,32 @@ class PluginsManager {
|
|
|
917
1030
|
* @param {object} plugin
|
|
918
1031
|
* @throws {PluginImplementationError} If strategies registration fails
|
|
919
1032
|
*/
|
|
920
|
-
_initAuthenticators
|
|
921
|
-
if (!
|
|
922
|
-
throw kerror.get(
|
|
1033
|
+
_initAuthenticators(plugin) {
|
|
1034
|
+
if (!isPlainObject(plugin.instance.authenticators)) {
|
|
1035
|
+
throw kerror.get(
|
|
1036
|
+
"plugin",
|
|
1037
|
+
"authenticators",
|
|
1038
|
+
"not_an_object",
|
|
1039
|
+
plugin.logPrefix
|
|
1040
|
+
);
|
|
923
1041
|
}
|
|
924
1042
|
|
|
925
1043
|
for (const authenticator of Object.keys(plugin.instance.authenticators)) {
|
|
926
|
-
if (!
|
|
1044
|
+
if (!isConstructor(plugin.instance.authenticators[authenticator])) {
|
|
927
1045
|
throw kerror.get(
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
1046
|
+
"plugin",
|
|
1047
|
+
"authenticators",
|
|
1048
|
+
"invalid_authenticator",
|
|
931
1049
|
plugin.logPrefix,
|
|
932
|
-
authenticator
|
|
1050
|
+
authenticator
|
|
1051
|
+
);
|
|
933
1052
|
}
|
|
934
1053
|
}
|
|
935
1054
|
|
|
936
1055
|
this.authenticators[plugin.name] = Object.assign(
|
|
937
1056
|
{},
|
|
938
|
-
plugin.instance.authenticators
|
|
1057
|
+
plugin.instance.authenticators
|
|
1058
|
+
);
|
|
939
1059
|
}
|
|
940
1060
|
|
|
941
1061
|
/**
|
|
@@ -943,11 +1063,13 @@ class PluginsManager {
|
|
|
943
1063
|
*
|
|
944
1064
|
* @returns {object} list of loaded plugin
|
|
945
1065
|
*/
|
|
946
|
-
loadPlugins
|
|
1066
|
+
loadPlugins(plugins = {}) {
|
|
947
1067
|
const loadedPlugins = new Map();
|
|
948
1068
|
|
|
949
1069
|
// first load plugins from Backend.plugin.use
|
|
950
|
-
for (const [name, { plugin: instance, options }] of Object.entries(
|
|
1070
|
+
for (const [name, { plugin: instance, options }] of Object.entries(
|
|
1071
|
+
plugins
|
|
1072
|
+
)) {
|
|
951
1073
|
const plugin = new Plugin(instance, { name, ...options });
|
|
952
1074
|
|
|
953
1075
|
// the plugin cluster can be loaded in the startup script
|
|
@@ -957,32 +1079,33 @@ class PluginsManager {
|
|
|
957
1079
|
plugin.init(name);
|
|
958
1080
|
|
|
959
1081
|
if (loadedPlugins.has(plugin.name)) {
|
|
960
|
-
throw assertionError.get(
|
|
1082
|
+
throw assertionError.get("name_already_exists", plugin.name);
|
|
961
1083
|
}
|
|
962
1084
|
|
|
963
1085
|
loadedPlugins.set(plugin.name, plugin);
|
|
964
1086
|
}
|
|
965
1087
|
|
|
966
1088
|
// then try to load plugins from the filesystem
|
|
967
|
-
if (!
|
|
1089
|
+
if (!fs.existsSync(this.pluginsEnabledDir)) {
|
|
968
1090
|
return loadedPlugins;
|
|
969
1091
|
}
|
|
970
1092
|
|
|
971
1093
|
let pluginsPath = [];
|
|
972
1094
|
|
|
973
1095
|
try {
|
|
974
|
-
pluginsPath = fs
|
|
975
|
-
.
|
|
976
|
-
.
|
|
977
|
-
|
|
978
|
-
catch (e) {
|
|
1096
|
+
pluginsPath = fs
|
|
1097
|
+
.readdirSync(this.pluginsEnabledDir)
|
|
1098
|
+
.map((name) => path.join(this.pluginsEnabledDir, name))
|
|
1099
|
+
.filter((filePath) => fs.statSync(filePath).isDirectory());
|
|
1100
|
+
} catch (e) {
|
|
979
1101
|
throw assertionError.get(
|
|
980
|
-
|
|
1102
|
+
"invalid_plugins_dir",
|
|
981
1103
|
this.pluginsEnabledDir,
|
|
982
|
-
e.message
|
|
1104
|
+
e.message
|
|
1105
|
+
);
|
|
983
1106
|
}
|
|
984
1107
|
|
|
985
|
-
debug(
|
|
1108
|
+
debug("loading plugins: %a", pluginsPath);
|
|
986
1109
|
|
|
987
1110
|
for (const relativePluginPath of pluginsPath) {
|
|
988
1111
|
const plugin = Plugin.loadFromDirectory(relativePluginPath);
|
|
@@ -990,7 +1113,7 @@ class PluginsManager {
|
|
|
990
1113
|
plugin.init(plugin.manifest.raw.name);
|
|
991
1114
|
|
|
992
1115
|
if (loadedPlugins.has(plugin.name)) {
|
|
993
|
-
throw assertionError.get(
|
|
1116
|
+
throw assertionError.get("name_already_exists", plugin.name);
|
|
994
1117
|
}
|
|
995
1118
|
|
|
996
1119
|
loadedPlugins.set(plugin.name, plugin);
|
|
@@ -1007,7 +1130,7 @@ class PluginsManager {
|
|
|
1007
1130
|
* @param {Function} verifyMethod - Strategy plugin's verify method
|
|
1008
1131
|
* @returns {Function}
|
|
1009
1132
|
*/
|
|
1010
|
-
wrapStrategyVerify
|
|
1133
|
+
wrapStrategyVerify(pluginName, strategyName, verifyMethod) {
|
|
1011
1134
|
const prefix = `${pluginName} Strategy ${strategyName}:`;
|
|
1012
1135
|
|
|
1013
1136
|
return async (...args) => {
|
|
@@ -1016,8 +1139,8 @@ class PluginsManager {
|
|
|
1016
1139
|
|
|
1017
1140
|
// catching plugins returning non-thenable content
|
|
1018
1141
|
// @todo - with async/await we might consider allowing non-promise results
|
|
1019
|
-
if (!
|
|
1020
|
-
callback(strategyError.get(
|
|
1142
|
+
if (!ret || !_.isFunction(ret.then)) {
|
|
1143
|
+
callback(strategyError.get("invalid_verify_return", prefix, ret));
|
|
1021
1144
|
return;
|
|
1022
1145
|
}
|
|
1023
1146
|
|
|
@@ -1025,8 +1148,7 @@ class PluginsManager {
|
|
|
1025
1148
|
|
|
1026
1149
|
try {
|
|
1027
1150
|
result = await ret;
|
|
1028
|
-
}
|
|
1029
|
-
catch (e) {
|
|
1151
|
+
} catch (e) {
|
|
1030
1152
|
callback(e);
|
|
1031
1153
|
return;
|
|
1032
1154
|
}
|
|
@@ -1036,25 +1158,24 @@ class PluginsManager {
|
|
|
1036
1158
|
return;
|
|
1037
1159
|
}
|
|
1038
1160
|
|
|
1039
|
-
if (!
|
|
1040
|
-
callback(strategyError.get(
|
|
1161
|
+
if (!isPlainObject(result)) {
|
|
1162
|
+
callback(strategyError.get("invalid_verify_resolve", prefix));
|
|
1041
1163
|
return;
|
|
1042
1164
|
}
|
|
1043
1165
|
|
|
1044
1166
|
if (result.kuid !== null && result.kuid !== undefined) {
|
|
1045
|
-
if (typeof result.kuid ===
|
|
1167
|
+
if (typeof result.kuid === "string") {
|
|
1046
1168
|
try {
|
|
1047
1169
|
const user = await global.kuzzle.ask(
|
|
1048
|
-
|
|
1049
|
-
result.kuid
|
|
1170
|
+
"core:security:user:get",
|
|
1171
|
+
result.kuid
|
|
1172
|
+
);
|
|
1050
1173
|
|
|
1051
1174
|
callback(null, user);
|
|
1052
|
-
}
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
}
|
|
1057
|
-
else {
|
|
1175
|
+
} catch (e) {
|
|
1176
|
+
if (e.id === "security.user.not_found") {
|
|
1177
|
+
callback(strategyError.get("unknown_kuid", prefix));
|
|
1178
|
+
} else {
|
|
1058
1179
|
callback(e);
|
|
1059
1180
|
}
|
|
1060
1181
|
}
|
|
@@ -1062,15 +1183,14 @@ class PluginsManager {
|
|
|
1062
1183
|
return;
|
|
1063
1184
|
}
|
|
1064
1185
|
|
|
1065
|
-
callback(strategyError.get(
|
|
1186
|
+
callback(strategyError.get("invalid_kuid", prefix, typeof result.kuid));
|
|
1066
1187
|
return;
|
|
1067
1188
|
}
|
|
1068
1189
|
|
|
1069
1190
|
let message;
|
|
1070
|
-
if (result.message && typeof result.message ===
|
|
1191
|
+
if (result.message && typeof result.message === "string") {
|
|
1071
1192
|
message = result.message;
|
|
1072
|
-
}
|
|
1073
|
-
else {
|
|
1193
|
+
} else {
|
|
1074
1194
|
message = `Unable to log in using the strategy "${strategyName}"`;
|
|
1075
1195
|
}
|
|
1076
1196
|
|
|
@@ -1085,25 +1205,26 @@ class PluginsManager {
|
|
|
1085
1205
|
* @param {*} arg
|
|
1086
1206
|
* @returns {Boolean}
|
|
1087
1207
|
*/
|
|
1088
|
-
function isConstructor
|
|
1208
|
+
function isConstructor(arg) {
|
|
1089
1209
|
try {
|
|
1090
1210
|
Reflect.construct(Object, [], arg);
|
|
1091
|
-
}
|
|
1092
|
-
catch (e) {
|
|
1211
|
+
} catch (e) {
|
|
1093
1212
|
return false;
|
|
1094
1213
|
}
|
|
1095
1214
|
|
|
1096
1215
|
return true;
|
|
1097
1216
|
}
|
|
1098
1217
|
|
|
1099
|
-
function getMethods
|
|
1218
|
+
function getMethods(object) {
|
|
1100
1219
|
const prototype = Object.getPrototypeOf(object);
|
|
1101
1220
|
|
|
1102
|
-
const instanceMethods = Object.getOwnPropertyNames(prototype)
|
|
1103
|
-
|
|
1221
|
+
const instanceMethods = Object.getOwnPropertyNames(prototype).filter(
|
|
1222
|
+
(method) => ["init", "constructor"].indexOf(method) === -1
|
|
1223
|
+
);
|
|
1104
1224
|
|
|
1105
|
-
const objectMethods = Object.getOwnPropertyNames(object)
|
|
1106
|
-
|
|
1225
|
+
const objectMethods = Object.getOwnPropertyNames(object).filter(
|
|
1226
|
+
(key) => typeof object[key] === "function"
|
|
1227
|
+
);
|
|
1107
1228
|
|
|
1108
1229
|
return [...instanceMethods, ...objectMethods];
|
|
1109
1230
|
}
|