kuzzle 2.16.8 → 2.17.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (167) hide show
  1. package/README.md +11 -0
  2. package/lib/api/controllers/adminController.js +7 -6
  3. package/lib/api/controllers/authController.js +11 -11
  4. package/lib/api/controllers/baseController.js +60 -3
  5. package/lib/api/controllers/clusterController.js +1 -1
  6. package/lib/api/controllers/collectionController.js +7 -5
  7. package/lib/api/controllers/documentController.js +130 -17
  8. package/lib/api/controllers/indexController.js +1 -1
  9. package/lib/api/controllers/memoryStorageController.js +39 -38
  10. package/lib/api/controllers/realtimeController.js +1 -1
  11. package/lib/api/controllers/securityController.js +49 -49
  12. package/lib/api/controllers/serverController.js +73 -27
  13. package/lib/api/documentExtractor.js +3 -3
  14. package/lib/api/funnel.js +40 -21
  15. package/lib/api/httpRoutes.js +9 -4
  16. package/lib/api/openapi/OpenApiManager.d.ts +11 -0
  17. package/lib/api/openapi/OpenApiManager.js +96 -0
  18. package/lib/api/openapi/{document → components/document}/count.yaml +2 -2
  19. package/lib/api/openapi/{document → components/document}/create.yaml +2 -2
  20. package/lib/api/openapi/{document → components/document}/createOrReplace.yaml +2 -2
  21. package/lib/api/openapi/{document → components/document}/delete.yaml +1 -1
  22. package/lib/api/openapi/{document → components/document}/deleteByQuery.yaml +2 -2
  23. package/lib/api/openapi/{document → components/document}/exists.yaml +1 -1
  24. package/lib/api/openapi/{document → components/document}/get.yaml +1 -1
  25. package/lib/api/openapi/{document → components/document}/index.d.ts +2 -0
  26. package/lib/api/openapi/{document → components/document}/index.js +7 -2
  27. package/lib/api/openapi/{document → components/document}/replace.yaml +2 -2
  28. package/lib/api/openapi/{document → components/document}/scroll.yaml +1 -1
  29. package/lib/api/openapi/{document → components/document}/update.yaml +2 -2
  30. package/lib/api/openapi/components/document/validate.yaml +42 -0
  31. package/lib/api/openapi/components/index.d.ts +2 -0
  32. package/lib/api/openapi/components/index.js +18 -0
  33. package/lib/api/openapi/{payloads.yaml → components/payloads.yaml} +0 -0
  34. package/lib/api/openapi/index.d.ts +1 -2
  35. package/lib/api/openapi/index.js +1 -5
  36. package/lib/api/openapi/openApiGenerator.d.ts +7 -0
  37. package/lib/api/openapi/openApiGenerator.js +133 -0
  38. package/lib/api/request/kuzzleRequest.d.ts +11 -11
  39. package/lib/api/request/kuzzleRequest.js +38 -48
  40. package/lib/cluster/node.js +9 -9
  41. package/lib/cluster/publisher.js +1 -1
  42. package/lib/cluster/subscriber.js +1 -1
  43. package/lib/cluster/workers/IDCardRenewer.js +13 -4
  44. package/lib/config/default.config.js +1 -0
  45. package/lib/config/index.js +6 -6
  46. package/lib/core/auth/passportResponse.js +6 -6
  47. package/lib/core/auth/passportWrapper.js +5 -5
  48. package/lib/core/backend/backend.d.ts +5 -1
  49. package/lib/core/backend/backend.js +12 -8
  50. package/lib/core/backend/backendConfig.d.ts +5 -1
  51. package/lib/core/backend/backendConfig.js +4 -0
  52. package/lib/core/backend/backendOpenApi.d.ts +9 -0
  53. package/lib/core/backend/backendOpenApi.js +69 -0
  54. package/lib/core/backend/index.d.ts +1 -0
  55. package/lib/core/backend/index.js +1 -0
  56. package/lib/core/network/accessLogger.js +6 -6
  57. package/lib/core/network/clientConnection.js +1 -1
  58. package/lib/core/network/entryPoint.js +5 -5
  59. package/lib/core/network/httpRouter/index.js +5 -5
  60. package/lib/core/network/httpRouter/routeHandler.js +3 -3
  61. package/lib/core/network/httpRouter/routePart.js +5 -5
  62. package/lib/core/network/protocolManifest.js +1 -1
  63. package/lib/core/network/protocols/httpMessage.js +2 -2
  64. package/lib/core/network/protocols/httpwsProtocol.js +207 -46
  65. package/lib/core/network/protocols/mqttProtocol.js +3 -3
  66. package/lib/core/network/protocols/protocol.js +3 -3
  67. package/lib/core/network/router.js +7 -6
  68. package/lib/core/plugin/plugin.js +38 -64
  69. package/lib/core/plugin/pluginContext.d.ts +10 -1
  70. package/lib/core/plugin/pluginContext.js +2 -0
  71. package/lib/core/plugin/pluginManifest.js +3 -3
  72. package/lib/core/plugin/pluginRepository.js +5 -5
  73. package/lib/core/plugin/pluginsManager.js +29 -28
  74. package/lib/core/realtime/notification/server.js +1 -1
  75. package/lib/core/realtime/notification/user.js +1 -1
  76. package/lib/core/realtime/notifier.js +5 -5
  77. package/lib/core/security/index.js +1 -1
  78. package/lib/core/security/profileRepository.d.ts +176 -0
  79. package/lib/core/security/profileRepository.js +426 -443
  80. package/lib/core/security/roleRepository.js +16 -16
  81. package/lib/core/security/securityLoader.js +3 -3
  82. package/lib/core/security/tokenRepository.js +18 -21
  83. package/lib/core/security/userRepository.js +8 -8
  84. package/lib/core/shared/abstractManifest.js +4 -4
  85. package/lib/core/shared/repository.js +6 -6
  86. package/lib/core/shared/sdk/funnelProtocol.js +1 -1
  87. package/lib/core/shared/sdk/impersonatedSdk.js +1 -1
  88. package/lib/core/shared/store.js +30 -23
  89. package/lib/core/statistics/statistics.js +17 -17
  90. package/lib/core/storage/clientAdapter.js +45 -10
  91. package/lib/core/validation/baseType.js +5 -5
  92. package/lib/core/validation/types/anything.js +1 -1
  93. package/lib/core/validation/types/boolean.js +2 -2
  94. package/lib/core/validation/types/date.js +9 -9
  95. package/lib/core/validation/types/email.js +5 -5
  96. package/lib/core/validation/types/enum.js +6 -6
  97. package/lib/core/validation/types/geoPoint.js +2 -2
  98. package/lib/core/validation/types/geoShape.js +28 -25
  99. package/lib/core/validation/types/integer.js +4 -4
  100. package/lib/core/validation/types/ipAddress.js +7 -6
  101. package/lib/core/validation/types/numeric.js +4 -4
  102. package/lib/core/validation/types/object.js +5 -5
  103. package/lib/core/validation/types/string.js +5 -5
  104. package/lib/core/validation/types/url.js +7 -6
  105. package/lib/core/validation/validation.js +95 -84
  106. package/lib/kerror/codes/1-services.json +12 -0
  107. package/lib/kerror/codes/2-api.json +12 -0
  108. package/lib/kerror/codes/3-network.json +12 -0
  109. package/lib/kerror/codes/4-plugin.json +6 -0
  110. package/lib/kerror/codes/index.js +11 -11
  111. package/lib/kerror/index.js +1 -1
  112. package/lib/kuzzle/dumpGenerator.js +3 -3
  113. package/lib/kuzzle/event/kuzzleEventEmitter.js +4 -4
  114. package/lib/kuzzle/event/pipeRunner.js +1 -1
  115. package/lib/kuzzle/event/waterfall.js +6 -6
  116. package/lib/kuzzle/kuzzle.js +36 -5
  117. package/lib/kuzzle/log.js +3 -3
  118. package/lib/kuzzle/vault.js +3 -3
  119. package/lib/model/security/profile.d.ts +54 -0
  120. package/lib/model/security/profile.js +174 -233
  121. package/lib/model/security/rights.js +1 -1
  122. package/lib/model/security/role.d.ts +40 -0
  123. package/lib/model/security/role.js +159 -191
  124. package/lib/model/security/user.d.ts +29 -0
  125. package/lib/model/security/user.js +84 -52
  126. package/lib/model/storage/apiKey.js +2 -2
  127. package/lib/model/storage/baseModel.js +3 -3
  128. package/lib/service/cache/redis.js +7 -7
  129. package/lib/service/storage/elasticsearch.js +152 -90
  130. package/lib/service/storage/esWrapper.js +2 -3
  131. package/lib/types/ControllerDefinition.d.ts +3 -3
  132. package/lib/types/ControllerRights.d.ts +22 -0
  133. package/lib/types/ControllerRights.js +23 -0
  134. package/lib/types/HttpStream.d.ts +32 -0
  135. package/lib/types/HttpStream.js +70 -0
  136. package/lib/types/OpenApiDefinition.d.ts +43 -0
  137. package/lib/types/{config/StorageService/StorageServiceElasticsearchConfiguration.js → OpenApiDefinition.js} +1 -1
  138. package/lib/types/Policy.d.ts +25 -0
  139. package/lib/types/Policy.js +23 -0
  140. package/lib/types/PolicyRestrictions.d.ts +21 -0
  141. package/lib/types/PolicyRestrictions.js +23 -0
  142. package/lib/types/Target.d.ts +15 -0
  143. package/lib/types/Target.js +23 -0
  144. package/lib/types/config/KuzzleConfiguration.d.ts +4 -0
  145. package/lib/types/config/ServicesConfiguration.d.ts +2 -2
  146. package/lib/types/config/{StorageService/StorageServiceElasticsearchConfiguration.d.ts → storageEngine/StorageEngineElasticsearchConfiguration.d.ts} +10 -3
  147. package/lib/types/config/storageEngine/StorageEngineElasticsearchConfiguration.js +3 -0
  148. package/lib/types/index.d.ts +7 -1
  149. package/lib/types/index.js +7 -1
  150. package/lib/util/array.d.ts +11 -0
  151. package/lib/util/array.js +57 -0
  152. package/lib/util/assertType.js +6 -6
  153. package/lib/util/bufferedPassThrough.d.ts +76 -0
  154. package/lib/util/bufferedPassThrough.js +161 -0
  155. package/lib/util/deprecate.js +7 -5
  156. package/lib/util/didYouMean.js +1 -1
  157. package/lib/util/dump-collection.d.ts +3 -0
  158. package/lib/util/dump-collection.js +265 -0
  159. package/lib/util/extractFields.js +2 -2
  160. package/lib/util/inflector.d.ts +8 -0
  161. package/lib/util/inflector.js +16 -0
  162. package/lib/util/requestAssertions.js +7 -7
  163. package/lib/util/wildcard.js +55 -0
  164. package/package-lock.json +881 -431
  165. package/package.json +23 -20
  166. package/lib/api/openApiGenerator.d.ts +0 -7
  167. package/lib/api/openApiGenerator.js +0 -197
