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,24 +19,24 @@
|
|
|
19
19
|
* limitations under the License.
|
|
20
20
|
*/
|
|
21
21
|
|
|
22
|
-
|
|
22
|
+
"use strict";
|
|
23
23
|
|
|
24
|
-
const _ = require(
|
|
25
|
-
const jwt = require(
|
|
26
|
-
const ms = require(
|
|
27
|
-
const Bluebird = require(
|
|
24
|
+
const _ = require("lodash");
|
|
25
|
+
const jwt = require("jsonwebtoken");
|
|
26
|
+
const ms = require("ms");
|
|
27
|
+
const Bluebird = require("bluebird");
|
|
28
28
|
|
|
29
|
-
const ApiKey = require(
|
|
30
|
-
const { UnauthorizedError } = require(
|
|
31
|
-
const { Token } = require(
|
|
32
|
-
const Repository = require(
|
|
33
|
-
const kerror = require(
|
|
34
|
-
const debug = require(
|
|
35
|
-
const { Mutex } = require(
|
|
29
|
+
const ApiKey = require("../../model/storage/apiKey");
|
|
30
|
+
const { UnauthorizedError } = require("../../kerror/errors");
|
|
31
|
+
const { Token } = require("../../model/security/token");
|
|
32
|
+
const Repository = require("../shared/repository");
|
|
33
|
+
const kerror = require("../../kerror");
|
|
34
|
+
const debug = require("../../util/debug")("kuzzle:bootstrap:tokens");
|
|
35
|
+
const { Mutex } = require("../../util/mutex");
|
|
36
36
|
|
|
37
|
-
const securityError = kerror.wrap(
|
|
37
|
+
const securityError = kerror.wrap("security", "token");
|
|
38
38
|
|
|
39
|
-
const BOOTSTRAP_DONE_KEY =
|
|
39
|
+
const BOOTSTRAP_DONE_KEY = "token/bootstrap";
|
|
40
40
|
|
|
41
41
|
/**
|
|
42
42
|
* @class TokenRepository
|
|
@@ -45,19 +45,21 @@ const BOOTSTRAP_DONE_KEY = 'token/bootstrap';
|
|
|
45
45
|
* @param {object} [opts]
|
|
46
46
|
*/
|
|
47
47
|
class TokenRepository extends Repository {
|
|
48
|
-
constructor
|
|
48
|
+
constructor(opts = {}) {
|
|
49
49
|
super();
|
|
50
|
-
this.collection =
|
|
50
|
+
this.collection = "token";
|
|
51
51
|
this.ObjectConstructor = Token;
|
|
52
52
|
if (opts.ttl !== undefined) {
|
|
53
53
|
this.ttl = opts.ttl;
|
|
54
54
|
}
|
|
55
55
|
|
|
56
|
-
this.tokenGracePeriod = Math.floor(
|
|
57
|
-
|
|
56
|
+
this.tokenGracePeriod = Math.floor(
|
|
57
|
+
global.kuzzle.config.security.jwt.gracePeriod
|
|
58
|
+
);
|
|
59
|
+
this.anonymousToken = new Token({ userId: "-1" });
|
|
58
60
|
}
|
|
59
61
|
|
|
60
|
-
async init
|
|
62
|
+
async init() {
|
|
61
63
|
await this._loadApiKeys();
|
|
62
64
|
|
|
63
65
|
/**
|
|
@@ -67,9 +69,9 @@ class TokenRepository extends Repository {
|
|
|
67
69
|
* @param {Number} ttl - token expiration delay
|
|
68
70
|
* @returns {Token}
|
|
69
71
|
*/
|
|
70
|
-
global.kuzzle.onAsk(
|
|
71
|
-
|
|
72
|
-
|
|
72
|
+
global.kuzzle.onAsk("core:security:token:assign", (hash, userId, ttl) =>
|
|
73
|
+
this.persistForUser(hash, userId, ttl)
|
|
74
|
+
);
|
|
73
75
|
|
|
74
76
|
/**
|
|
75
77
|
* Creates and assigns a token to a user
|
|
@@ -77,24 +79,26 @@ class TokenRepository extends Repository {
|
|
|
77
79
|
* @param {Objects} opts (algorithm, expiresIn, bypassMaxTTL)
|
|
78
80
|
* @returns {Token}
|
|
79
81
|
*/
|
|
80
|
-
global.kuzzle.onAsk(
|
|
81
|
-
|
|
82
|
-
|
|
82
|
+
global.kuzzle.onAsk("core:security:token:create", (user, opts) =>
|
|
83
|
+
this.generateToken(user, opts)
|
|
84
|
+
);
|
|
83
85
|
|
|
84
86
|
/**
|
|
85
87
|
* Deletes a token immediately
|
|
86
88
|
* @param {Token} token
|
|
87
89
|
*/
|
|
88
|
-
global.kuzzle.onAsk(
|
|
90
|
+
global.kuzzle.onAsk("core:security:token:delete", (token) =>
|
|
91
|
+
this.expire(token)
|
|
92
|
+
);
|
|
89
93
|
|
|
90
94
|
/**
|
|
91
95
|
* Deletes all tokens assigned to the provided user ID.
|
|
92
96
|
* @param {String} userId
|
|
93
97
|
* @param {Objects} opts (keepApiKeys)
|
|
94
98
|
*/
|
|
95
|
-
global.kuzzle.onAsk(
|
|
96
|
-
|
|
97
|
-
|
|
99
|
+
global.kuzzle.onAsk("core:security:token:deleteByKuid", (kuid, opts) =>
|
|
100
|
+
this.deleteByKuid(kuid, opts)
|
|
101
|
+
);
|
|
98
102
|
|
|
99
103
|
/**
|
|
100
104
|
* Gets a token
|
|
@@ -102,9 +106,9 @@ class TokenRepository extends Repository {
|
|
|
102
106
|
* @param {String} hash - JWT
|
|
103
107
|
* @returns {Token}
|
|
104
108
|
*/
|
|
105
|
-
global.kuzzle.onAsk(
|
|
106
|
-
|
|
107
|
-
|
|
109
|
+
global.kuzzle.onAsk("core:security:token:get", (userId, hash) =>
|
|
110
|
+
this.loadForUser(userId, hash)
|
|
111
|
+
);
|
|
108
112
|
|
|
109
113
|
/**
|
|
110
114
|
* Refreshes an existing token for the given user.
|
|
@@ -118,8 +122,9 @@ class TokenRepository extends Repository {
|
|
|
118
122
|
* @returns {Token} new token
|
|
119
123
|
*/
|
|
120
124
|
global.kuzzle.onAsk(
|
|
121
|
-
|
|
122
|
-
(user, token, expiresIn) => this.refresh(user, token, expiresIn)
|
|
125
|
+
"core:security:token:refresh",
|
|
126
|
+
(user, token, expiresIn) => this.refresh(user, token, expiresIn)
|
|
127
|
+
);
|
|
123
128
|
|
|
124
129
|
/**
|
|
125
130
|
* Verifies if the provided hash is valid, and returns the corresponding
|
|
@@ -127,10 +132,9 @@ class TokenRepository extends Repository {
|
|
|
127
132
|
* @param {String} hash - JWT
|
|
128
133
|
* @returns {Token}
|
|
129
134
|
*/
|
|
130
|
-
global.kuzzle.onAsk(
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
135
|
+
global.kuzzle.onAsk("core:security:token:verify", (hash) =>
|
|
136
|
+
this.verifyToken(hash)
|
|
137
|
+
);
|
|
134
138
|
}
|
|
135
139
|
|
|
136
140
|
/**
|
|
@@ -138,7 +142,7 @@ class TokenRepository extends Repository {
|
|
|
138
142
|
* @param {Token} requestToken
|
|
139
143
|
* @returns {Promise}
|
|
140
144
|
*/
|
|
141
|
-
async expire
|
|
145
|
+
async expire(token) {
|
|
142
146
|
await super.expireFromCache(token);
|
|
143
147
|
await global.kuzzle.tokenManager.expire(token);
|
|
144
148
|
}
|
|
@@ -153,19 +157,17 @@ class TokenRepository extends Repository {
|
|
|
153
157
|
* @param {String} expiresIn - new token expiration delay
|
|
154
158
|
* @returns {Promise<Token>}
|
|
155
159
|
*/
|
|
156
|
-
async refresh
|
|
160
|
+
async refresh(user, token, expiresIn) {
|
|
157
161
|
// do not refresh a token marked as already
|
|
158
162
|
if (token.refreshed) {
|
|
159
|
-
throw securityError.get(
|
|
163
|
+
throw securityError.get("invalid");
|
|
160
164
|
}
|
|
161
165
|
|
|
162
166
|
// do not refresh API Keys or token that have an infinite TTL
|
|
163
|
-
if (token.type ===
|
|
167
|
+
if (token.type === "apiKey" || token.ttl < 0) {
|
|
164
168
|
throw securityError.get(
|
|
165
|
-
|
|
166
|
-
token.type ===
|
|
167
|
-
? 'API Key'
|
|
168
|
-
: 'Token with infinite TTL'
|
|
169
|
+
"refresh_forbidden",
|
|
170
|
+
token.type === "apiKey" ? "API Key" : "Token with infinite TTL"
|
|
169
171
|
);
|
|
170
172
|
}
|
|
171
173
|
|
|
@@ -186,37 +188,44 @@ class TokenRepository extends Repository {
|
|
|
186
188
|
*
|
|
187
189
|
* @returns {Promise.<Object>} { _id, jwt, userId, ttl, expiresAt }
|
|
188
190
|
*/
|
|
189
|
-
async generateToken
|
|
191
|
+
async generateToken(
|
|
190
192
|
user,
|
|
191
193
|
{
|
|
192
194
|
algorithm = global.kuzzle.config.security.jwt.algorithm,
|
|
193
195
|
expiresIn = global.kuzzle.config.security.jwt.expiresIn,
|
|
194
196
|
bypassMaxTTL = false,
|
|
195
|
-
type =
|
|
197
|
+
type = "authToken",
|
|
196
198
|
} = {}
|
|
197
199
|
) {
|
|
198
|
-
if (!
|
|
199
|
-
throw securityError.get(
|
|
200
|
+
if (!user || user._id === null) {
|
|
201
|
+
throw securityError.get("unknown_user");
|
|
200
202
|
}
|
|
201
203
|
|
|
202
204
|
const parsedExpiresIn = parseTimespan(expiresIn);
|
|
203
205
|
|
|
204
|
-
const maxTTL =
|
|
205
|
-
|
|
206
|
-
|
|
206
|
+
const maxTTL =
|
|
207
|
+
type === "apiKey"
|
|
208
|
+
? global.kuzzle.config.security.apiKey.maxTTL
|
|
209
|
+
: global.kuzzle.config.security.jwt.maxTTL;
|
|
207
210
|
|
|
208
|
-
if (
|
|
209
|
-
&&
|
|
210
|
-
|
|
211
|
-
|
|
211
|
+
if (
|
|
212
|
+
!bypassMaxTTL &&
|
|
213
|
+
maxTTL > -1 &&
|
|
214
|
+
(parsedExpiresIn > maxTTL || parsedExpiresIn === -1)
|
|
212
215
|
) {
|
|
213
|
-
throw securityError.get(
|
|
216
|
+
throw securityError.get("ttl_exceeded");
|
|
214
217
|
}
|
|
215
218
|
|
|
216
219
|
const signOptions = { algorithm };
|
|
217
220
|
|
|
218
221
|
if (parsedExpiresIn === 0) {
|
|
219
|
-
throw kerror.get(
|
|
222
|
+
throw kerror.get(
|
|
223
|
+
"api",
|
|
224
|
+
"assert",
|
|
225
|
+
"invalid_argument",
|
|
226
|
+
"expiresIn",
|
|
227
|
+
"a number of milliseconds, or a parsable timespan string"
|
|
228
|
+
);
|
|
220
229
|
}
|
|
221
230
|
// -1 mean infite duration, so we don't pass the expiresIn option to
|
|
222
231
|
// jwt.sign
|
|
@@ -229,16 +238,15 @@ class TokenRepository extends Repository {
|
|
|
229
238
|
encodedToken = jwt.sign(
|
|
230
239
|
{ _id: user._id },
|
|
231
240
|
global.kuzzle.secret,
|
|
232
|
-
signOptions
|
|
233
|
-
|
|
234
|
-
catch (err) {
|
|
235
|
-
throw securityError.getFrom(err,
|
|
241
|
+
signOptions
|
|
242
|
+
);
|
|
243
|
+
} catch (err) {
|
|
244
|
+
throw securityError.getFrom(err, "generation_failed", err.message);
|
|
236
245
|
}
|
|
237
246
|
|
|
238
|
-
if (type ===
|
|
247
|
+
if (type === "apiKey") {
|
|
239
248
|
encodedToken = Token.APIKEY_PREFIX + encodedToken;
|
|
240
|
-
}
|
|
241
|
-
else {
|
|
249
|
+
} else {
|
|
242
250
|
encodedToken = Token.AUTH_PREFIX + encodedToken;
|
|
243
251
|
}
|
|
244
252
|
|
|
@@ -254,7 +262,7 @@ class TokenRepository extends Repository {
|
|
|
254
262
|
*
|
|
255
263
|
* @returns {Promise}
|
|
256
264
|
*/
|
|
257
|
-
async persistForUser
|
|
265
|
+
async persistForUser(encodedToken, userId, ttl) {
|
|
258
266
|
const redisTTL = ttl === -1 ? 0 : ttl;
|
|
259
267
|
const expiresAt = ttl === -1 ? -1 : Date.now() + ttl;
|
|
260
268
|
const token = new Token({
|
|
@@ -267,18 +275,18 @@ class TokenRepository extends Repository {
|
|
|
267
275
|
|
|
268
276
|
try {
|
|
269
277
|
return await this.persistToCache(token, { ttl: redisTTL });
|
|
270
|
-
}
|
|
271
|
-
catch (err) {
|
|
278
|
+
} catch (err) {
|
|
272
279
|
throw kerror.getFrom(
|
|
273
280
|
err,
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
err.message
|
|
281
|
+
"services",
|
|
282
|
+
"cache",
|
|
283
|
+
"write_failed",
|
|
284
|
+
err.message
|
|
285
|
+
);
|
|
278
286
|
}
|
|
279
287
|
}
|
|
280
288
|
|
|
281
|
-
async verifyToken
|
|
289
|
+
async verifyToken(token) {
|
|
282
290
|
if (token === null) {
|
|
283
291
|
return this.anonymousToken;
|
|
284
292
|
}
|
|
@@ -289,67 +297,65 @@ class TokenRepository extends Repository {
|
|
|
289
297
|
decoded = jwt.verify(this.removeTokenPrefix(token), global.kuzzle.secret);
|
|
290
298
|
|
|
291
299
|
// probably forged token => throw without providing any information
|
|
292
|
-
if (!
|
|
293
|
-
throw new jwt.JsonWebTokenError(
|
|
300
|
+
if (!decoded._id) {
|
|
301
|
+
throw new jwt.JsonWebTokenError("Invalid token");
|
|
294
302
|
}
|
|
295
|
-
}
|
|
296
|
-
catch (err) {
|
|
303
|
+
} catch (err) {
|
|
297
304
|
if (err instanceof jwt.TokenExpiredError) {
|
|
298
|
-
throw securityError.get(
|
|
305
|
+
throw securityError.get("expired");
|
|
299
306
|
}
|
|
300
307
|
|
|
301
308
|
if (err instanceof jwt.JsonWebTokenError) {
|
|
302
|
-
throw securityError.get(
|
|
309
|
+
throw securityError.get("invalid");
|
|
303
310
|
}
|
|
304
311
|
|
|
305
|
-
throw securityError.getFrom(err,
|
|
312
|
+
throw securityError.getFrom(err, "verification_error", err.message);
|
|
306
313
|
}
|
|
307
314
|
|
|
308
315
|
let userToken;
|
|
309
316
|
|
|
310
317
|
try {
|
|
311
318
|
userToken = await this.loadForUser(decoded._id, token);
|
|
312
|
-
}
|
|
313
|
-
catch (err) {
|
|
319
|
+
} catch (err) {
|
|
314
320
|
if (err instanceof UnauthorizedError) {
|
|
315
321
|
throw err;
|
|
316
322
|
}
|
|
317
323
|
|
|
318
|
-
throw securityError.getFrom(err,
|
|
324
|
+
throw securityError.getFrom(err, "verification_error", err.message);
|
|
319
325
|
}
|
|
320
326
|
|
|
321
327
|
if (userToken === null) {
|
|
322
|
-
throw securityError.get(
|
|
328
|
+
throw securityError.get("invalid");
|
|
323
329
|
}
|
|
324
330
|
|
|
325
331
|
return userToken;
|
|
326
332
|
}
|
|
327
333
|
|
|
328
|
-
removeTokenPrefix
|
|
334
|
+
removeTokenPrefix(token) {
|
|
329
335
|
return token
|
|
330
|
-
.replace(Token.AUTH_PREFIX,
|
|
331
|
-
.replace(Token.APIKEY_PREFIX,
|
|
336
|
+
.replace(Token.AUTH_PREFIX, "")
|
|
337
|
+
.replace(Token.APIKEY_PREFIX, "");
|
|
332
338
|
}
|
|
333
339
|
|
|
334
|
-
loadForUser
|
|
340
|
+
loadForUser(userId, encodedToken) {
|
|
335
341
|
return this.load(`${userId}#${encodedToken}`);
|
|
336
342
|
}
|
|
337
343
|
|
|
338
|
-
async hydrate
|
|
339
|
-
if (!
|
|
344
|
+
async hydrate(userToken, data) {
|
|
345
|
+
if (!_.isObject(data)) {
|
|
340
346
|
return userToken;
|
|
341
347
|
}
|
|
342
348
|
|
|
343
349
|
_.assignIn(userToken, data);
|
|
344
350
|
|
|
345
|
-
if (!
|
|
351
|
+
if (!userToken.userId) {
|
|
346
352
|
return this.anonymousToken;
|
|
347
353
|
}
|
|
348
354
|
|
|
349
355
|
return userToken;
|
|
350
356
|
}
|
|
351
357
|
|
|
352
|
-
serializeToDatabase
|
|
358
|
+
serializeToDatabase(token) {
|
|
353
359
|
return this.serializeToCache(token);
|
|
354
360
|
}
|
|
355
361
|
|
|
@@ -359,11 +365,14 @@ class TokenRepository extends Repository {
|
|
|
359
365
|
* @param {string} kuid
|
|
360
366
|
* @returns {Promise}
|
|
361
367
|
*/
|
|
362
|
-
async deleteByKuid
|
|
363
|
-
const emptyKeyLength = super.getCacheKey(
|
|
368
|
+
async deleteByKuid(kuid, { keepApiKeys = true } = {}) {
|
|
369
|
+
const emptyKeyLength = super.getCacheKey("").length;
|
|
364
370
|
const userKey = super.getCacheKey(`${kuid}#*`);
|
|
365
371
|
|
|
366
|
-
const keys = await global.kuzzle.ask(
|
|
372
|
+
const keys = await global.kuzzle.ask(
|
|
373
|
+
"core:cache:internal:searchKeys",
|
|
374
|
+
userKey
|
|
375
|
+
);
|
|
367
376
|
|
|
368
377
|
/*
|
|
369
378
|
Given the fact that user ids have no restriction, and that Redis pattern
|
|
@@ -381,19 +390,18 @@ class TokenRepository extends Repository {
|
|
|
381
390
|
JWT character
|
|
382
391
|
*/
|
|
383
392
|
const ids = keys
|
|
384
|
-
.map(key => {
|
|
385
|
-
return key.indexOf(
|
|
393
|
+
.map((key) => {
|
|
394
|
+
return key.indexOf("#", userKey.length - 1) === -1
|
|
386
395
|
? key.slice(emptyKeyLength)
|
|
387
396
|
: null;
|
|
388
397
|
})
|
|
389
|
-
.filter(key => key !== null);
|
|
390
|
-
|
|
391
|
-
await Bluebird.map(ids, async token => {
|
|
398
|
+
.filter((key) => key !== null);
|
|
392
399
|
|
|
400
|
+
await Bluebird.map(ids, async (token) => {
|
|
393
401
|
const cacheToken = await this.load(token);
|
|
394
402
|
|
|
395
403
|
if (cacheToken !== null) {
|
|
396
|
-
if (keepApiKeys && cacheToken.type ===
|
|
404
|
+
if (keepApiKeys && cacheToken.type === "apiKey") {
|
|
397
405
|
return;
|
|
398
406
|
}
|
|
399
407
|
|
|
@@ -407,8 +415,8 @@ class TokenRepository extends Repository {
|
|
|
407
415
|
*
|
|
408
416
|
* @returns {Promise}
|
|
409
417
|
*/
|
|
410
|
-
async _loadApiKeys
|
|
411
|
-
const mutex = new Mutex(
|
|
418
|
+
async _loadApiKeys() {
|
|
419
|
+
const mutex = new Mutex("ApiKeysBootstrap", {
|
|
412
420
|
timeout: -1,
|
|
413
421
|
ttl: 30000,
|
|
414
422
|
});
|
|
@@ -417,29 +425,35 @@ class TokenRepository extends Repository {
|
|
|
417
425
|
|
|
418
426
|
try {
|
|
419
427
|
const bootstrapped = await global.kuzzle.ask(
|
|
420
|
-
|
|
421
|
-
BOOTSTRAP_DONE_KEY
|
|
428
|
+
"core:cache:internal:get",
|
|
429
|
+
BOOTSTRAP_DONE_KEY
|
|
430
|
+
);
|
|
422
431
|
|
|
423
432
|
if (bootstrapped) {
|
|
424
|
-
debug(
|
|
433
|
+
debug("API keys already in cache. Skip.");
|
|
425
434
|
return;
|
|
426
435
|
}
|
|
427
436
|
|
|
428
|
-
debug(
|
|
437
|
+
debug("Loading API keys into Redis");
|
|
429
438
|
|
|
430
439
|
const promises = [];
|
|
431
440
|
|
|
432
|
-
await ApiKey.batchExecute({ match_all: {} }, documents => {
|
|
441
|
+
await ApiKey.batchExecute({ match_all: {} }, (documents) => {
|
|
433
442
|
for (const { _source } of documents) {
|
|
434
|
-
promises.push(
|
|
443
|
+
promises.push(
|
|
444
|
+
this.persistForUser(_source.token, _source.userId, _source.ttl)
|
|
445
|
+
);
|
|
435
446
|
}
|
|
436
447
|
});
|
|
437
448
|
|
|
438
449
|
await Bluebird.all(promises);
|
|
439
450
|
|
|
440
|
-
await global.kuzzle.ask(
|
|
441
|
-
|
|
442
|
-
|
|
451
|
+
await global.kuzzle.ask(
|
|
452
|
+
"core:cache:internal:store",
|
|
453
|
+
BOOTSTRAP_DONE_KEY,
|
|
454
|
+
1
|
|
455
|
+
);
|
|
456
|
+
} finally {
|
|
443
457
|
await mutex.unlock();
|
|
444
458
|
}
|
|
445
459
|
}
|
|
@@ -453,7 +467,7 @@ class TokenRepository extends Repository {
|
|
|
453
467
|
*
|
|
454
468
|
* So we need to override the TTL auto-refresh function to disable it
|
|
455
469
|
*/
|
|
456
|
-
refreshCacheTTL
|
|
470
|
+
refreshCacheTTL() {
|
|
457
471
|
// This comment is here to please Sonarqube. It requires a comment
|
|
458
472
|
// explaining why a function is empty, but there is no sense
|
|
459
473
|
// duplicating what has been just said in the JSDoc.
|
|
@@ -479,18 +493,18 @@ module.exports = TokenRepository;
|
|
|
479
493
|
* @param {String|Number} time
|
|
480
494
|
* @return {Number}
|
|
481
495
|
*/
|
|
482
|
-
function parseTimespan
|
|
483
|
-
if (typeof time ===
|
|
496
|
+
function parseTimespan(time) {
|
|
497
|
+
if (typeof time === "string") {
|
|
484
498
|
const milliseconds = ms(time);
|
|
485
499
|
|
|
486
|
-
if (typeof milliseconds ===
|
|
500
|
+
if (typeof milliseconds === "undefined") {
|
|
487
501
|
return 0;
|
|
488
502
|
}
|
|
489
503
|
|
|
490
504
|
return milliseconds;
|
|
491
505
|
}
|
|
492
506
|
|
|
493
|
-
if (typeof time ===
|
|
507
|
+
if (typeof time === "number") {
|
|
494
508
|
return time;
|
|
495
509
|
}
|
|
496
510
|
|