kuzzle 2.56.0 → 2.57.0-beta.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/dist/bin/copy-binaries.js +71 -4
- package/dist/bin/start-kuzzle-server +191 -97
- package/dist/index.d.ts +31 -1
- package/dist/index.js +45 -2
- package/dist/lib/api/controllers/adminController.d.ts +4 -3
- package/dist/lib/api/controllers/adminController.js +1 -2
- package/dist/lib/api/controllers/authController.d.ts +37 -16
- package/dist/lib/api/controllers/authController.js +88 -39
- package/dist/lib/api/controllers/baseController.d.ts +10 -5
- package/dist/lib/api/controllers/baseController.js +36 -15
- package/dist/lib/api/controllers/bulkController.d.ts +11 -7
- package/dist/lib/api/controllers/bulkController.js +28 -5
- package/dist/lib/api/controllers/clusterController.d.ts +2 -2
- package/dist/lib/api/controllers/clusterController.js +3 -3
- package/dist/lib/api/controllers/collectionController.d.ts +57 -21
- package/dist/lib/api/controllers/collectionController.js +40 -11
- package/dist/lib/api/controllers/debugController.d.ts +1 -1
- package/dist/lib/api/controllers/documentController.d.ts +137 -28
- package/dist/lib/api/controllers/documentController.js +156 -125
- package/dist/lib/api/controllers/index.d.ts +27 -12
- package/dist/lib/api/controllers/index.js +28 -13
- package/dist/lib/api/controllers/indexController.d.ts +17 -10
- package/dist/lib/api/controllers/indexController.js +13 -11
- package/dist/lib/api/controllers/memoryStorageController.d.ts +2 -5
- package/dist/lib/api/controllers/memoryStorageController.js +199 -127
- package/dist/lib/api/controllers/realtimeController.d.ts +19 -9
- package/dist/lib/api/controllers/realtimeController.js +8 -4
- package/dist/lib/api/controllers/securityController.d.ts +42 -29
- package/dist/lib/api/controllers/securityController.js +35 -19
- package/dist/lib/api/controllers/serverController.d.ts +114 -19
- package/dist/lib/api/controllers/serverController.js +69 -29
- package/dist/lib/api/documentExtractor.d.ts +9 -7
- package/dist/lib/api/documentExtractor.js +105 -41
- package/dist/lib/api/funnel.d.ts +131 -29
- package/dist/lib/api/funnel.js +436 -225
- package/dist/lib/api/httpRoutes.d.ts +16 -11
- package/dist/lib/api/httpRoutes.js +272 -2
- package/dist/lib/api/openapi/OpenApiManager.d.ts +1 -1
- package/dist/lib/api/openapi/openApiGenerator.d.ts +1 -1
- package/dist/lib/api/rateLimiter.d.ts +15 -5
- package/dist/lib/api/rateLimiter.js +42 -14
- package/dist/lib/api/request/kuzzleRequest.d.ts +83 -12
- package/dist/lib/api/request/kuzzleRequest.js +88 -23
- package/dist/lib/api/request/requestContext.d.ts +20 -5
- package/dist/lib/api/request/requestContext.js +14 -4
- package/dist/lib/api/request/requestInput.d.ts +37 -6
- package/dist/lib/api/request/requestInput.js +22 -9
- package/dist/lib/api/request/requestResponse.d.ts +45 -9
- package/dist/lib/api/request/requestResponse.js +34 -3
- package/dist/lib/cluster/command.d.ts +131 -37
- package/dist/lib/cluster/command.js +243 -71
- package/dist/lib/cluster/idCardHandler.d.ts +18 -5
- package/dist/lib/cluster/idCardHandler.js +52 -19
- package/dist/lib/cluster/index.d.ts +8 -2
- package/dist/lib/cluster/index.js +6 -2
- package/dist/lib/cluster/node.d.ts +127 -49
- package/dist/lib/cluster/node.js +412 -179
- package/dist/lib/cluster/protobuf/command.proto +18 -0
- package/dist/lib/cluster/protobuf/commandMessages.d.ts +104 -0
- package/dist/lib/cluster/protobuf/commandMessages.js +30 -0
- package/dist/lib/cluster/protobuf/syncMessages.d.ts +184 -0
- package/dist/lib/cluster/protobuf/syncMessages.js +23 -0
- package/dist/lib/cluster/publisher.d.ts +118 -78
- package/dist/lib/cluster/publisher.js +174 -72
- package/dist/lib/cluster/state.d.ts +15 -9
- package/dist/lib/cluster/state.js +12 -8
- package/dist/lib/cluster/subscriber.d.ts +185 -131
- package/dist/lib/cluster/subscriber.js +357 -95
- package/dist/lib/cluster/workers/IDCardRenewer.d.ts +39 -8
- package/dist/lib/cluster/workers/IDCardRenewer.js +88 -23
- package/dist/lib/config/default.config.d.ts +2 -2
- package/dist/lib/config/default.config.js +10 -3
- package/dist/lib/config/documentEventAliases.d.ts +1 -1
- package/dist/lib/config/index.d.ts +2 -5
- package/dist/lib/config/index.js +30 -17
- package/dist/lib/core/auth/formatProcessing.d.ts +3 -3
- package/dist/lib/core/auth/passportResponse.d.ts +1 -1
- package/dist/lib/core/auth/passportWrapper.d.ts +1 -1
- package/dist/lib/core/auth/passportWrapper.js +14 -13
- package/dist/lib/core/auth/tokenManager.d.ts +24 -3
- package/dist/lib/core/auth/tokenManager.js +47 -19
- package/dist/lib/core/backend/applicationManager.d.ts +2 -2
- package/dist/lib/core/backend/backend.d.ts +16 -5
- package/dist/lib/core/backend/backend.js +14 -6
- package/dist/lib/core/backend/backendCluster.d.ts +1 -1
- package/dist/lib/core/backend/backendConfig.d.ts +17 -5
- package/dist/lib/core/backend/backendConfig.js +1 -0
- package/dist/lib/core/backend/backendController.d.ts +1 -1
- package/dist/lib/core/backend/backendController.js +8 -1
- package/dist/lib/core/backend/backendErrors.d.ts +15 -8
- package/dist/lib/core/backend/backendErrors.js +5 -0
- package/dist/lib/core/backend/backendHook.d.ts +1 -1
- package/dist/lib/core/backend/backendImport.d.ts +1 -1
- package/dist/lib/core/backend/backendOpenApi.d.ts +3 -2
- package/dist/lib/core/backend/backendPipe.d.ts +1 -1
- package/dist/lib/core/backend/backendPipe.js +9 -1
- package/dist/lib/core/backend/backendPlugin.d.ts +2 -2
- package/dist/lib/core/backend/backendSubscription.d.ts +2 -2
- package/dist/lib/core/backend/backendVault.d.ts +1 -1
- package/dist/lib/core/backend/backendVault.js +8 -1
- package/dist/lib/core/cache/cacheEngine.d.ts +7 -4
- package/dist/lib/core/cache/cacheEngine.js +25 -8
- package/dist/lib/core/debug/kuzzleDebugger.d.ts +2 -1
- package/dist/lib/core/debug/kuzzleDebugger.js +31 -17
- package/dist/lib/core/network/accessLogger.d.ts +33 -18
- package/dist/lib/core/network/accessLogger.js +135 -73
- package/dist/lib/core/network/clientConnection.d.ts +13 -11
- package/dist/lib/core/network/clientConnection.js +33 -9
- package/dist/lib/core/network/context.d.ts +17 -22
- package/dist/lib/core/network/context.js +43 -26
- package/dist/lib/core/network/entryPoint.d.ts +38 -16
- package/dist/lib/core/network/entryPoint.js +119 -48
- package/dist/lib/core/network/httpRouter/index.d.ts +20 -50
- package/dist/lib/core/network/httpRouter/index.js +61 -75
- package/dist/lib/core/network/httpRouter/routeHandler.d.ts +17 -32
- package/dist/lib/core/network/httpRouter/routeHandler.js +26 -36
- package/dist/lib/core/network/httpRouter/routePart.d.ts +9 -18
- package/dist/lib/core/network/httpRouter/routePart.js +61 -43
- package/dist/lib/core/network/httpRouter/routeTypes.d.ts +3 -0
- package/dist/lib/core/network/httpRouter/routeTypes.js +23 -0
- package/dist/lib/core/network/networkEntryPoint.d.ts +20 -0
- package/dist/lib/core/network/networkEntryPoint.js +23 -0
- package/dist/lib/core/network/protocolManifest.d.ts +5 -4
- package/dist/lib/core/network/protocolManifest.js +6 -3
- package/dist/lib/core/network/protocols/httpMessage.d.ts +25 -18
- package/dist/lib/core/network/protocols/httpMessage.js +14 -11
- package/dist/lib/core/network/protocols/httpwsProtocol.d.ts +84 -93
- package/dist/lib/core/network/protocols/httpwsProtocol.js +284 -129
- package/dist/lib/core/network/protocols/internalProtocol.d.ts +26 -15
- package/dist/lib/core/network/protocols/internalProtocol.js +17 -16
- package/dist/lib/core/network/protocols/mqttProtocol.d.ts +56 -32
- package/dist/lib/core/network/protocols/mqttProtocol.js +91 -44
- package/dist/lib/core/network/protocols/protocol.d.ts +85 -21
- package/dist/lib/core/network/protocols/protocol.js +83 -27
- package/dist/lib/core/network/router.d.ts +13 -22
- package/dist/lib/core/network/router.js +59 -46
- package/dist/lib/core/plugin/plugin.d.ts +57 -51
- package/dist/lib/core/plugin/plugin.js +218 -103
- package/dist/lib/core/plugin/pluginContext.d.ts +54 -11
- package/dist/lib/core/plugin/pluginContext.js +99 -58
- package/dist/lib/core/plugin/pluginManifest.d.ts +6 -2
- package/dist/lib/core/plugin/pluginManifest.js +18 -11
- package/dist/lib/core/plugin/pluginRepository.d.ts +35 -44
- package/dist/lib/core/plugin/pluginRepository.js +35 -50
- package/dist/lib/core/plugin/pluginsManager.d.ts +128 -46
- package/dist/lib/core/plugin/pluginsManager.js +468 -231
- package/dist/lib/core/plugin/privilegedContext.d.ts +4 -9
- package/dist/lib/core/plugin/privilegedContext.js +5 -10
- package/dist/lib/core/realtime/actionEnum.d.ts +12 -21
- package/dist/lib/core/realtime/actionEnum.js +6 -7
- package/dist/lib/core/realtime/channel.d.ts +11 -5
- package/dist/lib/core/realtime/channel.js +17 -2
- package/dist/lib/core/realtime/connectionRooms.d.ts +2 -2
- package/dist/lib/core/realtime/hotelClerk.d.ts +12 -6
- package/dist/lib/core/realtime/hotelClerk.js +29 -11
- package/dist/lib/core/realtime/index.d.ts +8 -3
- package/dist/lib/core/realtime/index.js +12 -5
- package/dist/lib/core/realtime/notification/document.d.ts +54 -25
- package/dist/lib/core/realtime/notification/document.js +10 -13
- package/dist/lib/core/realtime/notification/index.d.ts +9 -3
- package/dist/lib/core/realtime/notification/index.js +10 -4
- package/dist/lib/core/realtime/notification/server.d.ts +7 -10
- package/dist/lib/core/realtime/notification/server.js +4 -7
- package/dist/lib/core/realtime/notification/user.d.ts +45 -21
- package/dist/lib/core/realtime/notification/user.js +8 -9
- package/dist/lib/core/realtime/notifier.d.ts +52 -40
- package/dist/lib/core/realtime/notifier.js +60 -25
- package/dist/lib/core/realtime/room.d.ts +1 -1
- package/dist/lib/core/realtime/subscription.d.ts +11 -6
- package/dist/lib/core/realtime/subscription.js +5 -1
- package/dist/lib/core/security/index.d.ts +14 -6
- package/dist/lib/core/security/index.js +27 -13
- package/dist/lib/core/security/profileRepository.d.ts +24 -19
- package/dist/lib/core/security/profileRepository.js +23 -10
- package/dist/lib/core/security/roleRepository.d.ts +60 -23
- package/dist/lib/core/security/roleRepository.js +122 -53
- package/dist/lib/core/security/securityLoader.d.ts +33 -18
- package/dist/lib/core/security/securityLoader.js +43 -16
- package/dist/lib/core/security/tokenRepository.d.ts +21 -7
- package/dist/lib/core/security/tokenRepository.js +50 -23
- package/dist/lib/core/security/userRepository.d.ts +44 -21
- package/dist/lib/core/security/userRepository.js +59 -19
- package/dist/lib/core/shared/KoncordeWrapper.d.ts +1 -1
- package/dist/lib/core/shared/ObjectRepository.d.ts +80 -18
- package/dist/lib/core/shared/ObjectRepository.js +57 -29
- package/dist/lib/core/shared/abstractManifest.d.ts +21 -8
- package/dist/lib/core/shared/abstractManifest.js +57 -17
- package/dist/lib/core/shared/sdk/embeddedSdk.d.ts +3 -1
- package/dist/lib/core/shared/sdk/embeddedSdk.js +8 -7
- package/dist/lib/core/shared/sdk/funnelProtocol.d.ts +2 -1
- package/dist/lib/core/shared/sdk/funnelProtocol.js +12 -3
- package/dist/lib/core/shared/sdk/impersonatedSdk.d.ts +11 -5
- package/dist/lib/core/shared/sdk/impersonatedSdk.js +22 -9
- package/dist/lib/core/shared/store.d.ts +45 -29
- package/dist/lib/core/shared/store.js +48 -27
- package/dist/lib/core/statistics/statistics.d.ts +1 -1
- package/dist/lib/core/storage/clientAdapter.d.ts +39 -21
- package/dist/lib/core/storage/clientAdapter.js +88 -48
- package/dist/lib/core/storage/indexCache.d.ts +8 -0
- package/dist/lib/core/storage/indexCache.js +16 -7
- package/dist/lib/core/storage/storageEngine.d.ts +7 -6
- package/dist/lib/core/storage/storageEngine.js +11 -8
- package/dist/lib/core/validation/baseType.d.ts +22 -22
- package/dist/lib/core/validation/baseType.js +11 -26
- package/dist/lib/core/validation/specification.d.ts +148 -0
- package/dist/lib/core/validation/specification.js +34 -0
- package/dist/lib/core/validation/typeOptions.d.ts +62 -0
- package/dist/lib/core/validation/typeOptions.js +23 -0
- package/dist/lib/core/validation/types/anything.d.ts +3 -6
- package/dist/lib/core/validation/types/anything.js +7 -7
- package/dist/lib/core/validation/types/boolean.d.ts +5 -12
- package/dist/lib/core/validation/types/boolean.js +7 -12
- package/dist/lib/core/validation/types/date.d.ts +19 -11
- package/dist/lib/core/validation/types/date.js +212 -161
- package/dist/lib/core/validation/types/email.d.ts +7 -11
- package/dist/lib/core/validation/types/email.js +13 -17
- package/dist/lib/core/validation/types/enum.d.ts +7 -11
- package/dist/lib/core/validation/types/enum.js +39 -20
- package/dist/lib/core/validation/types/geoPoint.d.ts +5 -13
- package/dist/lib/core/validation/types/geoPoint.js +10 -15
- package/dist/lib/core/validation/types/geoShape.d.ts +22 -21
- package/dist/lib/core/validation/types/geoShape.js +113 -129
- package/dist/lib/core/validation/types/geoShapeUtils.d.ts +15 -0
- package/dist/lib/core/validation/types/geoShapeUtils.js +75 -0
- package/dist/lib/core/validation/types/integer.d.ts +7 -5
- package/dist/lib/core/validation/types/integer.js +7 -13
- package/dist/lib/core/validation/types/ipAddress.d.ts +7 -11
- package/dist/lib/core/validation/types/ipAddress.js +13 -17
- package/dist/lib/core/validation/types/numeric.d.ts +7 -11
- package/dist/lib/core/validation/types/numeric.js +22 -29
- package/dist/lib/core/validation/types/object.d.ts +8 -15
- package/dist/lib/core/validation/types/object.js +12 -21
- package/dist/lib/core/validation/types/string.d.ts +7 -11
- package/dist/lib/core/validation/types/string.js +22 -29
- package/dist/lib/core/validation/types/url.d.ts +7 -11
- package/dist/lib/core/validation/types/url.js +14 -18
- package/dist/lib/core/validation/validation.d.ts +119 -80
- package/dist/lib/core/validation/validation.js +470 -412
- package/dist/lib/core/validation/validationUtils.d.ts +31 -0
- package/dist/lib/core/validation/validationUtils.js +190 -0
- package/dist/lib/kerror/codes/4-plugin.json +0 -12
- package/dist/lib/kerror/codes/index.d.ts +12 -2
- package/dist/lib/kerror/codes/index.js +5 -4
- package/dist/lib/kerror/errors/badRequestError.d.ts +1 -1
- package/dist/lib/kerror/errors/badRequestError.js +1 -1
- package/dist/lib/kerror/errors/externalServiceError.d.ts +1 -1
- package/dist/lib/kerror/errors/externalServiceError.js +1 -1
- package/dist/lib/kerror/errors/forbiddenError.d.ts +1 -1
- package/dist/lib/kerror/errors/forbiddenError.js +1 -1
- package/dist/lib/kerror/errors/gatewayTimeoutError.d.ts +1 -1
- package/dist/lib/kerror/errors/gatewayTimeoutError.js +1 -1
- package/dist/lib/kerror/errors/internalError.d.ts +1 -1
- package/dist/lib/kerror/errors/internalError.js +1 -1
- package/dist/lib/kerror/errors/kuzzleError.d.ts +32 -3
- package/dist/lib/kerror/errors/kuzzleError.js +21 -7
- package/dist/lib/kerror/errors/multipleErrorsError.d.ts +2 -2
- package/dist/lib/kerror/errors/multipleErrorsError.js +2 -2
- package/dist/lib/kerror/errors/notFoundError.d.ts +1 -1
- package/dist/lib/kerror/errors/notFoundError.js +1 -1
- package/dist/lib/kerror/errors/partialError.d.ts +8 -2
- package/dist/lib/kerror/errors/partialError.js +22 -9
- package/dist/lib/kerror/errors/pluginImplementationError.d.ts +9 -1
- package/dist/lib/kerror/errors/pluginImplementationError.js +9 -3
- package/dist/lib/kerror/errors/preconditionError.d.ts +1 -1
- package/dist/lib/kerror/errors/preconditionError.js +1 -1
- package/dist/lib/kerror/errors/serviceUnavailableError.d.ts +1 -1
- package/dist/lib/kerror/errors/serviceUnavailableError.js +1 -1
- package/dist/lib/kerror/errors/sizeLimitError.d.ts +1 -1
- package/dist/lib/kerror/errors/sizeLimitError.js +1 -1
- package/dist/lib/kerror/errors/tooManyRequestsError.d.ts +1 -1
- package/dist/lib/kerror/errors/tooManyRequestsError.js +1 -1
- package/dist/lib/kerror/errors/unauthorizedError.d.ts +1 -1
- package/dist/lib/kerror/errors/unauthorizedError.js +1 -1
- package/dist/lib/kerror/index.d.ts +19 -13
- package/dist/lib/kerror/index.js +60 -19
- package/dist/lib/kuzzle/Logger.d.ts +2 -2
- package/dist/lib/kuzzle/dumpGenerator.d.ts +12 -8
- package/dist/lib/kuzzle/dumpGenerator.js +130 -62
- package/dist/lib/kuzzle/event/KuzzleEventEmitter.d.ts +18 -9
- package/dist/lib/kuzzle/event/KuzzleEventEmitter.js +45 -18
- package/dist/lib/kuzzle/event/pipeRunner.d.ts +37 -16
- package/dist/lib/kuzzle/event/pipeRunner.js +73 -26
- package/dist/lib/kuzzle/event/waterfall.d.ts +11 -1
- package/dist/lib/kuzzle/event/waterfall.js +38 -13
- package/dist/lib/kuzzle/internalIndexHandler.d.ts +11 -174
- package/dist/lib/kuzzle/internalIndexHandler.js +58 -29
- package/dist/lib/kuzzle/kuzzle.d.ts +25 -10
- package/dist/lib/kuzzle/kuzzle.js +74 -17
- package/dist/lib/kuzzle/kuzzleStateEnum.d.ts +16 -12
- package/dist/lib/kuzzle/kuzzleStateEnum.js +5 -7
- package/dist/lib/kuzzle/vault.d.ts +5 -1
- package/dist/lib/kuzzle/vault.js +29 -17
- package/dist/lib/model/security/profile.d.ts +34 -5
- package/dist/lib/model/security/profile.js +6 -5
- package/dist/lib/model/security/rights.d.ts +12 -4
- package/dist/lib/model/security/rights.js +7 -6
- package/dist/lib/model/security/role.d.ts +8 -4
- package/dist/lib/model/security/role.js +12 -6
- package/dist/lib/model/security/token.d.ts +8 -0
- package/dist/lib/model/security/user.d.ts +8 -2
- package/dist/lib/model/security/user.js +7 -4
- package/dist/lib/model/storage/apiKey.d.ts +55 -26
- package/dist/lib/model/storage/apiKey.js +97 -24
- package/dist/lib/model/storage/baseModel.d.ts +77 -66
- package/dist/lib/model/storage/baseModel.js +21 -34
- package/dist/lib/service/cache/redis.d.ts +53 -36
- package/dist/lib/service/cache/redis.js +148 -71
- package/dist/lib/service/service.d.ts +14 -19
- package/dist/lib/service/service.js +41 -22
- package/dist/lib/service/storage/7/elasticsearch.d.ts +136 -93
- package/dist/lib/service/storage/7/elasticsearch.js +218 -165
- package/dist/lib/service/storage/7/esWrapper.d.ts +30 -13
- package/dist/lib/service/storage/7/esWrapper.js +58 -37
- package/dist/lib/service/storage/8/elasticsearch.d.ts +153 -119
- package/dist/lib/service/storage/8/elasticsearch.js +286 -213
- package/dist/lib/service/storage/8/esWrapper.d.ts +30 -13
- package/dist/lib/service/storage/8/esWrapper.js +59 -38
- package/dist/lib/service/storage/commons/queryTranslator.d.ts +3 -3
- package/dist/lib/service/storage/commons/queryTranslator.js +71 -35
- package/dist/lib/types/ApiRoute.d.ts +12 -0
- package/dist/lib/types/ApiRoute.js +23 -0
- package/dist/lib/types/ClientConnection.d.ts +1 -1
- package/dist/lib/types/EventHandler.d.ts +10 -0
- package/dist/lib/types/Global.d.ts +8 -3
- package/dist/lib/types/HttpMessage.d.ts +2 -2
- package/dist/lib/types/HttpStream.d.ts +1 -1
- package/dist/lib/types/HttpStream.js +3 -1
- package/dist/lib/types/JSONObject.d.ts +9 -0
- package/dist/lib/types/JSONObject.js +23 -0
- package/dist/lib/types/Kuzzle.d.ts +5 -3
- package/dist/lib/types/KuzzleDocument.d.ts +1 -1
- package/dist/lib/types/KuzzleWebSocket.d.ts +24 -0
- package/dist/lib/types/KuzzleWebSocket.js +23 -0
- package/dist/lib/types/OpenApiDefinition.d.ts +1 -1
- package/dist/lib/types/Plugin.d.ts +33 -8
- package/dist/lib/types/PluginInstance.d.ts +67 -0
- package/dist/lib/types/PluginInstance.js +23 -0
- package/dist/lib/types/Policy.d.ts +1 -1
- package/dist/lib/types/Target.d.ts +8 -0
- package/dist/lib/types/Token.d.ts +14 -2
- package/dist/lib/types/config/HttpConfiguration.d.ts +5 -0
- package/dist/lib/types/config/KuzzleConfiguration.d.ts +102 -1
- package/dist/lib/types/config/PluginsConfiguration.d.ts +3 -2
- package/dist/lib/types/config/SecurityConfiguration.d.ts +6 -2
- package/dist/lib/types/config/ServerConfiguration.d.ts +2 -2
- package/dist/lib/types/config/ServicesConfiguration.d.ts +1 -1
- package/dist/lib/types/config/cache/BaseCacheRedisConfiguration.d.ts +131 -0
- package/dist/lib/types/config/cache/BaseCacheRedisConfiguration.js +3 -0
- package/dist/lib/types/config/internalCache/InternalCacheRedisConfiguration.d.ts +2 -106
- package/dist/lib/types/config/publicCache/PublicCacheRedisConfiguration.d.ts +2 -26
- package/dist/lib/types/config/storageEngine/StorageEngineElasticsearchConfiguration.d.ts +3 -0
- package/dist/lib/types/controllers/Controller.d.ts +12 -3
- package/dist/lib/types/controllers/ControllerDefinition.d.ts +2 -2
- package/dist/lib/types/controllers/{adminControlller.type.js → adminController.type.js} +1 -1
- package/dist/lib/types/controllers/authController.type.d.ts +2 -2
- package/dist/lib/types/core/auth/formatProcessing.type.d.ts +7 -1
- package/dist/lib/types/errors/ErrorDomains.d.ts +1 -1
- package/dist/lib/types/events/EventGenericDocument.d.ts +10 -9
- package/dist/lib/types/events/EventProtocol.d.ts +4 -4
- package/dist/lib/types/index.d.ts +7 -0
- package/dist/lib/types/index.js +7 -0
- package/dist/lib/types/shared/StoreCollectionsDefinition.d.ts +1 -1
- package/dist/lib/types/storage/7/Elasticsearch.d.ts +62 -13
- package/dist/lib/types/storage/8/Elasticsearch.d.ts +62 -13
- package/dist/lib/util/Inflector.d.ts +4 -1
- package/dist/lib/util/Inflector.js +0 -3
- package/dist/lib/util/assertType.d.ts +24 -27
- package/dist/lib/util/assertType.js +28 -39
- package/dist/lib/util/async.js +19 -6
- package/dist/lib/util/asyncStore.js +1 -1
- package/dist/lib/util/bufferedPassThrough.d.ts +9 -0
- package/dist/lib/util/bufferedPassThrough.js +27 -13
- package/dist/lib/util/bytes.d.ts +1 -1
- package/dist/lib/util/bytes.js +6 -2
- package/dist/lib/util/debug.d.ts +3 -1
- package/dist/lib/util/debug.js +42 -10
- package/dist/lib/util/deprecate.d.ts +9 -1
- package/dist/lib/util/deprecate.js +10 -6
- package/dist/lib/util/didYouMean.d.ts +2 -1
- package/dist/lib/util/didYouMean.js +8 -4
- package/dist/lib/util/distributedLock.d.ts +56 -0
- package/dist/lib/util/distributedLock.js +166 -0
- package/dist/lib/util/dump-collection.d.ts +1 -1
- package/dist/lib/util/dump-collection.js +4 -5
- package/dist/lib/util/extractFields.d.ts +15 -11
- package/dist/lib/util/extractFields.js +8 -9
- package/dist/lib/util/koncordeCompat.d.ts +2 -2
- package/dist/lib/util/koncordeCompat.js +33 -0
- package/dist/lib/util/memoize.d.ts +7 -6
- package/dist/lib/util/memoize.js +3 -3
- package/dist/lib/util/mutex.d.ts +22 -2
- package/dist/lib/util/mutex.js +39 -1
- package/dist/lib/util/name-generator.js +14 -2
- package/dist/lib/util/promback.d.ts +20 -11
- package/dist/lib/util/promback.js +14 -7
- package/dist/lib/util/requestAssertions.d.ts +30 -10
- package/dist/lib/util/requestAssertions.js +125 -121
- package/dist/lib/util/safeObject.d.ts +3 -3
- package/dist/lib/util/safeObject.js +7 -3
- package/dist/lib/util/stackTrace.d.ts +13 -5
- package/dist/lib/util/stackTrace.js +17 -12
- package/dist/lib/util/thrown.d.ts +13 -0
- package/dist/lib/util/thrown.js +46 -0
- package/dist/package.json +26 -19
- package/package.json +26 -19
- package/dist/lib/util/wildcard.d.ts +0 -1
- package/dist/lib/util/wildcard.js +0 -46
- /package/dist/lib/types/controllers/{adminControlller.type.d.ts → adminController.type.d.ts} +0 -0
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
"use strict";
|
|
1
2
|
/*
|
|
2
3
|
* Kuzzle, a backend software, self-hostable and ready to use
|
|
3
4
|
* to power modern apps
|
|
@@ -18,30 +19,77 @@
|
|
|
18
19
|
* See the License for the specific language governing permissions and
|
|
19
20
|
* limitations under the License.
|
|
20
21
|
*/
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
22
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
23
|
+
if (k2 === undefined) k2 = k;
|
|
24
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
25
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
26
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
27
|
+
}
|
|
28
|
+
Object.defineProperty(o, k2, desc);
|
|
29
|
+
}) : (function(o, m, k, k2) {
|
|
30
|
+
if (k2 === undefined) k2 = k;
|
|
31
|
+
o[k2] = m[k];
|
|
32
|
+
}));
|
|
33
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
34
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
35
|
+
}) : function(o, v) {
|
|
36
|
+
o["default"] = v;
|
|
37
|
+
});
|
|
38
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
39
|
+
if (mod && mod.__esModule) return mod;
|
|
40
|
+
var result = {};
|
|
41
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
42
|
+
__setModuleDefault(result, mod);
|
|
43
|
+
return result;
|
|
44
|
+
};
|
|
45
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
46
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
47
|
+
};
|
|
48
|
+
const node_assert_1 = __importDefault(require("node:assert"));
|
|
49
|
+
const node_fs_1 = __importDefault(require("node:fs"));
|
|
50
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
51
|
+
const bluebird_1 = __importDefault(require("bluebird"));
|
|
52
|
+
const lodash_1 = require("lodash");
|
|
53
|
+
const baseController_1 = require("../../api/controllers/baseController");
|
|
54
|
+
const kerror = __importStar(require("../../kerror"));
|
|
55
|
+
const errors_1 = require("../../kerror/errors");
|
|
56
|
+
const debug_1 = __importDefault(require("../../util/debug"));
|
|
57
|
+
const didYouMean_1 = __importDefault(require("../../util/didYouMean"));
|
|
58
|
+
const Inflector_1 = require("../../util/Inflector");
|
|
59
|
+
const safeObject_1 = require("../../util/safeObject");
|
|
60
|
+
const thrown_1 = require("../../util/thrown");
|
|
61
|
+
const plugin_1 = __importDefault(require("./plugin"));
|
|
62
|
+
const debug = (0, debug_1.default)("kuzzle:plugins");
|
|
35
63
|
const assertionError = kerror.wrap("plugin", "assert");
|
|
36
64
|
const runtimeError = kerror.wrap("plugin", "runtime");
|
|
37
65
|
const strategyError = kerror.wrap("plugin", "strategy");
|
|
38
66
|
const controllerError = kerror.wrap("plugin", "controller");
|
|
39
67
|
// Without those plugins, Kuzzle won't start at all.
|
|
40
|
-
const CORE_PLUGINS = ["kuzzle-plugin-auth-passport-local"];
|
|
68
|
+
const CORE_PLUGINS = new Set(["kuzzle-plugin-auth-passport-local"]);
|
|
41
69
|
/**
|
|
42
|
-
*
|
|
43
|
-
* @param {Kuzzle} kuzzle
|
|
70
|
+
* The `id` of whatever was thrown, when it carries one.
|
|
44
71
|
*/
|
|
72
|
+
function idOf(thrown) {
|
|
73
|
+
if (typeof thrown === "object" &&
|
|
74
|
+
thrown !== null &&
|
|
75
|
+
"id" in thrown &&
|
|
76
|
+
typeof thrown.id === "string") {
|
|
77
|
+
return thrown.id;
|
|
78
|
+
}
|
|
79
|
+
return undefined;
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Whatever was thrown, as the `KuzzleError` the caller is about to forward.
|
|
83
|
+
* A plugin's own KuzzleError passes through untouched — that is the contract
|
|
84
|
+
* these two handlers have always honoured.
|
|
85
|
+
*/
|
|
86
|
+
function asKuzzleError(thrown) {
|
|
87
|
+
if (thrown instanceof errors_1.KuzzleError) {
|
|
88
|
+
return thrown;
|
|
89
|
+
}
|
|
90
|
+
const cause = (0, thrown_1.causeOf)(thrown);
|
|
91
|
+
return runtimeError.getFrom(cause, "unexpected_error", cause.message);
|
|
92
|
+
}
|
|
45
93
|
class PluginsManager {
|
|
46
94
|
constructor() {
|
|
47
95
|
Reflect.defineProperty(this, "kuzzle", {
|
|
@@ -52,8 +100,8 @@ class PluginsManager {
|
|
|
52
100
|
this.controllers = new Map();
|
|
53
101
|
this.strategies = {};
|
|
54
102
|
this.routes = [];
|
|
55
|
-
this.pluginsEnabledDir =
|
|
56
|
-
this.pluginsAvailableDir =
|
|
103
|
+
this.pluginsEnabledDir = node_path_1.default.resolve(node_path_1.default.join(global.kuzzle.rootPath, "plugins", "enabled"));
|
|
104
|
+
this.pluginsAvailableDir = node_path_1.default.resolve(node_path_1.default.join(global.kuzzle.rootPath, "plugins", "available"));
|
|
57
105
|
/**
|
|
58
106
|
* @example
|
|
59
107
|
* {
|
|
@@ -80,16 +128,53 @@ class PluginsManager {
|
|
|
80
128
|
this.loadedPlugins = [];
|
|
81
129
|
}
|
|
82
130
|
set application(plugin) {
|
|
83
|
-
|
|
84
|
-
|
|
131
|
+
(0, node_assert_1.default)(this._plugins.size === 0, "The application plugin can only be set before every other plugins are loaded");
|
|
132
|
+
(0, node_assert_1.default)(plugin.application, 'The application plugin must have the "application" property equals to true');
|
|
85
133
|
this._plugins.set(plugin.name, plugin);
|
|
86
134
|
}
|
|
87
135
|
get plugins() {
|
|
88
136
|
return Array.from(this._plugins.values()).filter((plugin) => !plugin.application);
|
|
89
137
|
}
|
|
138
|
+
/**
|
|
139
|
+
* The application plugin, once `kuzzle.start` has registered one.
|
|
140
|
+
*
|
|
141
|
+
* `undefined` before that, and the shutdown path already read it that way —
|
|
142
|
+
* `pluginsManager?.application?.instance?.log?.flush?.()` defends against a
|
|
143
|
+
* start that failed before the assignment. The declared `Plugin` was the
|
|
144
|
+
* half of that the three eager readers assumed.
|
|
145
|
+
*/
|
|
90
146
|
get application() {
|
|
91
147
|
return Array.from(this._plugins.values()).find((plugin) => plugin.application);
|
|
92
148
|
}
|
|
149
|
+
/**
|
|
150
|
+
* The plugin registered under `pluginName`, which is the only thing the
|
|
151
|
+
* strategy methods below can act on. Pre-Kaaf plugin names may carry upper
|
|
152
|
+
* case, hence the lowercasing every call site did for itself.
|
|
153
|
+
*
|
|
154
|
+
* The three callers dereferenced the map's answer unchecked — a strategy
|
|
155
|
+
* registered for an unknown plugin read `undefined.initCalled`. The error
|
|
156
|
+
* is the one `Backend.plugin.get` already raises for the same question.
|
|
157
|
+
*/
|
|
158
|
+
getPlugin(pluginName) {
|
|
159
|
+
const plugin = this._plugins.get(pluginName.toLowerCase());
|
|
160
|
+
if (plugin === undefined) {
|
|
161
|
+
throw assertionError.get("plugin_not_found", pluginName, (0, didYouMean_1.default)(pluginName, Array.from(this._plugins.keys())));
|
|
162
|
+
}
|
|
163
|
+
return plugin;
|
|
164
|
+
}
|
|
165
|
+
/**
|
|
166
|
+
* The strategy registered under `strategyName`. Reading it off the record
|
|
167
|
+
* and dereferencing straight away is what `getStrategyFields` and
|
|
168
|
+
* `getStrategyMethod` did; `hasStrategyMethod` is the guard that existed,
|
|
169
|
+
* and only one of the two call sites used it.
|
|
170
|
+
*/
|
|
171
|
+
getStrategy(strategyName) {
|
|
172
|
+
const strategy = this.strategies[strategyName];
|
|
173
|
+
if (strategy === undefined) {
|
|
174
|
+
throw strategyError.get("strategy_not_found", strategyName);
|
|
175
|
+
}
|
|
176
|
+
return strategy;
|
|
177
|
+
}
|
|
93
178
|
/**
|
|
94
179
|
* Giving a controller name, tells if exists
|
|
95
180
|
*
|
|
@@ -116,7 +201,11 @@ class PluginsManager {
|
|
|
116
201
|
* @returns {Array}
|
|
117
202
|
*/
|
|
118
203
|
getActions(controller) {
|
|
119
|
-
|
|
204
|
+
const registered = this.controllers.get(controller);
|
|
205
|
+
// An unregistered controller has no actions. Reading `._actions` off the
|
|
206
|
+
// map's answer raised a TypeError instead, which is what `isAction`
|
|
207
|
+
// answered for a controller `isController` says does not exist.
|
|
208
|
+
return registered === undefined ? [] : Array.from(registered._actions);
|
|
120
209
|
}
|
|
121
210
|
/**
|
|
122
211
|
* Returns an array filled with controller names
|
|
@@ -167,8 +256,7 @@ class PluginsManager {
|
|
|
167
256
|
const loadPlugins = [];
|
|
168
257
|
const defaultImports = {};
|
|
169
258
|
for (const plugin of this._plugins.values()) {
|
|
170
|
-
if (this.config.common.failsafeMode &&
|
|
171
|
-
!CORE_PLUGINS.includes(plugin.name)) {
|
|
259
|
+
if (this.config.common.failsafeMode && !CORE_PLUGINS.has(plugin.name)) {
|
|
172
260
|
this.logger.info(`Failsafe mode activated, skipping plugin "${plugin.name}"`);
|
|
173
261
|
continue;
|
|
174
262
|
}
|
|
@@ -177,9 +265,17 @@ class PluginsManager {
|
|
|
177
265
|
}
|
|
178
266
|
const { initTimeout } = this.config.common;
|
|
179
267
|
debug('[%s] starting plugin in "%s" mode', plugin.name, plugin.config.privileged ? "privileged" : "standard");
|
|
180
|
-
const
|
|
268
|
+
const { init } = plugin.instance;
|
|
269
|
+
// Both loaders — `loadPlugins` here and `Backend.plugin.use` — refuse a
|
|
270
|
+
// plugin without one, so this is the third statement of the same
|
|
271
|
+
// precondition rather than a new one. It is the type of `init` on a
|
|
272
|
+
// user-supplied object that makes it appear.
|
|
273
|
+
if (!isPluginMethod(init)) {
|
|
274
|
+
throw assertionError.get("init_not_found", plugin.name);
|
|
275
|
+
}
|
|
276
|
+
const promise = bluebird_1.default.resolve((async () => {
|
|
181
277
|
try {
|
|
182
|
-
await plugin.instance
|
|
278
|
+
await init.call(plugin.instance, plugin.config, plugin.context);
|
|
183
279
|
}
|
|
184
280
|
catch (error) {
|
|
185
281
|
throw runtimeError.get("failed_init", plugin.name, error);
|
|
@@ -188,34 +284,34 @@ class PluginsManager {
|
|
|
188
284
|
.timeout(initTimeout, `${plugin.logPrefix} Initialization timed out after ${initTimeout}ms. Try to increase the configuration "plugins.common.initTimeout".`)
|
|
189
285
|
.then(async () => {
|
|
190
286
|
plugin.initCalled = true;
|
|
191
|
-
if (!
|
|
192
|
-
!
|
|
287
|
+
if (!(0, lodash_1.isEmpty)(plugin.instance.controllers) &&
|
|
288
|
+
!(0, lodash_1.isEmpty)(plugin.instance.api)) {
|
|
193
289
|
throw assertionError.get("duplicated_api_definition");
|
|
194
290
|
}
|
|
195
|
-
if (!
|
|
291
|
+
if (!(0, lodash_1.isEmpty)(plugin.instance.controllers)) {
|
|
196
292
|
this._initControllers(plugin);
|
|
197
293
|
}
|
|
198
|
-
if (!
|
|
294
|
+
if (!(0, lodash_1.isEmpty)(plugin.instance.api)) {
|
|
199
295
|
await this._initApi(plugin);
|
|
200
296
|
}
|
|
201
|
-
if (!
|
|
297
|
+
if (!(0, lodash_1.isEmpty)(plugin.instance.authenticators)) {
|
|
202
298
|
this._initAuthenticators(plugin);
|
|
203
299
|
}
|
|
204
|
-
if (!
|
|
300
|
+
if (!(0, lodash_1.isEmpty)(plugin.instance.strategies)) {
|
|
205
301
|
this._initStrategies(plugin);
|
|
206
302
|
}
|
|
207
|
-
if (!
|
|
303
|
+
if (!(0, lodash_1.isEmpty)(plugin.instance.hooks)) {
|
|
208
304
|
this._initHooks(plugin);
|
|
209
305
|
}
|
|
210
|
-
if (!
|
|
306
|
+
if (!(0, lodash_1.isEmpty)(plugin.instance.pipes)) {
|
|
211
307
|
this._initPipes(plugin);
|
|
212
308
|
}
|
|
213
309
|
debug("[%s] plugin started", plugin.name);
|
|
214
310
|
if (!plugin.application) {
|
|
215
311
|
this.loadedPlugins.push(plugin.name);
|
|
216
312
|
}
|
|
217
|
-
if (!
|
|
218
|
-
|
|
313
|
+
if (!(0, lodash_1.isEmpty)(plugin.instance.imports)) {
|
|
314
|
+
(0, lodash_1.merge)(defaultImports, plugin.instance.imports);
|
|
219
315
|
}
|
|
220
316
|
return null;
|
|
221
317
|
});
|
|
@@ -230,7 +326,7 @@ class PluginsManager {
|
|
|
230
326
|
* @returns {string[]}
|
|
231
327
|
*/
|
|
232
328
|
getStrategyFields(strategyName) {
|
|
233
|
-
return this.
|
|
329
|
+
return this.getStrategy(strategyName).strategy.config.fields || [];
|
|
234
330
|
}
|
|
235
331
|
/**
|
|
236
332
|
* @param {string} strategyName
|
|
@@ -238,8 +334,10 @@ class PluginsManager {
|
|
|
238
334
|
* @returns {boolean}
|
|
239
335
|
*/
|
|
240
336
|
hasStrategyMethod(strategyName, methodName) {
|
|
241
|
-
const strategy =
|
|
242
|
-
|
|
337
|
+
const strategy = (0, safeObject_1.has)(this.strategies, strategyName)
|
|
338
|
+
? this.strategies[strategyName]
|
|
339
|
+
: undefined;
|
|
340
|
+
return strategy !== undefined && (0, safeObject_1.has)(strategy.methods, methodName);
|
|
243
341
|
}
|
|
244
342
|
/**
|
|
245
343
|
* @param {string} strategyName
|
|
@@ -247,7 +345,7 @@ class PluginsManager {
|
|
|
247
345
|
* @returns {function}
|
|
248
346
|
*/
|
|
249
347
|
getStrategyMethod(strategyName, methodName) {
|
|
250
|
-
return this.
|
|
348
|
+
return this.getStrategy(strategyName).methods[methodName];
|
|
251
349
|
}
|
|
252
350
|
/**
|
|
253
351
|
* Returns the list of registered passport strategies
|
|
@@ -266,51 +364,50 @@ class PluginsManager {
|
|
|
266
364
|
*/
|
|
267
365
|
validateStrategy(pluginName, strategyName, strategy) {
|
|
268
366
|
const errorPrefix = `[${pluginName}] Strategy ${strategyName}:`;
|
|
269
|
-
if (!isPlainObject(strategy)) {
|
|
367
|
+
if (!(0, safeObject_1.isPlainObject)(strategy)) {
|
|
270
368
|
throw strategyError.get("invalid_description", errorPrefix, strategy);
|
|
271
369
|
}
|
|
272
|
-
if (!isPlainObject(strategy.methods)) {
|
|
370
|
+
if (!(0, safeObject_1.isPlainObject)(strategy.methods)) {
|
|
273
371
|
throw strategyError.get("invalid_methods", errorPrefix, strategy.methods);
|
|
274
372
|
}
|
|
275
|
-
const plugin = this.
|
|
373
|
+
const plugin = this.getPlugin(pluginName);
|
|
276
374
|
// required methods check
|
|
277
375
|
["exists", "create", "update", "delete", "validate", "verify"].forEach((methodName) => {
|
|
278
|
-
if (!
|
|
376
|
+
if (!(0, lodash_1.isString)(strategy.methods[methodName])) {
|
|
279
377
|
throw strategyError.get("invalid_method_type", errorPrefix, methodName, strategy.methods[methodName]);
|
|
280
378
|
}
|
|
281
|
-
if (!
|
|
379
|
+
if (!(0, lodash_1.isFunction)(plugin.instance[strategy.methods[methodName]])) {
|
|
282
380
|
throw strategyError.get("missing_method_function", errorPrefix, strategy.methods[methodName]);
|
|
283
381
|
}
|
|
284
382
|
});
|
|
285
383
|
// optional methods check
|
|
286
384
|
["getInfo", "getById", "afterRegister"].forEach((name) => {
|
|
287
385
|
const optionalMethodName = strategy.methods[name];
|
|
288
|
-
if (!
|
|
289
|
-
if (!
|
|
386
|
+
if (!(0, lodash_1.isNil)(optionalMethodName)) {
|
|
387
|
+
if (!(0, lodash_1.isString)(optionalMethodName)) {
|
|
290
388
|
throw strategyError.get("invalid_method_type", errorPrefix, name, optionalMethodName);
|
|
291
389
|
}
|
|
292
|
-
if (!
|
|
390
|
+
if (!(0, lodash_1.isFunction)(plugin.instance[optionalMethodName])) {
|
|
293
391
|
throw strategyError.get("missing_method_function", errorPrefix, optionalMethodName);
|
|
294
392
|
}
|
|
295
393
|
}
|
|
296
394
|
});
|
|
297
|
-
if (!isPlainObject(strategy.config)) {
|
|
395
|
+
if (!(0, safeObject_1.isPlainObject)(strategy.config)) {
|
|
298
396
|
throw strategyError.get("invalid_config", errorPrefix, strategy.config);
|
|
299
397
|
}
|
|
300
398
|
if (typeof strategy.config.authenticator !== "string") {
|
|
301
399
|
throw strategyError.get("invalid_authenticator", errorPrefix, strategy.config.authenticator);
|
|
302
400
|
}
|
|
303
|
-
else if (!this.authenticators[pluginName]
|
|
304
|
-
!this.authenticators[pluginName][strategy.config.authenticator]) {
|
|
401
|
+
else if (!this.authenticators[pluginName]?.[strategy.config.authenticator]) {
|
|
305
402
|
throw strategyError.get("unknown_authenticator", errorPrefix, strategy.config.authenticator);
|
|
306
403
|
}
|
|
307
404
|
for (const optionName of ["strategyOptions", "authenticateOptions"]) {
|
|
308
405
|
const options = strategy.config[optionName];
|
|
309
|
-
if (!
|
|
406
|
+
if (!(0, lodash_1.isNil)(options) && !(0, safeObject_1.isPlainObject)(options)) {
|
|
310
407
|
throw strategyError.get("invalid_option", errorPrefix, optionName, options);
|
|
311
408
|
}
|
|
312
409
|
}
|
|
313
|
-
if (!
|
|
410
|
+
if (!(0, lodash_1.isNil)(strategy.config.fields) &&
|
|
314
411
|
!Array.isArray(strategy.config.fields)) {
|
|
315
412
|
throw strategyError.get("invalid_fields", errorPrefix, strategy.config.fields);
|
|
316
413
|
}
|
|
@@ -331,11 +428,19 @@ class PluginsManager {
|
|
|
331
428
|
? plugin.config.pipeWarnTime
|
|
332
429
|
: this.config.common.pipeWarnTime;
|
|
333
430
|
const wrapper = (...data) => {
|
|
334
|
-
const
|
|
431
|
+
const startedAt = warnDelay ? Date.now() : null;
|
|
335
432
|
const callback = data.pop();
|
|
433
|
+
// The pipe runner always calls a registered pipe with a trailing
|
|
434
|
+
// callback — the same narrowing `wrapStrategyVerify` makes, and the
|
|
435
|
+
// same branch that cannot be taken.
|
|
436
|
+
if (!isPluginMethod(callback)) {
|
|
437
|
+
return;
|
|
438
|
+
}
|
|
336
439
|
const cb = (error, result) => {
|
|
337
|
-
|
|
338
|
-
|
|
440
|
+
// `startedAt !== null` is `warnDelay` truthy, said in the form that
|
|
441
|
+
// proves there is a timestamp to subtract.
|
|
442
|
+
if (startedAt !== null) {
|
|
443
|
+
const elapsed = Date.now() - startedAt;
|
|
339
444
|
if (elapsed > warnDelay) {
|
|
340
445
|
this.logger.warn(`${plugin.logPrefix} pipe for event '${event}' is slow (${elapsed}ms)`);
|
|
341
446
|
}
|
|
@@ -344,10 +449,7 @@ class PluginsManager {
|
|
|
344
449
|
};
|
|
345
450
|
try {
|
|
346
451
|
const pipeResponse = data.length === 0 ? handler(null, cb) : handler(...data, cb);
|
|
347
|
-
if (
|
|
348
|
-
pipeResponse !== null &&
|
|
349
|
-
typeof pipeResponse.then === "function" &&
|
|
350
|
-
typeof pipeResponse.catch === "function") {
|
|
452
|
+
if (isThenable(pipeResponse)) {
|
|
351
453
|
pipeResponse
|
|
352
454
|
.then((result) => {
|
|
353
455
|
cb(null, result);
|
|
@@ -357,9 +459,7 @@ class PluginsManager {
|
|
|
357
459
|
}
|
|
358
460
|
}
|
|
359
461
|
catch (error) {
|
|
360
|
-
cb(error
|
|
361
|
-
? error
|
|
362
|
-
: runtimeError.getFrom(error, "unexpected_error", error.message));
|
|
462
|
+
cb(asKuzzleError(error));
|
|
363
463
|
}
|
|
364
464
|
};
|
|
365
465
|
return global.kuzzle.registerPluginPipe(event, wrapper);
|
|
@@ -379,8 +479,7 @@ class PluginsManager {
|
|
|
379
479
|
* registration fails
|
|
380
480
|
*/
|
|
381
481
|
registerStrategy(pluginName, strategyName, strategy) {
|
|
382
|
-
|
|
383
|
-
const plugin = this._plugins.get(pluginName.toLowerCase());
|
|
482
|
+
const plugin = this.getPlugin(pluginName);
|
|
384
483
|
// only add the strategy to the strategies object if the init method
|
|
385
484
|
// has not been called
|
|
386
485
|
if (!plugin.initCalled) {
|
|
@@ -389,7 +488,7 @@ class PluginsManager {
|
|
|
389
488
|
return;
|
|
390
489
|
}
|
|
391
490
|
this.validateStrategy(plugin.name, strategyName, strategy);
|
|
392
|
-
if (has(this.strategies, strategyName)) {
|
|
491
|
+
if ((0, safeObject_1.has)(this.strategies, strategyName)) {
|
|
393
492
|
this.unregisterStrategy(plugin.name, strategyName);
|
|
394
493
|
}
|
|
395
494
|
const methods = {};
|
|
@@ -399,14 +498,11 @@ class PluginsManager {
|
|
|
399
498
|
for (const methodName of Object.keys(strategy.methods).filter((name) => name !== "verify")) {
|
|
400
499
|
methods[methodName] = async (...args) => {
|
|
401
500
|
try {
|
|
402
|
-
const boundFunction = plugin.instance
|
|
501
|
+
const boundFunction = bindPluginMethod(plugin.instance, strategy.methods[methodName]);
|
|
403
502
|
return await boundFunction(...args);
|
|
404
503
|
}
|
|
405
504
|
catch (error) {
|
|
406
|
-
|
|
407
|
-
throw error;
|
|
408
|
-
}
|
|
409
|
-
throw runtimeError.getFrom(error, "unexpected_error", error.message);
|
|
505
|
+
throw asKuzzleError(error);
|
|
410
506
|
}
|
|
411
507
|
};
|
|
412
508
|
}
|
|
@@ -414,7 +510,7 @@ class PluginsManager {
|
|
|
414
510
|
...strategy.config.strategyOptions,
|
|
415
511
|
passReqToCallback: true,
|
|
416
512
|
};
|
|
417
|
-
const verifyAdapter = this.wrapStrategyVerify(plugin.logPrefix, strategyName, plugin.instance
|
|
513
|
+
const verifyAdapter = this.wrapStrategyVerify(plugin.logPrefix, strategyName, bindPluginMethod(plugin.instance, strategy.methods.verify));
|
|
418
514
|
try {
|
|
419
515
|
const Ctor = this.authenticators[plugin.name][strategy.config.authenticator], instance = new Ctor(opts, verifyAdapter);
|
|
420
516
|
this.strategies[strategyName] = { methods, owner: plugin.name, strategy };
|
|
@@ -424,7 +520,8 @@ class PluginsManager {
|
|
|
424
520
|
}
|
|
425
521
|
}
|
|
426
522
|
catch (e) {
|
|
427
|
-
|
|
523
|
+
const cause = (0, thrown_1.causeOf)(e);
|
|
524
|
+
throw strategyError.getFrom(cause, "failed_registration", strategyName, cause.message);
|
|
428
525
|
}
|
|
429
526
|
}
|
|
430
527
|
/**
|
|
@@ -453,90 +550,70 @@ class PluginsManager {
|
|
|
453
550
|
*/
|
|
454
551
|
_initPipes(plugin) {
|
|
455
552
|
const methodsList = getMethods(plugin.instance);
|
|
456
|
-
|
|
553
|
+
// `?? {}`: every member of a plugin's object is optional, and `init`
|
|
554
|
+
// guards each of these loops with an `isEmpty` the compiler cannot read.
|
|
555
|
+
for (const [event, fn] of Object.entries(plugin.instance.pipes ?? {})) {
|
|
457
556
|
const list = Array.isArray(fn) ? fn : [fn];
|
|
458
557
|
for (const target of list) {
|
|
459
|
-
|
|
460
|
-
typeof plugin.instance[target] !== "function") {
|
|
461
|
-
const message = typeof target === "string" ? didYouMean(target, methodsList) : "";
|
|
462
|
-
throw assertionError.get("invalid_pipe", event, target, message);
|
|
463
|
-
}
|
|
464
|
-
let handler = target;
|
|
465
|
-
if (typeof target === "string") {
|
|
466
|
-
// @deprecated - warn about using a string representing an instance method
|
|
467
|
-
plugin.printDeprecation("Defining pipe handler using a string is deprecated. Pass a function instead.");
|
|
468
|
-
handler = plugin.instance[target].bind(plugin.instance);
|
|
469
|
-
}
|
|
470
|
-
// if the function handler is a plugin instance method,
|
|
471
|
-
// bound the context to the plugin instance
|
|
472
|
-
if (target.name && typeof plugin.instance[target.name] === "function") {
|
|
473
|
-
handler = target.bind(plugin.instance);
|
|
474
|
-
}
|
|
558
|
+
const handler = this.resolveEventHandler(plugin, event, target, methodsList, "invalid_pipe", "Defining pipe handler using a string is deprecated. Pass a function instead.");
|
|
475
559
|
this.registerPipe(plugin, event, handler);
|
|
476
560
|
}
|
|
477
561
|
}
|
|
478
562
|
}
|
|
563
|
+
/**
|
|
564
|
+
* Resolves one pipe or hook target — a function, or the name of a plugin
|
|
565
|
+
* method — into the handler to register.
|
|
566
|
+
*
|
|
567
|
+
* Shared by `_initPipes` and `_initHooks`, which carried the same twenty
|
|
568
|
+
* lines with two words changed. The `.js` → `.ts` rename re-scored both as
|
|
569
|
+
* new code, so the gate asked for the deduplication the files already wanted.
|
|
570
|
+
*
|
|
571
|
+
* @throws {PluginImplementationError} when the target names nothing callable
|
|
572
|
+
*/
|
|
573
|
+
resolveEventHandler(plugin, event, target, methodsList, errorId, deprecation) {
|
|
574
|
+
if (typeof target !== "function" &&
|
|
575
|
+
typeof plugin.instance[target] !== "function") {
|
|
576
|
+
const message = typeof target === "string" ? (0, didYouMean_1.default)(target, methodsList) : "";
|
|
577
|
+
throw assertionError.get(errorId, event, target, message);
|
|
578
|
+
}
|
|
579
|
+
// @deprecated - warn about using a string representing an instance method
|
|
580
|
+
if (typeof target === "string") {
|
|
581
|
+
plugin.printDeprecation(deprecation);
|
|
582
|
+
return bindPluginMethod(plugin.instance, target);
|
|
583
|
+
}
|
|
584
|
+
// if the function handler is a plugin instance method,
|
|
585
|
+
// bound the context to the plugin instance
|
|
586
|
+
if (target.name && typeof plugin.instance[target.name] === "function") {
|
|
587
|
+
return target.bind(plugin.instance);
|
|
588
|
+
}
|
|
589
|
+
return target;
|
|
590
|
+
}
|
|
479
591
|
/**
|
|
480
592
|
* @param {object} plugin
|
|
481
593
|
*/
|
|
482
594
|
_initHooks(plugin) {
|
|
483
595
|
const methodsList = getMethods(plugin.instance);
|
|
484
|
-
for (const [event, fn] of Object.entries(plugin.instance.hooks)) {
|
|
596
|
+
for (const [event, fn] of Object.entries(plugin.instance.hooks ?? {})) {
|
|
485
597
|
const list = Array.isArray(fn) ? fn : [fn];
|
|
486
598
|
for (const target of list) {
|
|
487
|
-
if (typeof target !== "function" &&
|
|
488
|
-
typeof plugin.instance[target] !== "function") {
|
|
489
|
-
const message = typeof target === "string" ? didYouMean(target, methodsList) : "";
|
|
490
|
-
throw assertionError.get("invalid_hook", event, target, message);
|
|
491
|
-
}
|
|
492
599
|
debug('[%s] register hook on event "%s"', plugin.name, event);
|
|
493
|
-
|
|
494
|
-
// @deprecated - warn about using a string representing an instance method
|
|
495
|
-
if (typeof target === "string") {
|
|
496
|
-
plugin.printDeprecation("Defining hook handler using a string is deprecated. Pass a function instead.");
|
|
497
|
-
handler = plugin.instance[target].bind(plugin.instance);
|
|
498
|
-
}
|
|
499
|
-
// if the function handler is a plugin instance method,
|
|
500
|
-
// bound the context to the plugin instance
|
|
501
|
-
if (target.name && typeof plugin.instance[target.name] === "function") {
|
|
502
|
-
handler = target.bind(plugin.instance);
|
|
503
|
-
}
|
|
600
|
+
const handler = this.resolveEventHandler(plugin, event, target, methodsList, "invalid_hook", "Defining hook handler using a string is deprecated. Pass a function instead.");
|
|
504
601
|
global.kuzzle.registerPluginHook(plugin.name, event, handler);
|
|
505
602
|
}
|
|
506
603
|
}
|
|
507
604
|
}
|
|
508
605
|
async _initApi(plugin) {
|
|
509
|
-
for (const [controller, definition] of Object.entries(plugin.instance.api)) {
|
|
606
|
+
for (const [controller, definition] of Object.entries(plugin.instance.api ?? {})) {
|
|
510
607
|
debug("[%s][%s] starting api controller registration", plugin.name, controller);
|
|
511
608
|
if (await global.kuzzle.ask("kuzzle:api:funnel:controller:isNative", controller)) {
|
|
512
609
|
throw assertionError.get("invalid_controller_definition", controller, "Native controllers cannot be overriden");
|
|
513
610
|
}
|
|
514
|
-
|
|
611
|
+
plugin_1.default.checkControllerDefinition(controller, definition);
|
|
515
612
|
for (const [action, actionDefinition] of Object.entries(definition.actions)) {
|
|
516
|
-
|
|
517
|
-
if (!apiController) {
|
|
518
|
-
apiController = new BaseController();
|
|
519
|
-
this.controllers.set(controller, apiController);
|
|
520
|
-
}
|
|
521
|
-
let handler = actionDefinition.handler;
|
|
522
|
-
// if the function handler is a plugin instance method,
|
|
523
|
-
// bind the context to the plugin instance
|
|
524
|
-
if (handler.name &&
|
|
525
|
-
typeof plugin.instance[handler.name] === "function") {
|
|
526
|
-
handler = handler.bind(plugin.instance);
|
|
527
|
-
}
|
|
528
|
-
apiController._addAction(action, handler);
|
|
529
|
-
const httpRoutes = actionDefinition.http || [];
|
|
530
|
-
// Define default HTTP route if none have been provided
|
|
531
|
-
if (httpRoutes.length === 0) {
|
|
532
|
-
httpRoutes.push({
|
|
533
|
-
path: `${Inflector.kebabCase(controller)}/${Inflector.kebabCase(action)}`,
|
|
534
|
-
verb: "get",
|
|
535
|
-
});
|
|
536
|
-
}
|
|
613
|
+
const httpRoutes = this.registerApiAction(plugin, controller, action, actionDefinition);
|
|
537
614
|
for (const httpRoute of httpRoutes) {
|
|
538
615
|
debug('[%s] binding HTTP route "%s" to controller "%s"', plugin.name, httpRoute.path, controller);
|
|
539
|
-
const routePath = httpRoute.path.
|
|
616
|
+
const routePath = httpRoute.path.startsWith("/")
|
|
540
617
|
? httpRoute.path
|
|
541
618
|
: `/_/${httpRoute.path}`;
|
|
542
619
|
this.routes.push({
|
|
@@ -558,39 +635,23 @@ class PluginsManager {
|
|
|
558
635
|
*/
|
|
559
636
|
_initControllers(plugin) {
|
|
560
637
|
// @deprecated - warn about using the obsolete "controllers" object
|
|
561
|
-
if (!
|
|
638
|
+
if (!(0, lodash_1.isEmpty)(plugin.instance.controllers)) {
|
|
562
639
|
plugin.printDeprecation('Defining controllers using the "controllers" object is deprecated. You should use the "api" object instead.');
|
|
563
640
|
}
|
|
564
|
-
|
|
641
|
+
const legacyControllers = plugin.instance.controllers ?? {};
|
|
642
|
+
for (const controller of Object.keys(legacyControllers)) {
|
|
565
643
|
debug("[%s][%s] starting controller registration", plugin.name, controller);
|
|
566
644
|
const methodsList = getMethods(plugin.instance);
|
|
567
645
|
const controllerName = `${plugin.name}/${controller}`;
|
|
568
|
-
const definition =
|
|
646
|
+
const definition = legacyControllers[controller];
|
|
569
647
|
const errorControllerPrefix = `Unable to inject controller "${controller}" from plugin "${plugin.name}":`;
|
|
570
|
-
if (!isPlainObject(definition)) {
|
|
648
|
+
if (!(0, safeObject_1.isPlainObject)(definition)) {
|
|
571
649
|
// @todo deprecate all those errors and use plugin.assert.invalid_controller_definition
|
|
572
650
|
throw controllerError.get("invalid_description", errorControllerPrefix, typeof definition);
|
|
573
651
|
}
|
|
574
652
|
for (const action of Object.keys(definition)) {
|
|
575
653
|
debug("[%s][%s][%s] starting action controller registration", plugin.name, controller, action);
|
|
576
|
-
|
|
577
|
-
typeof plugin.instance[definition[action]] !== "function") {
|
|
578
|
-
const suggestion = typeof definition[action] === "string"
|
|
579
|
-
? didYouMean(definition[action], methodsList)
|
|
580
|
-
: "";
|
|
581
|
-
throw controllerError.get("invalid_action", errorControllerPrefix, controller, action, suggestion);
|
|
582
|
-
}
|
|
583
|
-
let apiController = this.controllers.get(controllerName);
|
|
584
|
-
if (!apiController) {
|
|
585
|
-
apiController = new BaseController();
|
|
586
|
-
this.controllers.set(controllerName, apiController);
|
|
587
|
-
}
|
|
588
|
-
if (typeof definition[action] === "function") {
|
|
589
|
-
apiController._addAction(action, definition[action]);
|
|
590
|
-
}
|
|
591
|
-
else {
|
|
592
|
-
apiController._addAction(action, plugin.instance[definition[action]].bind(plugin.instance));
|
|
593
|
-
}
|
|
654
|
+
this.registerLegacyAction(plugin, definition[action], { action, controller, controllerName, errorControllerPrefix }, methodsList);
|
|
594
655
|
}
|
|
595
656
|
}
|
|
596
657
|
const httpVerbs = [
|
|
@@ -603,34 +664,21 @@ class PluginsManager {
|
|
|
603
664
|
"options",
|
|
604
665
|
];
|
|
605
666
|
const routeProperties = ["verb", "url", "controller", "action", "path"];
|
|
606
|
-
const controllerNames = Object.keys(
|
|
667
|
+
const controllerNames = Object.keys(legacyControllers);
|
|
607
668
|
// @deprecated - warn about using the obsolete "routes" object
|
|
608
|
-
if (!
|
|
669
|
+
if (!(0, lodash_1.isEmpty)(plugin.instance.routes)) {
|
|
609
670
|
plugin.printDeprecation('Defining routes using the "routes" object is deprecated. You should use the "api" object instead.');
|
|
610
671
|
}
|
|
611
672
|
for (const route of plugin.instance.routes || []) {
|
|
612
673
|
const controller = `${plugin.name}/${route.controller}`;
|
|
613
674
|
const errorRoutePrefix = `Unable to inject API route "${JSON.stringify(route)}" from plugin "${plugin.name}":`;
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
}
|
|
622
|
-
}
|
|
623
|
-
const apiController = this.controllers.get(controller);
|
|
624
|
-
if (!apiController) {
|
|
625
|
-
throw controllerError.get("undefined_controller", errorRoutePrefix, route.controller, didYouMean(route.controller, controllerNames));
|
|
626
|
-
}
|
|
627
|
-
if (!apiController._isAction(route.action)) {
|
|
628
|
-
const actionNames = Array.from(apiController._actions);
|
|
629
|
-
throw controllerError.get("undefined_action", errorRoutePrefix, route.action, didYouMean(route.action, actionNames));
|
|
630
|
-
}
|
|
631
|
-
if (httpVerbs.indexOf(route.verb.toLowerCase()) === -1) {
|
|
632
|
-
throw controllerError.get("unsupported_verb", errorRoutePrefix, httpVerbs.join(", "), didYouMean(route.verb, httpVerbs));
|
|
633
|
-
}
|
|
675
|
+
this.checkLegacyRoute(route, {
|
|
676
|
+
controller,
|
|
677
|
+
controllerNames,
|
|
678
|
+
errorRoutePrefix,
|
|
679
|
+
httpVerbs,
|
|
680
|
+
routeProperties,
|
|
681
|
+
});
|
|
634
682
|
// @deprecated route.url is deprecated
|
|
635
683
|
if (route.url) {
|
|
636
684
|
plugin.printDeprecation('Usage of "url" property for routes is deprecated. Use "path" instead.');
|
|
@@ -655,13 +703,116 @@ class PluginsManager {
|
|
|
655
703
|
});
|
|
656
704
|
}
|
|
657
705
|
}
|
|
706
|
+
/**
|
|
707
|
+
* Registers one action of the `api` object and answers the HTTP routes to
|
|
708
|
+
* bind for it — the declared ones, or the single default route built from the
|
|
709
|
+
* controller and action names.
|
|
710
|
+
*
|
|
711
|
+
* Lifted verbatim out of `_initApi` for the same gate reason as its siblings.
|
|
712
|
+
*/
|
|
713
|
+
registerApiAction(plugin, controller, action, actionDefinition) {
|
|
714
|
+
let apiController = this.controllers.get(controller);
|
|
715
|
+
if (!apiController) {
|
|
716
|
+
apiController = new baseController_1.BaseController();
|
|
717
|
+
this.controllers.set(controller, apiController);
|
|
718
|
+
}
|
|
719
|
+
let handler = actionDefinition.handler;
|
|
720
|
+
// if the function handler is a plugin instance method,
|
|
721
|
+
// bind the context to the plugin instance
|
|
722
|
+
if (handler.name && typeof plugin.instance[handler.name] === "function") {
|
|
723
|
+
handler = handler.bind(plugin.instance);
|
|
724
|
+
}
|
|
725
|
+
apiController._addAction(action, handler);
|
|
726
|
+
const httpRoutes = actionDefinition.http || [];
|
|
727
|
+
// Define default HTTP route if none have been provided
|
|
728
|
+
if (httpRoutes.length === 0) {
|
|
729
|
+
httpRoutes.push({
|
|
730
|
+
path: `${Inflector_1.Inflector.kebabCase(controller)}/${Inflector_1.Inflector.kebabCase(action)}`,
|
|
731
|
+
verb: "get",
|
|
732
|
+
});
|
|
733
|
+
}
|
|
734
|
+
return httpRoutes;
|
|
735
|
+
}
|
|
736
|
+
/**
|
|
737
|
+
* Checks one entry of the deprecated `routes` object: its properties, the
|
|
738
|
+
* controller and action it names, and its HTTP verb.
|
|
739
|
+
*
|
|
740
|
+
* Lifted verbatim out of `_initControllers`, second half of the same
|
|
741
|
+
* gate-driven split as `registerLegacyAction`.
|
|
742
|
+
*
|
|
743
|
+
* @throws {PluginImplementationError}
|
|
744
|
+
*/
|
|
745
|
+
checkLegacyRoute(route, names) {
|
|
746
|
+
const { controller, controllerNames, errorRoutePrefix, httpVerbs, routeProperties, } = names;
|
|
747
|
+
for (const key of Object.keys(route)) {
|
|
748
|
+
if (!routeProperties.includes(key)) {
|
|
749
|
+
throw controllerError.get("unexpected_route_property", errorRoutePrefix, key, (0, didYouMean_1.default)(key, routeProperties));
|
|
750
|
+
}
|
|
751
|
+
if (typeof route[key] !== "string" ||
|
|
752
|
+
(route[key].length === 0 && key !== "url")) {
|
|
753
|
+
throw controllerError.get("invalid_route_property", errorRoutePrefix, key);
|
|
754
|
+
}
|
|
755
|
+
}
|
|
756
|
+
const apiController = this.controllers.get(controller);
|
|
757
|
+
if (!apiController) {
|
|
758
|
+
throw controllerError.get("undefined_controller", errorRoutePrefix, route.controller, (0, didYouMean_1.default)(route.controller, controllerNames));
|
|
759
|
+
}
|
|
760
|
+
if (!apiController._isAction(route.action)) {
|
|
761
|
+
const actionNames = Array.from(apiController._actions);
|
|
762
|
+
throw controllerError.get("undefined_action", errorRoutePrefix, route.action, (0, didYouMean_1.default)(route.action, actionNames));
|
|
763
|
+
}
|
|
764
|
+
if (!httpVerbs.includes(route.verb.toLowerCase())) {
|
|
765
|
+
throw controllerError.get("unsupported_verb", errorRoutePrefix, httpVerbs.join(", "), (0, didYouMean_1.default)(route.verb, httpVerbs));
|
|
766
|
+
}
|
|
767
|
+
}
|
|
768
|
+
/**
|
|
769
|
+
* Registers one action of the pre-Kaaf `controllers` object: a handler given
|
|
770
|
+
* either as a function or as the name of a plugin method.
|
|
771
|
+
*
|
|
772
|
+
* Lifted verbatim out of `_initControllers`, whose cognitive complexity the
|
|
773
|
+
* `.js` → `.ts` rename re-scored as new code.
|
|
774
|
+
*
|
|
775
|
+
* @throws {PluginImplementationError} when the target names nothing callable
|
|
776
|
+
*/
|
|
777
|
+
registerLegacyAction(plugin,
|
|
778
|
+
/**
|
|
779
|
+
* Unvalidated: it arrives from the plugin's own `controllers` object, which
|
|
780
|
+
* is `JSONObject`. The first check below is what makes the declared shape
|
|
781
|
+
* true, and is the reason this parameter may claim it.
|
|
782
|
+
*/
|
|
783
|
+
target, names, methodsList) {
|
|
784
|
+
const { action, controller, controllerName, errorControllerPrefix } = names;
|
|
785
|
+
// Nested rather than one flat condition: what the throw leaves standing
|
|
786
|
+
// is "a function, or a name that resolves to one", and written this way
|
|
787
|
+
// that is what the compiler carries down to the two branches below —
|
|
788
|
+
// where the `null` the previous spelling introduced had to be asserted
|
|
789
|
+
// away again.
|
|
790
|
+
if (typeof target !== "function") {
|
|
791
|
+
if (typeof target !== "string" ||
|
|
792
|
+
typeof plugin.instance[target] !== "function") {
|
|
793
|
+
const suggestion = typeof target === "string" ? (0, didYouMean_1.default)(target, methodsList) : "";
|
|
794
|
+
throw controllerError.get("invalid_action", errorControllerPrefix, controller, action, suggestion);
|
|
795
|
+
}
|
|
796
|
+
}
|
|
797
|
+
let apiController = this.controllers.get(controllerName);
|
|
798
|
+
if (!apiController) {
|
|
799
|
+
apiController = new baseController_1.BaseController();
|
|
800
|
+
this.controllers.set(controllerName, apiController);
|
|
801
|
+
}
|
|
802
|
+
if (typeof target === "function") {
|
|
803
|
+
apiController._addAction(action, target);
|
|
804
|
+
}
|
|
805
|
+
else {
|
|
806
|
+
apiController._addAction(action, bindPluginMethod(plugin.instance, target));
|
|
807
|
+
}
|
|
808
|
+
}
|
|
658
809
|
/**
|
|
659
810
|
* @param {object} plugin
|
|
660
811
|
* @throws {PluginImplementationError} If strategies registration fails
|
|
661
812
|
*/
|
|
662
813
|
_initStrategies(plugin) {
|
|
663
|
-
if (!isPlainObject(plugin.instance.strategies) ||
|
|
664
|
-
|
|
814
|
+
if (!(0, safeObject_1.isPlainObject)(plugin.instance.strategies) ||
|
|
815
|
+
(0, lodash_1.isEmpty)(plugin.instance.strategies)) {
|
|
665
816
|
throw strategyError.get("invalid_definition", plugin.logPrefix);
|
|
666
817
|
}
|
|
667
818
|
for (const name of Object.keys(plugin.instance.strategies)) {
|
|
@@ -673,7 +824,7 @@ class PluginsManager {
|
|
|
673
824
|
* @throws {PluginImplementationError} If strategies registration fails
|
|
674
825
|
*/
|
|
675
826
|
_initAuthenticators(plugin) {
|
|
676
|
-
if (!isPlainObject(plugin.instance.authenticators)) {
|
|
827
|
+
if (!(0, safeObject_1.isPlainObject)(plugin.instance.authenticators)) {
|
|
677
828
|
throw kerror.get("plugin", "authenticators", "not_an_object", plugin.logPrefix);
|
|
678
829
|
}
|
|
679
830
|
for (const authenticator of Object.keys(plugin.instance.authenticators)) {
|
|
@@ -681,7 +832,7 @@ class PluginsManager {
|
|
|
681
832
|
throw kerror.get("plugin", "authenticators", "invalid_authenticator", plugin.logPrefix, authenticator);
|
|
682
833
|
}
|
|
683
834
|
}
|
|
684
|
-
this.authenticators[plugin.name] =
|
|
835
|
+
this.authenticators[plugin.name] = { ...plugin.instance.authenticators };
|
|
685
836
|
}
|
|
686
837
|
/**
|
|
687
838
|
* Load detected plugins in memory
|
|
@@ -692,7 +843,7 @@ class PluginsManager {
|
|
|
692
843
|
const loadedPlugins = new Map();
|
|
693
844
|
// first load plugins from Backend.plugin.use
|
|
694
845
|
for (const [name, { plugin: instance, options }] of Object.entries(plugins)) {
|
|
695
|
-
const plugin = new
|
|
846
|
+
const plugin = new plugin_1.default(instance, { name, ...options });
|
|
696
847
|
// the plugin cluster can be loaded in the startup script
|
|
697
848
|
// and we need the manifest
|
|
698
849
|
plugin.manifest = plugin.manifest || options.manifest;
|
|
@@ -703,23 +854,26 @@ class PluginsManager {
|
|
|
703
854
|
loadedPlugins.set(plugin.name, plugin);
|
|
704
855
|
}
|
|
705
856
|
// then try to load plugins from the filesystem
|
|
706
|
-
if (!
|
|
857
|
+
if (!node_fs_1.default.existsSync(this.pluginsEnabledDir)) {
|
|
707
858
|
return loadedPlugins;
|
|
708
859
|
}
|
|
709
|
-
let pluginsPath
|
|
860
|
+
let pluginsPath;
|
|
710
861
|
try {
|
|
711
|
-
pluginsPath =
|
|
862
|
+
pluginsPath = node_fs_1.default
|
|
712
863
|
.readdirSync(this.pluginsEnabledDir)
|
|
713
|
-
.map((name) =>
|
|
714
|
-
.filter((filePath) =>
|
|
864
|
+
.map((name) => node_path_1.default.join(this.pluginsEnabledDir, name))
|
|
865
|
+
.filter((filePath) => node_fs_1.default.statSync(filePath).isDirectory());
|
|
715
866
|
}
|
|
716
867
|
catch (e) {
|
|
717
|
-
throw assertionError.get("invalid_plugins_dir", this.pluginsEnabledDir, e.message);
|
|
868
|
+
throw assertionError.get("invalid_plugins_dir", this.pluginsEnabledDir, (0, thrown_1.causeOf)(e).message);
|
|
718
869
|
}
|
|
719
870
|
debug("loading plugins: %a", pluginsPath);
|
|
720
871
|
for (const relativePluginPath of pluginsPath) {
|
|
721
|
-
const plugin =
|
|
722
|
-
|
|
872
|
+
const plugin = plugin_1.default.loadFromDirectory(relativePluginPath);
|
|
873
|
+
// `loadFromDirectory` has already read the name out of the manifest —
|
|
874
|
+
// `manifest.load()` throws `missing_name` rather than leave it unset —
|
|
875
|
+
// so this is the same string without two nullable dereferences.
|
|
876
|
+
plugin.init(plugin.name);
|
|
723
877
|
if (loadedPlugins.has(plugin.name)) {
|
|
724
878
|
throw assertionError.get("name_already_exists", plugin.name);
|
|
725
879
|
}
|
|
@@ -738,11 +892,16 @@ class PluginsManager {
|
|
|
738
892
|
wrapStrategyVerify(pluginName, strategyName, verifyMethod) {
|
|
739
893
|
const prefix = `${pluginName} Strategy ${strategyName}:`;
|
|
740
894
|
return async (...args) => {
|
|
741
|
-
const callback = args
|
|
895
|
+
const callback = args.at(-1);
|
|
896
|
+
// passport always calls the adapter with a trailing callback; the
|
|
897
|
+
// narrowing is what lets it be invoked, and the branch cannot be taken.
|
|
898
|
+
if (!isPluginMethod(callback)) {
|
|
899
|
+
return;
|
|
900
|
+
}
|
|
742
901
|
const ret = verifyMethod(...args.slice(0, -1));
|
|
743
902
|
// catching plugins returning non-thenable content
|
|
744
903
|
// @todo - with async/await we might consider allowing non-promise results
|
|
745
|
-
if (!
|
|
904
|
+
if (!hasThen(ret)) {
|
|
746
905
|
callback(strategyError.get("invalid_verify_return", prefix, ret));
|
|
747
906
|
return;
|
|
748
907
|
}
|
|
@@ -754,63 +913,141 @@ class PluginsManager {
|
|
|
754
913
|
callback(e);
|
|
755
914
|
return;
|
|
756
915
|
}
|
|
757
|
-
|
|
758
|
-
callback(null, result, { message: null });
|
|
759
|
-
return;
|
|
760
|
-
}
|
|
761
|
-
if (!isPlainObject(result)) {
|
|
762
|
-
callback(strategyError.get("invalid_verify_resolve", prefix));
|
|
763
|
-
return;
|
|
764
|
-
}
|
|
765
|
-
if (result.kuid !== null && result.kuid !== undefined) {
|
|
766
|
-
if (typeof result.kuid === "string") {
|
|
767
|
-
try {
|
|
768
|
-
const user = await global.kuzzle.ask("core:security:user:get", result.kuid);
|
|
769
|
-
callback(null, user);
|
|
770
|
-
}
|
|
771
|
-
catch (e) {
|
|
772
|
-
if (e.id === "security.user.not_found") {
|
|
773
|
-
callback(strategyError.get("unknown_kuid", prefix));
|
|
774
|
-
}
|
|
775
|
-
else {
|
|
776
|
-
callback(e);
|
|
777
|
-
}
|
|
778
|
-
}
|
|
779
|
-
return;
|
|
780
|
-
}
|
|
781
|
-
callback(strategyError.get("invalid_kuid", prefix, typeof result.kuid));
|
|
782
|
-
return;
|
|
783
|
-
}
|
|
784
|
-
let message;
|
|
785
|
-
if (result.message && typeof result.message === "string") {
|
|
786
|
-
message = result.message;
|
|
787
|
-
}
|
|
788
|
-
else {
|
|
789
|
-
message = `Unable to log in using the strategy "${strategyName}"`;
|
|
790
|
-
}
|
|
791
|
-
callback(null, false, { message });
|
|
916
|
+
await resolveVerifiedUser(result, prefix, strategyName, callback);
|
|
792
917
|
};
|
|
793
918
|
}
|
|
794
919
|
}
|
|
795
920
|
/**
|
|
796
|
-
*
|
|
921
|
+
* Turns what a strategy's `verify` resolved into the passport callback call it
|
|
922
|
+
* stands for: the authenticated user, an explicit refusal, or an error.
|
|
797
923
|
*
|
|
798
|
-
*
|
|
799
|
-
*
|
|
924
|
+
* Lifted verbatim out of `wrapStrategyVerify`, whose cognitive complexity the
|
|
925
|
+
* `.js` → `.ts` rename re-scored as new code.
|
|
800
926
|
*/
|
|
927
|
+
async function resolveVerifiedUser(result, prefix, strategyName, callback) {
|
|
928
|
+
if (result === false) {
|
|
929
|
+
callback(null, result, { message: null });
|
|
930
|
+
return;
|
|
931
|
+
}
|
|
932
|
+
if (!(0, safeObject_1.isPlainObject)(result)) {
|
|
933
|
+
callback(strategyError.get("invalid_verify_resolve", prefix));
|
|
934
|
+
return;
|
|
935
|
+
}
|
|
936
|
+
if (result.kuid !== null && result.kuid !== undefined) {
|
|
937
|
+
await resolveKuid(result.kuid, prefix, callback);
|
|
938
|
+
return;
|
|
939
|
+
}
|
|
940
|
+
const message = typeof result.message === "string" && result.message
|
|
941
|
+
? result.message
|
|
942
|
+
: `Unable to log in using the strategy "${strategyName}"`;
|
|
943
|
+
callback(null, false, { message });
|
|
944
|
+
}
|
|
945
|
+
/**
|
|
946
|
+
* Loads the user a strategy named by `kuid` and hands it to the passport
|
|
947
|
+
* callback, turning a missing user into the dedicated `unknown_kuid` error.
|
|
948
|
+
*
|
|
949
|
+
* Split out of `resolveVerifiedUser` to keep both under the cognitive
|
|
950
|
+
* complexity ceiling the `.js` → `.ts` rename re-scores as new code.
|
|
951
|
+
*/
|
|
952
|
+
async function resolveKuid(kuid, prefix, callback) {
|
|
953
|
+
if (typeof kuid !== "string") {
|
|
954
|
+
callback(strategyError.get("invalid_kuid", prefix, typeof kuid));
|
|
955
|
+
return;
|
|
956
|
+
}
|
|
957
|
+
try {
|
|
958
|
+
const user = await global.kuzzle.ask("core:security:user:get", kuid);
|
|
959
|
+
callback(null, user);
|
|
960
|
+
}
|
|
961
|
+
catch (e) {
|
|
962
|
+
// Duck-typed, as it always was: `core:security:user:get` rejects with a
|
|
963
|
+
// KuzzleError, but the id is all this branch reads and narrowing to the
|
|
964
|
+
// class would change which errors it recognises.
|
|
965
|
+
if (idOf(e) === "security.user.not_found") {
|
|
966
|
+
callback(strategyError.get("unknown_kuid", prefix));
|
|
967
|
+
}
|
|
968
|
+
else {
|
|
969
|
+
callback(e);
|
|
970
|
+
}
|
|
971
|
+
}
|
|
972
|
+
}
|
|
973
|
+
/**
|
|
974
|
+
* Resolves a handler a plugin referenced by name and binds it to the instance.
|
|
975
|
+
*
|
|
976
|
+
* `plugin.instance[name]` is `unknown` — a plugin may expose anything — so the
|
|
977
|
+
* `typeof` check is what makes the result callable. Every call site had already
|
|
978
|
+
* made that check; this is the same one, in the place that needs it.
|
|
979
|
+
*
|
|
980
|
+
* The name resolving to nothing callable is unreachable — all four call sites
|
|
981
|
+
* establish it first — and the previous annotation said so by answering
|
|
982
|
+
* `undefined`, deferring the choice to the day this file had to pass strict
|
|
983
|
+
* (TD-54, #2757). That is this slice: the branch throws, so
|
|
984
|
+
* the three callers that would each have had to guard a value that cannot
|
|
985
|
+
* exist do not, and the one thing that could produce it — a plugin whose
|
|
986
|
+
* member stopped being a function between the check and the bind — says so
|
|
987
|
+
* instead of returning something uncallable.
|
|
988
|
+
*/
|
|
989
|
+
function bindPluginMethod(instance, name) {
|
|
990
|
+
const method = instance[name];
|
|
991
|
+
if (!isPluginMethod(method)) {
|
|
992
|
+
throw runtimeError.get("unexpected_error", `plugin member "${name}" is not a function`);
|
|
993
|
+
}
|
|
994
|
+
return method.bind(instance);
|
|
995
|
+
}
|
|
996
|
+
/**
|
|
997
|
+
* A declared narrowing from `unknown` to "callable", the same shape
|
|
998
|
+
* `safeObject.isPlainObject` has. A predicate rather than an assertion: it is
|
|
999
|
+
* what lets a plugin's member — `unknown` by construction — be invoked without
|
|
1000
|
+
* an `as`, which TD-43's `casts` ratchet now prices.
|
|
1001
|
+
*/
|
|
1002
|
+
function isPluginMethod(value) {
|
|
1003
|
+
return typeof value === "function";
|
|
1004
|
+
}
|
|
1005
|
+
/**
|
|
1006
|
+
* The duck-typed promise check `registerPipe` has always made: a plugin's pipe
|
|
1007
|
+
* may answer a promise, a value, or nothing, and only the first is awaited.
|
|
1008
|
+
* A guard rather than an inline `typeof` chain so the branch narrows.
|
|
1009
|
+
*
|
|
1010
|
+
* `Promise` rather than `Bluebird`: nothing here proves the plugin returned a
|
|
1011
|
+
* Bluebird, and `then`/`catch` — which is exactly what the guard tests and what
|
|
1012
|
+
* `registerPipe` calls — is all of `Promise` the callers need (TD-56, #2759).
|
|
1013
|
+
*/
|
|
1014
|
+
function isThenable(value) {
|
|
1015
|
+
return (typeof value === "object" &&
|
|
1016
|
+
value !== null &&
|
|
1017
|
+
"then" in value &&
|
|
1018
|
+
typeof value.then === "function" &&
|
|
1019
|
+
"catch" in value &&
|
|
1020
|
+
typeof value.catch === "function");
|
|
1021
|
+
}
|
|
1022
|
+
/**
|
|
1023
|
+
* What `wrapStrategyVerify` has always accepted from a strategy's `verify`:
|
|
1024
|
+
* anything with a callable `then`, which is all `await` needs. Looser than
|
|
1025
|
+
* `isThenable` on purpose — that one also requires `catch`, because
|
|
1026
|
+
* `registerPipe` calls it; reusing it here (#2748) had started rejecting the
|
|
1027
|
+
* `then`-only thenables v2.56.0 awaited.
|
|
1028
|
+
*/
|
|
1029
|
+
function hasThen(value) {
|
|
1030
|
+
return ((typeof value === "object" || typeof value === "function") &&
|
|
1031
|
+
value !== null &&
|
|
1032
|
+
"then" in value &&
|
|
1033
|
+
typeof value.then === "function");
|
|
1034
|
+
}
|
|
801
1035
|
function isConstructor(arg) {
|
|
1036
|
+
if (typeof arg !== "function") {
|
|
1037
|
+
return false;
|
|
1038
|
+
}
|
|
802
1039
|
try {
|
|
803
1040
|
Reflect.construct(Object, [], arg);
|
|
804
1041
|
}
|
|
805
|
-
catch
|
|
1042
|
+
catch {
|
|
806
1043
|
return false;
|
|
807
1044
|
}
|
|
808
1045
|
return true;
|
|
809
1046
|
}
|
|
810
1047
|
function getMethods(object) {
|
|
811
1048
|
const prototype = Object.getPrototypeOf(object);
|
|
812
|
-
const instanceMethods = Object.getOwnPropertyNames(prototype).filter((method) => ["init", "constructor"].
|
|
813
|
-
const objectMethods = Object.getOwnPropertyNames(object).filter((key) => typeof object
|
|
1049
|
+
const instanceMethods = Object.getOwnPropertyNames(prototype).filter((method) => !["init", "constructor"].includes(method));
|
|
1050
|
+
const objectMethods = Object.getOwnPropertyNames(object).filter((key) => typeof Reflect.get(object, key) === "function");
|
|
814
1051
|
return [...instanceMethods, ...objectMethods];
|
|
815
1052
|
}
|
|
816
1053
|
module.exports = PluginsManager;
|