@@ -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,202 +19,169 @@
18
19
  * See the License for the specific language governing permissions and
19
20
  * limitations under the License.
20
21
  */
21
-
22
- 'use strict';
23
-
24
- const kerror = require('../../kerror');
25
- const { has, isPlainObject } = require('../../util/safeObject');
26
-
27
- const assertionError = kerror.wrap('api', 'assert');
28
-
22
+ var __importDefault = (this && this.__importDefault) || function (mod) {
23
+ return (mod && mod.__esModule) ? mod : { "default": mod };
24
+ };
25
+ Object.defineProperty(exports, "__esModule", { value: true });
26
+ exports.Role = void 0;
27
+ const kerror_1 = __importDefault(require("../../kerror"));
28
+ const safeObject_1 = require("../../util/safeObject");
29
+ const array_1 = require("../../util/array");
30
+ const assertionError = kerror_1.default.wrap('api', 'assert');
29
31
  /**
30
32
  * @class Role
31
33
  */
32
34
  class Role {
33
- constructor () {
34
- this.controllers = {};
35
- }
36
-
37
- /**
38
- * @param {Request} request
39
- * @param {Array} restrictedTo
40
- * @returns {boolean}
41
- */
42
- isActionAllowed (request, restrictedTo = []) {
43
- if (!global.kuzzle) {
44
- throw kerror.get('security', 'role', 'uninitialized', this._id);
45
- }
46
-
47
- if (this.controllers === undefined || this.controllers === null) {
48
- return false;
49
- }
50
-
51
- let controllerRights;
52
-
53
- // @deprecated - the "memoryStorage" alias should be removed in the next
54
- // major version
55
- // Handles the memory storage controller aliases: ms, memoryStorage
56
- if ((request.input.controller === 'ms' || request.input.controller === 'memoryStorage')
57
- && (this.controllers.ms || this.controllers.memoryStorage)
58
- ) {
59
- controllerRights = this.controllers.ms || this.controllers.memoryStorage;
60
- }
61
- else if (has(this.controllers, request.input.controller)) {
62
- controllerRights = this.controllers[request.input.controller];
63
- }
64
- else if (this.controllers['*'] !== undefined) {
65
- controllerRights = this.controllers['*'];
66
- }
67
- else {
68
- return false;
69
- }
70
-
71
- if (controllerRights.actions === undefined) {
72
- return false;
73
- }
74
-
75
- let actionRights;
76
-
77
- if (has(controllerRights.actions, request.input.action)) {
78
- actionRights = controllerRights.actions[request.input.action];
79
- }
80
- else if (controllerRights.actions['*'] !== undefined) {
81
- actionRights = controllerRights.actions['*'];
82
- }
83
- else {
84
- return false;
85
- }
86
-
87
- if (typeof actionRights !== 'boolean' || !actionRights) {
88
- return false;
89
- }
90
-
91
- return checkRestrictions(request, restrictedTo);
92
- }
93
-
94
- /**
95
- * @returns {Promise}
96
- */
97
- async validateDefinition () {
98
- if (this.controllers === undefined || this.controllers === null) {
99
- throw assertionError.get('missing_argument', `${this._id}.controllers`);
100
- }
101
-
102
- if (!isPlainObject(this.controllers)) {
103
- throw assertionError.get('invalid_type', `${this._id}.controllers`, 'object');
104
- }
105
-
106
- if (Object.keys(this.controllers).length === 0) {
107
- throw assertionError.get('empty_argument', `${this._id}.controllers`);
108
- }
109
-
110
- Object
111
- .entries(this.controllers)
112
- .forEach(entry => this.validateControllerRights(...entry));
113
- }
114
-
115
- /**
116
- * Verifies that a controller rights definition is correct
117
- *
118
- * @param {Array.<string, Object>}
119
- * @throws If the controller definition is invalid
120
- */
121
- validateControllerRights (name, controller) {
122
- if (!isPlainObject(controller)) {
123
- throw assertionError.get('invalid_type', name, 'object');
124
- }
125
-
126
- if (Object.keys(controller).length === 0) {
127
- throw assertionError.get('empty_argument', name);
128
- }
129
-
130
- if (!has(controller, 'actions')) {
131
- throw assertionError.get('missing_argument', name);
132
- }
133
-
134
- if (!isPlainObject(controller.actions)) {
135
- throw assertionError.get('invalid_type', `${name}.actions`, 'object');
136
- }
137
-
138
- if (Object.keys(controller.actions).length === 0) {
139
- throw assertionError.get('empty_argument', `${name}.actions`);
140
- }
141
-
142
- for (const [actionName, action] of Object.entries(controller.actions)) {
143
- if (typeof action !== 'boolean') {
144
- throw assertionError.get('invalid_type', `${name}.actions.${actionName}`, 'boolean');
145
- }
146
- }
147
- }
148
-
149
- /**
150
- * Checks if current role allows to log in
151
- *
152
- * @returns {boolean}
153
- */
154
- canLogIn () {
155
- for (const controllerKey of ['auth', '*']) {
156
- if (this.controllers[controllerKey]) {
157
- const controller = this.controllers[controllerKey];
158
-
159
- for (const actionKey of ['login', '*']) {
160
- const action = controller.actions[actionKey];
161
-
162
- if (typeof action === 'boolean' && action) {
35
+ constructor() {
36
+ this.controllers = {};
37
+ }
38
+ /**
39
+ * @param {Request} request
40
+ * @returns {boolean}
41
+ */
42
+ isActionAllowed(request) {
43
+ if (!global.kuzzle) {
44
+ throw kerror_1.default.get('security', 'role', 'uninitialized', this._id);
45
+ }
46
+ if (this.controllers === undefined || this.controllers === null) {
47
+ return false;
48
+ }
49
+ let controllerRights;
50
+ // @deprecated - the "memoryStorage" alias should be removed in the next
51
+ // major version
52
+ // Handles the memory storage controller aliases: ms, memoryStorage
53
+ if ((request.input.controller === 'ms' || request.input.controller === 'memoryStorage')
54
+ && (this.controllers.ms || this.controllers.memoryStorage)) {
55
+ controllerRights = this.controllers.ms || this.controllers.memoryStorage;
56
+ }
57
+ else if ((0, safeObject_1.has)(this.controllers, request.input.controller)) {
58
+ controllerRights = this.controllers[request.input.controller];
59
+ }
60
+ else if (this.controllers['*'] !== undefined) {
61
+ controllerRights = this.controllers['*'];
62
+ }
63
+ else {
64
+ return false;
65
+ }
66
+ if (controllerRights.actions === undefined) {
67
+ return false;
68
+ }
69
+ let actionRights;
70
+ if ((0, safeObject_1.has)(controllerRights.actions, request.input.action)) {
71
+ actionRights = controllerRights.actions[request.input.action];
72
+ }
73
+ else if (controllerRights.actions['*'] !== undefined) {
74
+ actionRights = controllerRights.actions['*'];
75
+ }
76
+ else {
77
+ return false;
78
+ }
79
+ if (typeof actionRights !== 'boolean' || !actionRights) {
80
+ return false;
81
+ }
82
+ return true;
83
+ }
84
+ /**
85
+ * @returns {Promise}
86
+ */
87
+ async validateDefinition() {
88
+ if (this.controllers === undefined || this.controllers === null) {
89
+ throw assertionError.get('missing_argument', `${this._id}.controllers`);
90
+ }
91
+ if (!(0, safeObject_1.isPlainObject)(this.controllers)) {
92
+ throw assertionError.get('invalid_type', `${this._id}.controllers`, 'object');
93
+ }
94
+ if (Object.keys(this.controllers).length === 0) {
95
+ throw assertionError.get('empty_argument', `${this._id}.controllers`);
96
+ }
97
+ Object
98
+ .entries(this.controllers)
99
+ .forEach(entry => this.validateControllerRights(...entry));
100
+ }
101
+ /**
102
+ * @param {String} index
103
+ * @param {String} collection
104
+ * @param {Map<string, string[]>} restrictedTo Restricted indexes
105
+ * @returns {Boolean} resolves to a Boolean value
106
+ */
107
+ checkRestrictions(index, collection, restrictedTo) {
108
+ // If no restrictions, we allow the action:
109
+ if (!restrictedTo || restrictedTo.size === 0) {
163
110
  return true;
164
- }
165
111
  }
166
- }
112
+ // If the request's action does not refer to an index, restrictions are
113
+ // useless for this action (=> ignore them)
114
+ if (!index) {
115
+ return true;
116
+ }
117
+ // If the index is not in the restrictions, the action is not allowed
118
+ if (!restrictedTo.has(index)) {
119
+ return false;
120
+ }
121
+ const collections = restrictedTo.get(index);
122
+ // if no collections given on the restriction, the action is allowed for all
123
+ // collections:
124
+ if (!collections || collections.length === 0) {
125
+ return true;
126
+ }
127
+ // Find collection index in array
128
+ // If the collection is not in the array, the action is not allowed
129
+ // The array must be sorted for binary search to work
130
+ const indexOfCollection = (0, array_1.binarySearch)(collections, (collectionName) => {
131
+ if (collection > collectionName) {
132
+ return 1;
133
+ }
134
+ return collection < collectionName ? -1 : 0;
135
+ });
136
+ return indexOfCollection > -1; // Collection found
137
+ }
138
+ /**
139
+ * Verifies that a controller rights definition is correct
140
+ *
141
+ * @param {Array.<string, Object>}
142
+ * @throws If the controller definition is invalid
143
+ */
144
+ validateControllerRights(name, controller) {
145
+ if (!(0, safeObject_1.isPlainObject)(controller)) {
146
+ throw assertionError.get('invalid_type', name, 'object');
147
+ }
148
+ if (Object.keys(controller).length === 0) {
149
+ throw assertionError.get('empty_argument', name);
150
+ }
151
+ if (!(0, safeObject_1.has)(controller, 'actions')) {
152
+ throw assertionError.get('missing_argument', name);
153
+ }
154
+ if (!(0, safeObject_1.isPlainObject)(controller.actions)) {
155
+ throw assertionError.get('invalid_type', `${name}.actions`, 'object');
156
+ }
157
+ if (Object.keys(controller.actions).length === 0) {
158
+ throw assertionError.get('empty_argument', `${name}.actions`);
159
+ }
160
+ for (const [actionName, action] of Object.entries(controller.actions)) {
161
+ if (typeof action !== 'boolean') {
162
+ throw assertionError.get('invalid_type', `${name}.actions.${actionName}`, 'boolean');
163
+ }
164
+ }
165
+ }
166
+ /**
167
+ * Checks if current role allows to log in
168
+ *
169
+ * @returns {boolean}
170
+ */
171
+ canLogIn() {
172
+ for (const controllerKey of ['auth', '*']) {
173
+ if (this.controllers[controllerKey]) {
174
+ const controller = this.controllers[controllerKey];
175
+ for (const actionKey of ['login', '*']) {
176
+ const action = controller.actions[actionKey];
177
+ if (typeof action === 'boolean' && action) {
178
+ return true;
179
+ }
180
+ }
181
+ }
182
+ }
183
+ return false;
167
184
  }
168
-
169
- return false;
170
- }
171
- }
172
-
173
- /**
174
- * @param {Request} request
175
- * @param {object} restriction a restriction object on an index
176
- * @returns {Boolean}
177
- */
178
- function checkIndexRestriction(request, restriction) {
179
- if (restriction.index !== request.input.args.index) {
180
- return false;
181
- }
182
-
183
- // if no collections given on the restriction, the action is allowed for all
184
- // collections:
185
- if (!restriction.collections || restriction.collections.length === 0) {
186
- return true;
187
- }
188
-
189
- // If the request's action does not refer to a collection, the restriction
190
- // is useless for this action (=> ignored):
191
- if (!request.input.args.collection) {
192
- return true;
193
- }
194
-
195
- return restriction.collections.includes(request.input.args.collection);
196
- }
197
-
198
- /**
199
- * @param {Request} request
200
- * @param {Array} restrictedTo
201
- * @returns {Boolean} resolves to a Boolean value
202
- */
203
- function checkRestrictions(request, restrictedTo) {
204
- // If no restrictions, we allow the action:
205
- if (restrictedTo.length === 0) {
206
- return true;
207
- }
208
-
209
- // If the request's action does not refer to an index, restrictions are
210
- // useless for this action (=> ignore them)
211
- if (!request.input.args.index) {
212
- return true;
213
- }
214
-
215
- return restrictedTo
216
- .some(restriction => checkIndexRestriction(request, restriction));
217
185
  }
218
-
219
- module.exports = Role;
186
+ exports.Role = Role;
187
+ //# sourceMappingURL=role.js.map
@@ -0,0 +1,29 @@
1
+ import { Profile } from './profile';
2
+ import { KuzzleRequest } from '../../../index';
3
+ /**
4
+ * @class User
5
+ */
6
+ export declare class User {
7
+ _id: string;
8
+ profileIds: string[];
9
+ constructor();
10
+ /**
11
+ * @returns {Promise<Profile[]>}
12
+ */
13
+ getProfiles(): Promise<Profile[]>;
14
+ /**
15
+ * @returns {Promise}
16
+ */
17
+ getRights(): Promise<{}>;
18
+ /**
19
+ * @param {Request} request
20
+ * @returns {Promise.<boolean>}
21
+ */
22
+ isActionAllowed(request: KuzzleRequest): Promise<boolean>;
23
+ /**
24
+ * Verifies that every targets are allowed by at least one profile,
25
+ * while skipping the ones that includes a wildcard since they will be expanded
26
+ * later on, based on index and collections authorized for the given user.
27
+ */
28
+ private areTargetsAllowed;
29
+ }
@@ -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,62 +19,93 @@
18
19
  * See the License for the specific language governing permissions and
19
20
  * limitations under the License.
20
21
  */
21
-
22
- 'use strict';
23
-
24
- const Rights = require('./rights');
25
- const Bluebird = require('bluebird');
26
- const _ = require('lodash');
27
- const kerror = require('../../kerror');
28
-
22
+ var __importDefault = (this && this.__importDefault) || function (mod) {
23
+ return (mod && mod.__esModule) ? mod : { "default": mod };
24
+ };
25
+ Object.defineProperty(exports, "__esModule", { value: true });
26
+ exports.User = void 0;
27
+ const rights_1 = __importDefault(require("./rights"));
28
+ const bluebird_1 = __importDefault(require("bluebird"));
29
+ const lodash_1 = __importDefault(require("lodash"));
30
+ const kerror_1 = __importDefault(require("../../kerror"));
29
31
  /**
30
32
  * @class User
31
33
  */
32
34
  class User {
33
- constructor() {
34
- this._id = null;
35
- this.profileIds = [];
36
- }
37
-
38
- /**
39
- * @returns {Promise<Profile[]>}
40
- */
41
- getProfiles() {
42
- if (!global.kuzzle) {
43
- return kerror.reject('security', 'user', 'uninitialized', this._id);
35
+ constructor() {
36
+ this._id = null;
37
+ this.profileIds = [];
44
38
  }
45
-
46
- return global.kuzzle.ask('core:security:profile:mGet', this.profileIds);
47
- }
48
-
49
- /**
50
- * @returns {Promise}
51
- */
52
- async getRights() {
53
- const profiles = await this.getProfiles();
54
- const results = await Bluebird.map(profiles, p => p.getRights());
55
-
56
- const rights = {};
57
-
58
- results.forEach(right => _.assignWith(rights, right, Rights.merge));
59
-
60
- return rights;
61
- }
62
-
63
- /**
64
- * @param {Request} request
65
- * @returns {Promise.<boolean>}
66
- */
67
- async isActionAllowed(request) {
68
- if (this.profileIds === undefined || this.profileIds.length === 0) {
69
- return false;
39
+ /**
40
+ * @returns {Promise<Profile[]>}
41
+ */
42
+ getProfiles() {
43
+ if (!global.kuzzle) {
44
+ return kerror_1.default.reject('security', 'user', 'uninitialized', this._id);
45
+ }
46
+ return global.kuzzle.ask('core:security:profile:mGet', this.profileIds);
47
+ }
48
+ /**
49
+ * @returns {Promise}
50
+ */
51
+ async getRights() {
52
+ const profiles = await this.getProfiles();
53
+ const results = await bluebird_1.default.map(profiles, p => p.getRights());
54
+ const rights = {};
55
+ results.forEach(right => lodash_1.default.assignWith(rights, right, rights_1.default.merge));
56
+ return rights;
57
+ }
58
+ /**
59
+ * @param {Request} request
60
+ * @returns {Promise.<boolean>}
61
+ */
62
+ async isActionAllowed(request) {
63
+ if (this.profileIds === undefined || this.profileIds.length === 0) {
64
+ return false;
65
+ }
66
+ const targets = request.getArray('targets', []);
67
+ const profiles = await this.getProfiles();
68
+ if (targets.length === 0) {
69
+ for (const profile of profiles) {
70
+ if (await profile.isActionAllowed(request)) {
71
+ return true;
72
+ }
73
+ }
74
+ return false;
75
+ }
76
+ // Every target must be allowed by at least one profile
77
+ return this.areTargetsAllowed(profiles, targets);
78
+ }
79
+ /**
80
+ * Verifies that every targets are allowed by at least one profile,
81
+ * while skipping the ones that includes a wildcard since they will be expanded
82
+ * later on, based on index and collections authorized for the given user.
83
+ */
84
+ async areTargetsAllowed(profiles, targets) {
85
+ const profilesPolicies = await bluebird_1.default.map(profiles, profile => profile.getAllowedPolicies());
86
+ // Every target must be allowed by at least one profile
87
+ for (const target of targets) {
88
+ // Skip targets with no Index or Collection
89
+ if (!target.index || !target.collections) {
90
+ continue;
91
+ }
92
+ // TODO: Support Wildcard
93
+ if (target.index.includes('*')) {
94
+ return false;
95
+ }
96
+ for (const collection of target.collections) {
97
+ // TODO: Support Wildcard
98
+ if (collection.includes('*')) {
99
+ return false;
100
+ }
101
+ const isTargetAllowed = profilesPolicies.some(policies => policies.some(policy => policy.role.checkRestrictions(target.index, collection, policy.restrictedTo)));
102
+ if (!isTargetAllowed) {
103
+ return false;
104
+ }
105
+ }
106
+ }
107
+ return true;
70
108
  }
71
-
72
- const profiles = await this.getProfiles();
73
- const result = await Bluebird.map(profiles, p => p.isActionAllowed(request));
74
-
75
- return result.includes(true);
76
- }
77
109
  }
78
-
79
- module.exports = User;
110
+ exports.User = User;
111
+ //# sourceMappingURL=user.js.map
@@ -50,7 +50,7 @@ class ApiKey extends BaseModel {
50
50
  }
51
51
  }
52
52
 
53
- serialize ({ includeToken=false } = {}) {
53
+ serialize ({ includeToken = false } = {}) {
54
54
  const serialized = super.serialize();
55
55
 
56
56
  if (! includeToken) {
@@ -90,7 +90,7 @@ class ApiKey extends BaseModel {
90
90
  user,
91
91
  expiresIn,
92
92
  description,
93
- { creatorId=null, apiKeyId=null, refresh, bypassMaxTTL=false } = {}
93
+ { creatorId = null, apiKeyId = null, refresh, bypassMaxTTL = false } = {}
94
94
  ) {
95
95
  const token = await global.kuzzle.ask('core:security:token:create', user, {
96
96
  bypassMaxTTL,
@@ -73,7 +73,7 @@ class BaseModel {
73
73
  *
74
74
  * @returns {Promise}
75
75
  */
76
- async save ({ userId=null, refresh } = {}) {
76
+ async save ({ userId = null, refresh } = {}) {
77
77
  if (! this.__persisted) {
78
78
  const { _id, _source } = await global.kuzzle.internalIndex.create(
79
79
  this.constructor.collection,
@@ -123,7 +123,7 @@ class BaseModel {
123
123
  */
124
124
  serialize () {
125
125
  return {
126
- _id : this._id,
126
+ _id: this._id,
127
127
  _source: this._source
128
128
  };
129
129
  }
@@ -195,7 +195,7 @@ class BaseModel {
195
195
  await Bluebird.map(
196
196
  documents,
197
197
  document => this._instantiateFromDb(document)._afterDelete(),
198
- {concurrency: 10}); // limits the load on storage services
198
+ { concurrency: 10 }); // limits the load on storage services
199
199
 
200
200
  if (refresh) {
201
201
  await global.kuzzle.internalIndex.refreshCollection(this.collection);
@@ -102,7 +102,7 @@ class Redis extends Service {
102
102
  * Setup a ping interval to keep the connection alive
103
103
  * Every 60 seconds a ping is sent to Redis
104
104
  */
105
- _setupKeepAlive(delay) {
105
+ _setupKeepAlive (delay) {
106
106
  this.client.on('ready', async () => {
107
107
  await this._ping();
108
108
  this.pingIntervalID = setInterval(this._ping.bind(this), delay);
@@ -117,7 +117,7 @@ class Redis extends Service {
117
117
  /**
118
118
  * Ping Redis
119
119
  */
120
- async _ping() {
120
+ async _ping () {
121
121
  try {
122
122
  await this.client.ping();
123
123
  }
@@ -134,7 +134,7 @@ class Redis extends Service {
134
134
 
135
135
  for (const command of commandsList) {
136
136
  this.commands[command] = async (...args) => {
137
- if (!this.connected) {
137
+ if (! this.connected) {
138
138
  throw kerror.get('notconnected');
139
139
  }
140
140
 
@@ -156,7 +156,7 @@ class Redis extends Service {
156
156
 
157
157
  arr.forEach(item => {
158
158
  item = item.trim();
159
- if (item.length > 0 && !item.startsWith('#')) {
159
+ if (item.length > 0 && ! item.startsWith('#')) {
160
160
  const keyValuePair = item.split(':');
161
161
  info[keyValuePair[0]] = keyValuePair[1];
162
162
  }
@@ -199,7 +199,7 @@ class Redis extends Service {
199
199
  * @returns {Promise}
200
200
  */
201
201
  mExecute (commands) {
202
- if (!Array.isArray(commands) || commands.length === 0) {
202
+ if (! Array.isArray(commands) || commands.length === 0) {
203
203
  return Bluebird.resolve([]);
204
204
  }
205
205
 
@@ -211,7 +211,7 @@ class Redis extends Service {
211
211
  _searchNodeKeys (node, pattern) {
212
212
  return new Bluebird(resolve => {
213
213
  let keys = [];
214
- const stream = node.scanStream({match: pattern});
214
+ const stream = node.scanStream({ match: pattern });
215
215
 
216
216
  stream.on('data', resultKeys => {
217
217
  keys = keys.concat(resultKeys);
@@ -243,7 +243,7 @@ class Redis extends Service {
243
243
  * @param {{onlyIfNew: boolean, ttl: number}} [options]
244
244
  * @return {boolean} true if the key was set, false otherwise
245
245
  */
246
- async store (key, value, {onlyIfNew = false, ttl = 0} = {}) {
246
+ async store (key, value, { onlyIfNew = false, ttl = 0 } = {}) {
247
247
  const command = [key, value];
248
248
 
249
249
  if (onlyIfNew) {