@flowerforce/flowerbase 1.7.5 → 1.7.6-beta.1
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/README.md +125 -1
- package/dist/auth/controller.d.ts.map +1 -1
- package/dist/auth/controller.js +11 -10
- package/dist/auth/plugins/jwt.js +1 -1
- package/dist/auth/providers/anon-user/controller.js +1 -1
- package/dist/auth/providers/custom-function/controller.d.ts.map +1 -1
- package/dist/auth/providers/custom-function/controller.js +28 -7
- package/dist/auth/providers/local-userpass/controller.d.ts.map +1 -1
- package/dist/auth/providers/local-userpass/controller.js +15 -14
- package/dist/auth/utils.d.ts +1 -0
- package/dist/auth/utils.d.ts.map +1 -1
- package/dist/constants.d.ts +11 -0
- package/dist/constants.d.ts.map +1 -1
- package/dist/constants.js +14 -3
- package/dist/features/encryption/interface.d.ts +36 -0
- package/dist/features/encryption/interface.d.ts.map +1 -0
- package/dist/features/encryption/interface.js +2 -0
- package/dist/features/encryption/utils.d.ts +9 -0
- package/dist/features/encryption/utils.d.ts.map +1 -0
- package/dist/features/encryption/utils.js +34 -0
- package/dist/features/rules/utils.d.ts.map +1 -1
- package/dist/features/rules/utils.js +1 -11
- package/dist/features/triggers/index.d.ts.map +1 -1
- package/dist/features/triggers/index.js +5 -1
- package/dist/features/triggers/utils.js +3 -3
- package/dist/index.d.ts +3 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +9 -4
- package/dist/monitoring/plugin.d.ts.map +1 -1
- package/dist/monitoring/plugin.js +31 -0
- package/dist/monitoring/routes/users.d.ts.map +1 -1
- package/dist/monitoring/routes/users.js +7 -6
- package/dist/monitoring/utils.d.ts.map +1 -1
- package/dist/monitoring/utils.js +5 -4
- package/dist/services/api/index.d.ts +4 -0
- package/dist/services/api/index.d.ts.map +1 -1
- package/dist/services/api/utils.d.ts +1 -0
- package/dist/services/api/utils.d.ts.map +1 -1
- package/dist/services/index.d.ts +4 -0
- package/dist/services/index.d.ts.map +1 -1
- package/dist/services/mongodb-atlas/index.d.ts.map +1 -1
- package/dist/services/mongodb-atlas/index.js +9 -7
- package/dist/services/mongodb-atlas/model.d.ts +2 -1
- package/dist/services/mongodb-atlas/model.d.ts.map +1 -1
- package/dist/shared/handleUserDeletion.js +1 -1
- package/dist/shared/handleUserRegistration.js +2 -2
- package/dist/utils/context/helpers.d.ts +12 -0
- package/dist/utils/context/helpers.d.ts.map +1 -1
- package/dist/utils/index.d.ts +1 -0
- package/dist/utils/index.d.ts.map +1 -1
- package/dist/utils/index.js +14 -3
- package/dist/utils/initializer/exposeRoutes.js +1 -1
- package/dist/utils/initializer/mongodbCSFLE.d.ts +69 -0
- package/dist/utils/initializer/mongodbCSFLE.d.ts.map +1 -0
- package/dist/utils/initializer/mongodbCSFLE.js +131 -0
- package/dist/utils/initializer/registerPlugins.d.ts +5 -1
- package/dist/utils/initializer/registerPlugins.d.ts.map +1 -1
- package/dist/utils/initializer/registerPlugins.js +27 -5
- package/dist/utils/rules-matcher/interface.d.ts +5 -1
- package/dist/utils/rules-matcher/interface.d.ts.map +1 -1
- package/dist/utils/rules-matcher/interface.js +2 -0
- package/dist/utils/rules-matcher/utils.d.ts.map +1 -1
- package/dist/utils/rules-matcher/utils.js +51 -16
- package/package.json +4 -2
- package/src/auth/__tests__/controller.test.ts +1 -0
- package/src/auth/controller.ts +12 -11
- package/src/auth/plugins/jwt.ts +2 -2
- package/src/auth/providers/anon-user/__tests__/controller.test.ts +1 -0
- package/src/auth/providers/anon-user/controller.ts +2 -2
- package/src/auth/providers/custom-function/controller.ts +29 -8
- package/src/auth/providers/local-userpass/controller.ts +16 -15
- package/src/auth/utils.ts +1 -0
- package/src/constants.ts +14 -4
- package/src/features/encryption/interface.ts +46 -0
- package/src/features/encryption/utils.ts +22 -0
- package/src/features/rules/utils.ts +1 -11
- package/src/features/triggers/__tests__/index.test.ts +1 -0
- package/src/features/triggers/index.ts +6 -2
- package/src/features/triggers/utils.ts +4 -4
- package/src/index.ts +10 -2
- package/src/monitoring/plugin.ts +33 -0
- package/src/monitoring/routes/users.ts +8 -7
- package/src/monitoring/ui.collections.js +7 -10
- package/src/monitoring/ui.css +383 -1
- package/src/monitoring/ui.endpoints.js +5 -10
- package/src/monitoring/ui.events.js +4 -6
- package/src/monitoring/ui.functions.js +64 -71
- package/src/monitoring/ui.html +8 -0
- package/src/monitoring/ui.js +189 -0
- package/src/monitoring/ui.shared.js +239 -3
- package/src/monitoring/ui.triggers.js +2 -3
- package/src/monitoring/ui.users.js +5 -9
- package/src/monitoring/utils.ts +6 -5
- package/src/services/mongodb-atlas/index.ts +10 -13
- package/src/services/mongodb-atlas/model.ts +3 -1
- package/src/shared/handleUserDeletion.ts +2 -2
- package/src/shared/handleUserRegistration.ts +3 -3
- package/src/types/fastify-raw-body.d.ts +0 -9
- package/src/utils/__tests__/mongodbCSFLE.test.ts +105 -0
- package/src/utils/__tests__/operators.test.ts +24 -0
- package/src/utils/__tests__/rule.test.ts +39 -0
- package/src/utils/__tests__/rulesMatcherInterfaces.test.ts +2 -0
- package/src/utils/index.ts +12 -1
- package/src/utils/initializer/exposeRoutes.ts +2 -2
- package/src/utils/initializer/mongodbCSFLE.ts +224 -0
- package/src/utils/initializer/registerPlugins.ts +45 -10
- package/src/utils/rules-matcher/interface.ts +5 -1
- package/src/utils/rules-matcher/utils.ts +78 -32
package/README.md
CHANGED
|
@@ -265,8 +265,132 @@ Example
|
|
|
265
265
|
```
|
|
266
266
|
If you're configuring the project from scratch, you can skip ahead to the [Build](#build) step.
|
|
267
267
|
|
|
268
|
-
|
|
268
|
+
## 🔐 7 Client-Side Field Level Encryption (CSFLE)
|
|
269
269
|
|
|
270
|
+
Flowerbase supports MongoDB Client-Side Field Level Encryption. When enabled, sensitive fields are encrypted by the MongoDB driver before writing to MongoDB and decrypted automatically when reading.
|
|
271
|
+
|
|
272
|
+
What Flowerbase does for you:
|
|
273
|
+
|
|
274
|
+
- Loads all `encryption.json` files under `data_sources/mongodb-atlas/**`.
|
|
275
|
+
- Builds the MongoDB `schemaMap` automatically from those files.
|
|
276
|
+
- Resolves each `keyAlias` in your schemas to a real Data Encryption Key (DEK) `keyId`.
|
|
277
|
+
- Ensures DEKs exist in the key vault (creates them if missing).
|
|
278
|
+
- Configures Fastify MongoDB plugin `autoEncryption` with the generated `schemaMap`.
|
|
279
|
+
|
|
280
|
+
### 1. Install encryption drivers
|
|
281
|
+
|
|
282
|
+
Refer to the official MongoDB documentation for CSFLE installation requirements: https://www.mongodb.com/docs/manual/core/csfle/install.
|
|
283
|
+
|
|
284
|
+
It is recommended to use the [**Automatic Encryption Shared Library**](https://www.mongodb.com/docs/manual/core/csfle/reference/install-library/?encryption-component=crypt_shared#std-label-csfle-reference-shared-library-download) instead of mongocryptd.
|
|
285
|
+
|
|
286
|
+
Note that the project should also install [mongodb-client-encryption](https://www.npmjs.com/package/mongodb-client-encryption), matching the mongodb driver version.
|
|
287
|
+
|
|
288
|
+
### 2. Add encryption schema files
|
|
289
|
+
|
|
290
|
+
Create one `encryption.json` per collection you want to encrypt:
|
|
291
|
+
|
|
292
|
+
Path example:
|
|
293
|
+
|
|
294
|
+
```text
|
|
295
|
+
src/data_sources/mongodb-atlas/<database>/<collection>/encryption.json
|
|
296
|
+
```
|
|
297
|
+
|
|
298
|
+
Example:
|
|
299
|
+
|
|
300
|
+
```json
|
|
301
|
+
{
|
|
302
|
+
"database": "appDb",
|
|
303
|
+
"collection": "records",
|
|
304
|
+
"schema": {
|
|
305
|
+
"bsonType": "object",
|
|
306
|
+
"encryptMetadata": {
|
|
307
|
+
"keyAlias": "root-key"
|
|
308
|
+
},
|
|
309
|
+
"properties": {
|
|
310
|
+
"protectedField1": {
|
|
311
|
+
"encrypt": {
|
|
312
|
+
"bsonType": "string",
|
|
313
|
+
"algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random"
|
|
314
|
+
}
|
|
315
|
+
},
|
|
316
|
+
"protectedField2": {
|
|
317
|
+
"encrypt": {
|
|
318
|
+
"bsonType": "string",
|
|
319
|
+
"algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic",
|
|
320
|
+
"keyAlias": "deep-key"
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
```
|
|
327
|
+
|
|
328
|
+
Notes:
|
|
329
|
+
|
|
330
|
+
- `encryptMetadata.keyAlias` applies as default key for that object level.
|
|
331
|
+
- `encrypt.keyAlias` overrides key selection for a specific field.
|
|
332
|
+
- If a field has `encrypt` but no `keyAlias`, MongoDB uses nearest `encryptMetadata`.
|
|
333
|
+
|
|
334
|
+
### 3. Pass `mongodbEncryptionConfig` to `initialize()`
|
|
335
|
+
|
|
336
|
+
`initialize()` accepts `mongodbEncryptionConfig` to configure KMS providers and key vault settings.
|
|
337
|
+
|
|
338
|
+
#### Local KMS provider example (development)
|
|
339
|
+
|
|
340
|
+
```ts
|
|
341
|
+
import { initialize } from "@flowerforce/flowerbase";
|
|
342
|
+
|
|
343
|
+
await initialize({
|
|
344
|
+
projectId: "my-project-id",
|
|
345
|
+
mongodbUrl: process.env.MONGODB_URL,
|
|
346
|
+
jwtSecret: process.env.JWT_SECRET,
|
|
347
|
+
mongodbEncryptionConfig: {
|
|
348
|
+
kmsProviders: [
|
|
349
|
+
{
|
|
350
|
+
provider: "local",
|
|
351
|
+
keyAlias: "root-key",
|
|
352
|
+
config: {
|
|
353
|
+
// 96-byte local master key encoded as base64
|
|
354
|
+
key: process.env.LOCAL_MASTER_KEY_BASE64,
|
|
355
|
+
},
|
|
356
|
+
},
|
|
357
|
+
{
|
|
358
|
+
provider: "local",
|
|
359
|
+
keyAlias: "deep-key",
|
|
360
|
+
config: { key: process.env.LOCAL_MASTER_KEY_BASE64 },
|
|
361
|
+
},
|
|
362
|
+
],
|
|
363
|
+
keyVaultDb: "encryption",
|
|
364
|
+
keyVaultCollection: "__keyVault",
|
|
365
|
+
extraOptions: {
|
|
366
|
+
// Optional: path to crypt shared library
|
|
367
|
+
// cryptSharedLibPath: '/opt/mongo_crypt_v1/lib/mongo_crypt_v1.so'
|
|
368
|
+
},
|
|
369
|
+
},
|
|
370
|
+
});
|
|
371
|
+
```
|
|
372
|
+
|
|
373
|
+
#### AWS KMS provider example
|
|
374
|
+
|
|
375
|
+
```ts
|
|
376
|
+
mongodbEncryptionConfig: {
|
|
377
|
+
kmsProviders: [
|
|
378
|
+
{
|
|
379
|
+
provider: "aws",
|
|
380
|
+
keyAlias: "root-key",
|
|
381
|
+
config: {
|
|
382
|
+
accessKeyId: process.env.AWS_ACCESS_KEY_ID,
|
|
383
|
+
secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY,
|
|
384
|
+
},
|
|
385
|
+
masterKey: {
|
|
386
|
+
key: process.env.AWS_KMS_KEY_ARN,
|
|
387
|
+
region: process.env.AWS_REGION,
|
|
388
|
+
},
|
|
389
|
+
},
|
|
390
|
+
];
|
|
391
|
+
}
|
|
392
|
+
```
|
|
393
|
+
---
|
|
270
394
|
|
|
271
395
|
<a id="migration"></a>
|
|
272
396
|
## 🔄 [Migration Guide](#migration) - Migrating Your Realm Project
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"controller.d.ts","sourceRoot":"","sources":["../../src/auth/controller.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,eAAe,EAAE,MAAM,SAAS,CAAA;AAgBzC;;;;GAIG;AACH,wBAAsB,cAAc,CAAC,GAAG,EAAE,eAAe,
|
|
1
|
+
{"version":3,"file":"controller.d.ts","sourceRoot":"","sources":["../../src/auth/controller.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,eAAe,EAAE,MAAM,SAAS,CAAA;AAgBzC;;;;GAIG;AACH,wBAAsB,cAAc,CAAC,GAAG,EAAE,eAAe,iBA2LxD"}
|
package/dist/auth/controller.js
CHANGED
|
@@ -30,16 +30,17 @@ const unauthorizedSessionError = {
|
|
|
30
30
|
function authController(app) {
|
|
31
31
|
return __awaiter(this, void 0, void 0, function* () {
|
|
32
32
|
const { authCollection, userCollection, refreshTokensCollection } = constants_1.AUTH_CONFIG;
|
|
33
|
-
const
|
|
33
|
+
const authDb = app.mongo.client.db(constants_1.AUTH_DB_NAME);
|
|
34
|
+
const customUserDb = app.mongo.client.db(constants_1.DB_NAME);
|
|
34
35
|
const refreshTokenTtlMs = constants_1.DEFAULT_CONFIG.REFRESH_TOKEN_TTL_DAYS * 24 * 60 * 60 * 1000;
|
|
35
36
|
try {
|
|
36
|
-
yield
|
|
37
|
+
yield authDb.collection(refreshTokensCollection).createIndex({ expiresAt: 1 }, { expireAfterSeconds: 0 });
|
|
37
38
|
}
|
|
38
39
|
catch (error) {
|
|
39
40
|
console.error('Failed to ensure refresh token TTL index', error);
|
|
40
41
|
}
|
|
41
42
|
try {
|
|
42
|
-
yield
|
|
43
|
+
yield authDb.collection(authCollection).createIndex({ email: 1 }, {
|
|
43
44
|
unique: true
|
|
44
45
|
});
|
|
45
46
|
}
|
|
@@ -64,11 +65,11 @@ function authController(app) {
|
|
|
64
65
|
if (req.user.typ !== 'access') {
|
|
65
66
|
throw new Error('Access token required');
|
|
66
67
|
}
|
|
67
|
-
const authUser = yield
|
|
68
|
+
const authUser = yield authDb
|
|
68
69
|
.collection(authCollection)
|
|
69
70
|
.findOne({ _id: bson_1.ObjectId.createFromHexString(req.user.id) });
|
|
70
71
|
const customData = userCollection && constants_1.AUTH_CONFIG.user_id_field
|
|
71
|
-
? yield
|
|
72
|
+
? yield customUserDb
|
|
72
73
|
.collection(userCollection)
|
|
73
74
|
.findOne({ [constants_1.AUTH_CONFIG.user_id_field]: req.user.id })
|
|
74
75
|
: null;
|
|
@@ -112,7 +113,7 @@ function authController(app) {
|
|
|
112
113
|
}
|
|
113
114
|
const refreshToken = authHeader.slice('Bearer '.length).trim();
|
|
114
115
|
const refreshTokenHash = (0, crypto_1.hashToken)(refreshToken);
|
|
115
|
-
const storedToken = yield
|
|
116
|
+
const storedToken = yield authDb.collection(refreshTokensCollection).findOne({
|
|
116
117
|
tokenHash: refreshTokenHash,
|
|
117
118
|
revokedAt: null,
|
|
118
119
|
expiresAt: { $gt: new Date() }
|
|
@@ -121,13 +122,13 @@ function authController(app) {
|
|
|
121
122
|
res.code(401).send(unauthorizedSessionError);
|
|
122
123
|
return;
|
|
123
124
|
}
|
|
124
|
-
const auth_user = yield (
|
|
125
|
+
const auth_user = yield (authDb === null || authDb === void 0 ? void 0 : authDb.collection(authCollection).findOne({ _id: new this.mongo.ObjectId(req.user.sub) }));
|
|
125
126
|
if (!auth_user) {
|
|
126
127
|
res.code(401).send(unauthorizedSessionError);
|
|
127
128
|
return;
|
|
128
129
|
}
|
|
129
130
|
const user = userCollection && constants_1.AUTH_CONFIG.user_id_field
|
|
130
|
-
? (yield
|
|
131
|
+
? (yield customUserDb.collection(userCollection).findOne({ [constants_1.AUTH_CONFIG.user_id_field]: req.user.sub }))
|
|
131
132
|
: {};
|
|
132
133
|
res.status(201);
|
|
133
134
|
return {
|
|
@@ -154,7 +155,7 @@ function authController(app) {
|
|
|
154
155
|
const refreshTokenHash = (0, crypto_1.hashToken)(refreshToken);
|
|
155
156
|
const now = new Date();
|
|
156
157
|
const expiresAt = new Date(Date.now() + refreshTokenTtlMs);
|
|
157
|
-
const updateResult = yield
|
|
158
|
+
const updateResult = yield authDb.collection(refreshTokensCollection).findOneAndUpdate({ tokenHash: refreshTokenHash }, {
|
|
158
159
|
$set: {
|
|
159
160
|
revokedAt: now,
|
|
160
161
|
expiresAt
|
|
@@ -171,7 +172,7 @@ function authController(app) {
|
|
|
171
172
|
}
|
|
172
173
|
}
|
|
173
174
|
if (userId && authCollection) {
|
|
174
|
-
yield
|
|
175
|
+
yield authDb.collection(authCollection).updateOne({ _id: userId }, { $set: { lastLogoutAt: now } });
|
|
175
176
|
}
|
|
176
177
|
return { status: 'ok' };
|
|
177
178
|
});
|
package/dist/auth/plugins/jwt.js
CHANGED
|
@@ -51,7 +51,7 @@ exports.default = (0, fastify_plugin_1.default)(function (fastify, opts) {
|
|
|
51
51
|
if (((_a = request.user) === null || _a === void 0 ? void 0 : _a.typ) !== 'access') {
|
|
52
52
|
return;
|
|
53
53
|
}
|
|
54
|
-
const db = (_c = (_b = fastify.mongo) === null || _b === void 0 ? void 0 : _b.client) === null || _c === void 0 ? void 0 : _c.db(constants_1.
|
|
54
|
+
const db = (_c = (_b = fastify.mongo) === null || _b === void 0 ? void 0 : _b.client) === null || _c === void 0 ? void 0 : _c.db(constants_1.AUTH_DB_NAME);
|
|
55
55
|
if (!db) {
|
|
56
56
|
fastify.log.warn('Mongo client unavailable while checking logout state');
|
|
57
57
|
return;
|
|
@@ -22,7 +22,7 @@ const utils_1 = require("../../utils");
|
|
|
22
22
|
*/
|
|
23
23
|
function anonUserController(app) {
|
|
24
24
|
return __awaiter(this, void 0, void 0, function* () {
|
|
25
|
-
const db = app.mongo.client.db(constants_1.
|
|
25
|
+
const db = app.mongo.client.db(constants_1.AUTH_DB_NAME);
|
|
26
26
|
const { authCollection, refreshTokensCollection } = constants_1.AUTH_CONFIG;
|
|
27
27
|
const refreshTokenTtlMs = constants_1.DEFAULT_CONFIG.REFRESH_TOKEN_TTL_DAYS * 24 * 60 * 60 * 1000;
|
|
28
28
|
const anonUserTtlSeconds = constants_1.DEFAULT_CONFIG.ANON_USER_TTL_SECONDS;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"controller.d.ts","sourceRoot":"","sources":["../../../../src/auth/providers/custom-function/controller.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,SAAS,CAAA;
|
|
1
|
+
{"version":3,"file":"controller.d.ts","sourceRoot":"","sources":["../../../../src/auth/providers/custom-function/controller.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,SAAS,CAAA;AAUzC;;;;GAIG;AACH,wBAAsB,wBAAwB,CAAC,GAAG,EAAE,eAAe,iBAqIlE"}
|
|
@@ -10,6 +10,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
10
10
|
};
|
|
11
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
12
|
exports.customFunctionController = customFunctionController;
|
|
13
|
+
const mongodb_1 = require("mongodb");
|
|
13
14
|
const constants_1 = require("../../../constants");
|
|
14
15
|
const state_1 = require("../../../state");
|
|
15
16
|
const context_1 = require("../../../utils/context");
|
|
@@ -25,7 +26,8 @@ function customFunctionController(app) {
|
|
|
25
26
|
return __awaiter(this, void 0, void 0, function* () {
|
|
26
27
|
const functionsList = state_1.StateManager.select('functions');
|
|
27
28
|
const services = state_1.StateManager.select('services');
|
|
28
|
-
const
|
|
29
|
+
const authDb = app.mongo.client.db(constants_1.AUTH_DB_NAME);
|
|
30
|
+
const customUserDb = app.mongo.client.db(constants_1.DB_NAME);
|
|
29
31
|
const { authCollection, refreshTokensCollection, userCollection, user_id_field } = constants_1.AUTH_CONFIG;
|
|
30
32
|
const refreshTokenTtlMs = constants_1.DEFAULT_CONFIG.REFRESH_TOKEN_TTL_DAYS * 24 * 60 * 60 * 1000;
|
|
31
33
|
/**
|
|
@@ -39,7 +41,7 @@ function customFunctionController(app) {
|
|
|
39
41
|
schema: schema_1.LOGIN_SCHEMA
|
|
40
42
|
}, function (req, reply) {
|
|
41
43
|
return __awaiter(this, void 0, void 0, function* () {
|
|
42
|
-
var _a, _b;
|
|
44
|
+
var _a, _b, _c;
|
|
43
45
|
const customFunctionProvider = (_a = constants_1.AUTH_CONFIG.authProviders) === null || _a === void 0 ? void 0 : _a['custom-function'];
|
|
44
46
|
if (!customFunctionProvider || customFunctionProvider.disabled) {
|
|
45
47
|
throw new Error('Custom function authentication disabled');
|
|
@@ -75,13 +77,32 @@ function customFunctionController(app) {
|
|
|
75
77
|
reply.code(401).send({ message: 'Unauthorized' });
|
|
76
78
|
return;
|
|
77
79
|
}
|
|
78
|
-
const
|
|
80
|
+
const email = (_c = authResult.email) !== null && _c !== void 0 ? _c : authResult.id;
|
|
81
|
+
let authUser = yield authDb.collection(authCollection).findOne({ email });
|
|
79
82
|
if (!authUser) {
|
|
80
|
-
|
|
81
|
-
|
|
83
|
+
const authUserId = new mongodb_1.ObjectId();
|
|
84
|
+
yield authDb.collection(authCollection).insertOne({
|
|
85
|
+
_id: authUserId,
|
|
86
|
+
email,
|
|
87
|
+
status: 'confirmed',
|
|
88
|
+
createdAt: new Date(),
|
|
89
|
+
custom_data: {},
|
|
90
|
+
identities: [
|
|
91
|
+
{
|
|
92
|
+
id: authResult.id.toString(),
|
|
93
|
+
provider_id: authResult.id.toString(),
|
|
94
|
+
provider_type: 'custom-function',
|
|
95
|
+
provider_data: { email }
|
|
96
|
+
}
|
|
97
|
+
]
|
|
98
|
+
});
|
|
99
|
+
authUser = {
|
|
100
|
+
_id: authUserId,
|
|
101
|
+
email
|
|
102
|
+
};
|
|
82
103
|
}
|
|
83
104
|
const user = user_id_field && userCollection
|
|
84
|
-
? yield
|
|
105
|
+
? yield customUserDb
|
|
85
106
|
.collection(userCollection)
|
|
86
107
|
.findOne({ [user_id_field]: authUser._id.toString() })
|
|
87
108
|
: {};
|
|
@@ -92,7 +113,7 @@ function customFunctionController(app) {
|
|
|
92
113
|
};
|
|
93
114
|
const refreshToken = this.createRefreshToken(currentUserData);
|
|
94
115
|
const refreshTokenHash = (0, crypto_1.hashToken)(refreshToken);
|
|
95
|
-
yield
|
|
116
|
+
yield authDb.collection(refreshTokensCollection).insertOne({
|
|
96
117
|
userId: authUser._id,
|
|
97
118
|
tokenHash: refreshTokenHash,
|
|
98
119
|
createdAt: new Date(),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"controller.d.ts","sourceRoot":"","sources":["../../../../src/auth/providers/local-userpass/controller.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,SAAS,CAAA;AAqCzC;;;;GAIG;AACH,wBAAsB,uBAAuB,CAAC,GAAG,EAAE,eAAe,
|
|
1
|
+
{"version":3,"file":"controller.d.ts","sourceRoot":"","sources":["../../../../src/auth/providers/local-userpass/controller.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,SAAS,CAAA;AAqCzC;;;;GAIG;AACH,wBAAsB,uBAAuB,CAAC,GAAG,EAAE,eAAe,iBAqXjE"}
|
|
@@ -40,7 +40,8 @@ function localUserPassController(app) {
|
|
|
40
40
|
const { authCollection, userCollection, user_id_field } = constants_1.AUTH_CONFIG;
|
|
41
41
|
const { resetPasswordCollection } = constants_1.AUTH_CONFIG;
|
|
42
42
|
const { refreshTokensCollection } = constants_1.AUTH_CONFIG;
|
|
43
|
-
const
|
|
43
|
+
const authDb = app.mongo.client.db(constants_1.AUTH_DB_NAME);
|
|
44
|
+
const customUserDb = app.mongo.client.db(constants_1.DB_NAME);
|
|
44
45
|
const resetPasswordTtlSeconds = constants_1.DEFAULT_CONFIG.RESET_PASSWORD_TTL_SECONDS;
|
|
45
46
|
const rateLimitWindowMs = constants_1.DEFAULT_CONFIG.AUTH_RATE_LIMIT_WINDOW_MS;
|
|
46
47
|
const loginMaxAttempts = constants_1.DEFAULT_CONFIG.AUTH_LOGIN_MAX_ATTEMPTS;
|
|
@@ -49,20 +50,20 @@ function localUserPassController(app) {
|
|
|
49
50
|
const refreshTokenTtlMs = constants_1.DEFAULT_CONFIG.REFRESH_TOKEN_TTL_DAYS * 24 * 60 * 60 * 1000;
|
|
50
51
|
const resolveLocalUserpassProvider = () => { var _a; return (_a = constants_1.AUTH_CONFIG.authProviders) === null || _a === void 0 ? void 0 : _a['local-userpass']; };
|
|
51
52
|
try {
|
|
52
|
-
yield
|
|
53
|
+
yield authDb.collection(resetPasswordCollection).createIndex({ createdAt: 1 }, { expireAfterSeconds: resetPasswordTtlSeconds });
|
|
53
54
|
}
|
|
54
55
|
catch (error) {
|
|
55
56
|
console.error('Failed to ensure reset password TTL index', error);
|
|
56
57
|
}
|
|
57
58
|
try {
|
|
58
|
-
yield
|
|
59
|
+
yield authDb.collection(refreshTokensCollection).createIndex({ expiresAt: 1 }, { expireAfterSeconds: 0 });
|
|
59
60
|
}
|
|
60
61
|
catch (error) {
|
|
61
62
|
console.error('Failed to ensure refresh token TTL index', error);
|
|
62
63
|
}
|
|
63
64
|
const handleResetPasswordRequest = (email, password, extraArguments) => __awaiter(this, void 0, void 0, function* () {
|
|
64
65
|
const { resetPasswordConfig } = constants_1.AUTH_CONFIG;
|
|
65
|
-
const authUser = yield
|
|
66
|
+
const authUser = yield authDb.collection(authCollection).findOne({
|
|
66
67
|
email
|
|
67
68
|
});
|
|
68
69
|
if (!authUser) {
|
|
@@ -70,7 +71,7 @@ function localUserPassController(app) {
|
|
|
70
71
|
}
|
|
71
72
|
const token = (0, crypto_1.generateToken)();
|
|
72
73
|
const tokenId = (0, crypto_1.generateToken)();
|
|
73
|
-
yield (
|
|
74
|
+
yield (authDb === null || authDb === void 0 ? void 0 : authDb.collection(resetPasswordCollection).updateOne({ email }, { $set: { token, tokenId, email, createdAt: new Date() } }, { upsert: true }));
|
|
74
75
|
if (!resetPasswordConfig.runResetFunction && !resetPasswordConfig.resetFunctionName) {
|
|
75
76
|
throw new Error(utils_1.AUTH_ERRORS.MISSING_RESET_FUNCTION);
|
|
76
77
|
}
|
|
@@ -156,7 +157,7 @@ function localUserPassController(app) {
|
|
|
156
157
|
res.status(429).send({ message: 'Too many requests' });
|
|
157
158
|
return;
|
|
158
159
|
}
|
|
159
|
-
const existing = yield
|
|
160
|
+
const existing = yield authDb.collection(authCollection).findOne({
|
|
160
161
|
confirmationToken: req.body.token,
|
|
161
162
|
confirmationTokenId: req.body.tokenId
|
|
162
163
|
});
|
|
@@ -165,7 +166,7 @@ function localUserPassController(app) {
|
|
|
165
166
|
throw new Error(utils_1.AUTH_ERRORS.INVALID_TOKEN);
|
|
166
167
|
}
|
|
167
168
|
if (existing.status !== 'confirmed') {
|
|
168
|
-
yield
|
|
169
|
+
yield authDb.collection(authCollection).updateOne({ _id: existing._id }, {
|
|
169
170
|
$set: { status: 'confirmed' },
|
|
170
171
|
$unset: { confirmationToken: '', confirmationTokenId: '' }
|
|
171
172
|
});
|
|
@@ -193,7 +194,7 @@ function localUserPassController(app) {
|
|
|
193
194
|
res.status(429).send({ message: 'Too many requests' });
|
|
194
195
|
return;
|
|
195
196
|
}
|
|
196
|
-
const authUser = yield
|
|
197
|
+
const authUser = yield authDb.collection(authCollection).findOne({
|
|
197
198
|
email: req.body.username
|
|
198
199
|
});
|
|
199
200
|
if (!authUser) {
|
|
@@ -204,7 +205,7 @@ function localUserPassController(app) {
|
|
|
204
205
|
throw new Error(utils_1.AUTH_ERRORS.INVALID_CREDENTIALS);
|
|
205
206
|
}
|
|
206
207
|
const user = user_id_field && userCollection
|
|
207
|
-
? yield
|
|
208
|
+
? yield customUserDb
|
|
208
209
|
.collection(userCollection)
|
|
209
210
|
.findOne({ [user_id_field]: authUser._id.toString() })
|
|
210
211
|
: {};
|
|
@@ -215,7 +216,7 @@ function localUserPassController(app) {
|
|
|
215
216
|
}
|
|
216
217
|
const refreshToken = this.createRefreshToken(userWithCustomData);
|
|
217
218
|
const refreshTokenHash = (0, crypto_1.hashToken)(refreshToken);
|
|
218
|
-
yield
|
|
219
|
+
yield authDb.collection(refreshTokensCollection).insertOne({
|
|
219
220
|
userId: authUser._id,
|
|
220
221
|
tokenHash: refreshTokenHash,
|
|
221
222
|
createdAt: new Date(),
|
|
@@ -298,7 +299,7 @@ function localUserPassController(app) {
|
|
|
298
299
|
return { message: 'Too many requests' };
|
|
299
300
|
}
|
|
300
301
|
const { token, tokenId, password } = req.body;
|
|
301
|
-
const resetRequest = yield (
|
|
302
|
+
const resetRequest = yield (authDb === null || authDb === void 0 ? void 0 : authDb.collection(resetPasswordCollection).findOne({ token, tokenId }));
|
|
302
303
|
if (!resetRequest) {
|
|
303
304
|
throw new Error(utils_1.AUTH_ERRORS.INVALID_RESET_PARAMS);
|
|
304
305
|
}
|
|
@@ -307,16 +308,16 @@ function localUserPassController(app) {
|
|
|
307
308
|
Number.isNaN(createdAt.getTime()) ||
|
|
308
309
|
Date.now() - createdAt.getTime() > resetPasswordTtlSeconds * 1000;
|
|
309
310
|
if (isExpired) {
|
|
310
|
-
yield (
|
|
311
|
+
yield (authDb === null || authDb === void 0 ? void 0 : authDb.collection(resetPasswordCollection).deleteOne({ _id: resetRequest._id }));
|
|
311
312
|
throw new Error(utils_1.AUTH_ERRORS.INVALID_RESET_PARAMS);
|
|
312
313
|
}
|
|
313
314
|
const hashedPassword = yield (0, crypto_1.hashPassword)(password);
|
|
314
|
-
yield
|
|
315
|
+
yield authDb.collection(authCollection).updateOne({ email: resetRequest.email }, {
|
|
315
316
|
$set: {
|
|
316
317
|
password: hashedPassword
|
|
317
318
|
}
|
|
318
319
|
});
|
|
319
|
-
yield (
|
|
320
|
+
yield (authDb === null || authDb === void 0 ? void 0 : authDb.collection(resetPasswordCollection).deleteOne({ _id: resetRequest._id }));
|
|
320
321
|
});
|
|
321
322
|
});
|
|
322
323
|
});
|
package/dist/auth/utils.d.ts
CHANGED
package/dist/auth/utils.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/auth/utils.ts"],"names":[],"mappings":"AAMA,eAAO,MAAM,cAAc;;;CAA4C,CAAC;AACxE,eAAO,MAAM,YAAY;;;;;;;;;;;;;;;;;;;CAexB,CAAA;AAED,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;CAc7B,CAAA;AAED,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;;;;;;;;;CAgB7B,CAAA;AAED,eAAO,MAAM,oBAAoB;;;;;;;;;;;;;;;;;;;CAWhC,CAAA;AAED,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;;CAU/B,CAAA;AAED,eAAO,MAAM,YAAY;;;;;;;;;;;;;;CAAoB,CAAA;AAE7C,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;;;;;;;CAe/B,CAAA;AAED,oBAAY,cAAc;IACxB,KAAK,WAAW;IAChB,YAAY,cAAc;IAC1B,OAAO,aAAa;IACpB,OAAO,aAAa;IACpB,OAAO,aAAa;IACpB,KAAK,gBAAgB;IACrB,UAAU,gBAAgB;IAC1B,aAAa,WAAW;IACxB,UAAU,sBAAsB;CACjC;AAED,oBAAY,WAAW;IACrB,mBAAmB,wBAAwB;IAC3C,aAAa,mCAAmC;IAChD,oBAAoB,sCAAsC;IAC1D,sBAAsB,2BAA2B;IACjD,kBAAkB,uBAAuB;CAC1C;AAED,MAAM,WAAW,UAAU;IACzB,eAAe,CAAC,EAAE,MAAM,CAAA;IACxB,SAAS,EAAE,MAAM,CAAA;IACjB,gBAAgB,EAAE,aAAa,CAAA;IAC/B,iBAAiB,EAAE,cAAc,CAAA;IACjC,WAAW,CAAC,EAAE,QAAQ,CAAA;CACvB;AAED,UAAU,MAAM;IACd,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,MAAM,CAAA;IACZ,QAAQ,EAAE,OAAO,CAAA;CAClB;AACD,UAAU,aAAa;IACrB,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,MAAM,CAAA;IACZ,QAAQ,EAAE,OAAO,CAAA;IACjB,MAAM,EAAE,MAAM,CAAA;CACf;AAED,UAAU,cAAc;IACtB,IAAI,EAAE,iBAAiB,CAAC;IACxB,IAAI,EAAE,iBAAiB,CAAC;IACxB,QAAQ,EAAE,OAAO,CAAC;IAClB,MAAM,EAAE;QACN,kBAAkB,EAAE,MAAM,CAAA;KAC3B,CAAA;CACF;AAED,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,WAAW,CAAA;IACjB,IAAI,EAAE,WAAW,CAAA;IACjB,QAAQ,EAAE,OAAO,CAAA;CAClB;AAED,MAAM,WAAW,MAAM;IACrB,WAAW,EAAE,OAAO,CAAA;IACpB,wBAAwB,CAAC,EAAE,MAAM,CAAA;IACjC,iBAAiB,EAAE,MAAM,CAAA;IACzB,gBAAgB,EAAE,MAAM,CAAA;IACxB,uBAAuB,EAAE,OAAO,CAAA;IAChC,gBAAgB,EAAE,OAAO,CAAA;CAC1B;AAED,MAAM,WAAW,oBAAoB;IACnC,OAAO,EAAE,OAAO,CAAA;IAChB,kBAAkB,EAAE,MAAM,CAAA;IAC1B,aAAa,EAAE,MAAM,CAAA;IACrB,eAAe,EAAE,MAAM,CAAA;IACvB,aAAa,EAAE,MAAM,CAAA;IACrB,8BAA8B,EAAE,MAAM,CAAA;CACvC;AAMD;;;GAGG;AACH,eAAO,MAAM,cAAc,QAAO,UAuCjC,CAAA;AAED;;;GAGG;AACH,eAAO,MAAM,kBAAkB,QAAO,oBAarC,CAAA;AAED,eAAO,MAAM,gBAAgB,GAAI,eAAW,WAG3C,CAAA"}
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/auth/utils.ts"],"names":[],"mappings":"AAMA,eAAO,MAAM,cAAc;;;CAA4C,CAAC;AACxE,eAAO,MAAM,YAAY;;;;;;;;;;;;;;;;;;;CAexB,CAAA;AAED,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;CAc7B,CAAA;AAED,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;;;;;;;;;CAgB7B,CAAA;AAED,eAAO,MAAM,oBAAoB;;;;;;;;;;;;;;;;;;;CAWhC,CAAA;AAED,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;;CAU/B,CAAA;AAED,eAAO,MAAM,YAAY;;;;;;;;;;;;;;CAAoB,CAAA;AAE7C,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;;;;;;;CAe/B,CAAA;AAED,oBAAY,cAAc;IACxB,KAAK,WAAW;IAChB,YAAY,cAAc;IAC1B,OAAO,aAAa;IACpB,OAAO,aAAa;IACpB,OAAO,aAAa;IACpB,KAAK,gBAAgB;IACrB,UAAU,gBAAgB;IAC1B,aAAa,WAAW;IACxB,UAAU,sBAAsB;CACjC;AAED,oBAAY,WAAW;IACrB,mBAAmB,wBAAwB;IAC3C,aAAa,mCAAmC;IAChD,oBAAoB,sCAAsC;IAC1D,sBAAsB,2BAA2B;IACjD,kBAAkB,uBAAuB;CAC1C;AAED,MAAM,WAAW,UAAU;IACzB,eAAe,CAAC,EAAE,MAAM,CAAA;IACxB,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,SAAS,EAAE,MAAM,CAAA;IACjB,gBAAgB,EAAE,aAAa,CAAA;IAC/B,iBAAiB,EAAE,cAAc,CAAA;IACjC,WAAW,CAAC,EAAE,QAAQ,CAAA;CACvB;AAED,UAAU,MAAM;IACd,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,MAAM,CAAA;IACZ,QAAQ,EAAE,OAAO,CAAA;CAClB;AACD,UAAU,aAAa;IACrB,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,MAAM,CAAA;IACZ,QAAQ,EAAE,OAAO,CAAA;IACjB,MAAM,EAAE,MAAM,CAAA;CACf;AAED,UAAU,cAAc;IACtB,IAAI,EAAE,iBAAiB,CAAC;IACxB,IAAI,EAAE,iBAAiB,CAAC;IACxB,QAAQ,EAAE,OAAO,CAAC;IAClB,MAAM,EAAE;QACN,kBAAkB,EAAE,MAAM,CAAA;KAC3B,CAAA;CACF;AAED,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,WAAW,CAAA;IACjB,IAAI,EAAE,WAAW,CAAA;IACjB,QAAQ,EAAE,OAAO,CAAA;CAClB;AAED,MAAM,WAAW,MAAM;IACrB,WAAW,EAAE,OAAO,CAAA;IACpB,wBAAwB,CAAC,EAAE,MAAM,CAAA;IACjC,iBAAiB,EAAE,MAAM,CAAA;IACzB,gBAAgB,EAAE,MAAM,CAAA;IACxB,uBAAuB,EAAE,OAAO,CAAA;IAChC,gBAAgB,EAAE,OAAO,CAAA;CAC1B;AAED,MAAM,WAAW,oBAAoB;IACnC,OAAO,EAAE,OAAO,CAAA;IAChB,kBAAkB,EAAE,MAAM,CAAA;IAC1B,aAAa,EAAE,MAAM,CAAA;IACrB,eAAe,EAAE,MAAM,CAAA;IACvB,aAAa,EAAE,MAAM,CAAA;IACrB,8BAA8B,EAAE,MAAM,CAAA;CACvC;AAMD;;;GAGG;AACH,eAAO,MAAM,cAAc,QAAO,UAuCjC,CAAA;AAED;;;GAGG;AACH,eAAO,MAAM,kBAAkB,QAAO,oBAarC,CAAA;AAED,eAAO,MAAM,gBAAgB,GAAI,eAAW,WAG3C,CAAA"}
|
package/dist/constants.d.ts
CHANGED
|
@@ -33,10 +33,15 @@ export declare const DEFAULT_CONFIG: {
|
|
|
33
33
|
origin: string;
|
|
34
34
|
methods: ALLOWED_METHODS[];
|
|
35
35
|
};
|
|
36
|
+
MONGODB_ENCRYPTION_CONFIG: {
|
|
37
|
+
keyVaultDb: string;
|
|
38
|
+
keyVaultCollection: string;
|
|
39
|
+
};
|
|
36
40
|
};
|
|
37
41
|
export declare const API_VERSION: string;
|
|
38
42
|
export declare const HTTPS_SCHEMA: string;
|
|
39
43
|
export declare const DB_NAME: string;
|
|
44
|
+
export declare const AUTH_DB_NAME: string;
|
|
40
45
|
type AuthProviders = Record<string, {
|
|
41
46
|
disabled?: boolean;
|
|
42
47
|
config?: unknown;
|
|
@@ -62,5 +67,11 @@ export declare const S3_CONFIG: {
|
|
|
62
67
|
ACCESS_KEY_ID: string | undefined;
|
|
63
68
|
SECRET_ACCESS_KEY: string | undefined;
|
|
64
69
|
};
|
|
70
|
+
/**
|
|
71
|
+
* Name of the MongoDB client to use for change streams.
|
|
72
|
+
* This may be a separate instance because streams do not work
|
|
73
|
+
* when the main client has auto encryption enabled.
|
|
74
|
+
*/
|
|
75
|
+
export declare const CHANGESTREAM = "changestream";
|
|
65
76
|
export {};
|
|
66
77
|
//# sourceMappingURL=constants.d.ts.map
|
package/dist/constants.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,eAAe,EAAE,MAAM,IAAI,CAAA;AAsBpC,eAAO,MAAM,cAAc;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAmCsB,eAAe,EAAE
|
|
1
|
+
{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,eAAe,EAAE,MAAM,IAAI,CAAA;AAsBpC,eAAO,MAAM,cAAc;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAmCsB,eAAe,EAAE;;;;;;CAMjE,CAAA;AACD,eAAO,MAAM,WAAW,QAA8C,CAAA;AACtE,eAAO,MAAM,YAAY,QAA8B,CAAA;AACvD,eAAO,MAAM,OAAO,QAAgB,CAAA;AACpC,eAAO,MAAM,YAAY,QAAiC,CAAA;AAE1D,KAAK,aAAa,GAAG,MAAM,CAAC,MAAM,EAAE;IAAE,QAAQ,CAAC,EAAE,OAAO,CAAC;IAAC,MAAM,CAAC,EAAE,OAAO,CAAA;CAAE,CAAC,CAAA;AAE7E,eAAO,MAAM,WAAW;;;;;;;mBAOqB,aAAa;;;;;;;;;CAOzD,CAAA;AAED,eAAO,MAAM,SAAS;;;CAGrB,CAAA;AAED;;;;GAIG;AACH,eAAO,MAAM,YAAY,iBAAiB,CAAA"}
|
package/dist/constants.js
CHANGED
|
@@ -12,7 +12,7 @@ var __rest = (this && this.__rest) || function (s, e) {
|
|
|
12
12
|
};
|
|
13
13
|
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
14
14
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
-
exports.S3_CONFIG = exports.AUTH_CONFIG = exports.DB_NAME = exports.HTTPS_SCHEMA = exports.API_VERSION = exports.DEFAULT_CONFIG = void 0;
|
|
15
|
+
exports.CHANGESTREAM = exports.S3_CONFIG = exports.AUTH_CONFIG = exports.AUTH_DB_NAME = exports.DB_NAME = exports.HTTPS_SCHEMA = exports.API_VERSION = exports.DEFAULT_CONFIG = void 0;
|
|
16
16
|
const utils_1 = require("./auth/utils");
|
|
17
17
|
const parseBoolean = (value) => {
|
|
18
18
|
if (!value)
|
|
@@ -25,8 +25,8 @@ const monitEnabledEnv = process.env.MONIT_ENABLED;
|
|
|
25
25
|
const monitEnabled = typeof monitEnabledEnv === 'string'
|
|
26
26
|
? parseBoolean(monitEnabledEnv)
|
|
27
27
|
: false;
|
|
28
|
-
const { database_name, collection_name = 'users', user_id_field = 'id', on_user_creation_function_name } = (0, utils_1.loadCustomUserData)();
|
|
29
|
-
const _j = (0, utils_1.loadAuthConfig)(), { auth_collection = 'auth_users' } = _j, configuration = __rest(_j, ["auth_collection"]);
|
|
28
|
+
const { database_name = 'main', collection_name = 'users', user_id_field = 'id', on_user_creation_function_name } = (0, utils_1.loadCustomUserData)();
|
|
29
|
+
const _j = (0, utils_1.loadAuthConfig)(), { auth_collection = 'auth_users', auth_database } = _j, configuration = __rest(_j, ["auth_collection", "auth_database"]);
|
|
30
30
|
exports.DEFAULT_CONFIG = {
|
|
31
31
|
PORT: Number(process.env.PORT) || 3000,
|
|
32
32
|
MONGODB_URL: process.env.MONGODB_URL || '',
|
|
@@ -63,11 +63,16 @@ exports.DEFAULT_CONFIG = {
|
|
|
63
63
|
CORS_OPTIONS: {
|
|
64
64
|
origin: "*",
|
|
65
65
|
methods: ["GET", "POST", "PUT", "DELETE"]
|
|
66
|
+
},
|
|
67
|
+
MONGODB_ENCRYPTION_CONFIG: {
|
|
68
|
+
keyVaultDb: "encryption",
|
|
69
|
+
keyVaultCollection: "__keyVault"
|
|
66
70
|
}
|
|
67
71
|
};
|
|
68
72
|
exports.API_VERSION = `/api/client/${exports.DEFAULT_CONFIG.API_VERSION}`;
|
|
69
73
|
exports.HTTPS_SCHEMA = exports.DEFAULT_CONFIG.HTTPS_SCHEMA;
|
|
70
74
|
exports.DB_NAME = database_name;
|
|
75
|
+
exports.AUTH_DB_NAME = auth_database !== null && auth_database !== void 0 ? auth_database : database_name;
|
|
71
76
|
// TODO spostare nell'oggetto providers anche le altre configurazioni
|
|
72
77
|
exports.AUTH_CONFIG = {
|
|
73
78
|
authCollection: auth_collection,
|
|
@@ -88,3 +93,9 @@ exports.S3_CONFIG = {
|
|
|
88
93
|
ACCESS_KEY_ID: process.env.S3_ACCESS_KEY_ID,
|
|
89
94
|
SECRET_ACCESS_KEY: process.env.S3_SECRET_ACCESS_KEY
|
|
90
95
|
};
|
|
96
|
+
/**
|
|
97
|
+
* Name of the MongoDB client to use for change streams.
|
|
98
|
+
* This may be a separate instance because streams do not work
|
|
99
|
+
* when the main client has auto encryption enabled.
|
|
100
|
+
*/
|
|
101
|
+
exports.CHANGESTREAM = "changestream";
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import type { UUID } from "mongodb";
|
|
2
|
+
export type EncryptionSchemaProperty = EncryptionSchema | {
|
|
3
|
+
encrypt: {
|
|
4
|
+
algorithm: string;
|
|
5
|
+
bsonType: string;
|
|
6
|
+
keyAlias?: string;
|
|
7
|
+
};
|
|
8
|
+
};
|
|
9
|
+
export type EncryptionSchema = {
|
|
10
|
+
bsonType: "object";
|
|
11
|
+
properties: Record<string, EncryptionSchemaProperty>;
|
|
12
|
+
encryptMetadata?: {
|
|
13
|
+
keyAlias: string;
|
|
14
|
+
};
|
|
15
|
+
};
|
|
16
|
+
export type MappedEncryptionSchemaProperty = MappedEncryptionSchema | {
|
|
17
|
+
encrypt: {
|
|
18
|
+
algorithm: string;
|
|
19
|
+
bsonType: string;
|
|
20
|
+
keyId?: [UUID];
|
|
21
|
+
};
|
|
22
|
+
};
|
|
23
|
+
export type MappedEncryptionSchema = {
|
|
24
|
+
bsonType: "object";
|
|
25
|
+
properties: Record<string, MappedEncryptionSchemaProperty>;
|
|
26
|
+
encryptMetadata?: {
|
|
27
|
+
keyId: [UUID];
|
|
28
|
+
};
|
|
29
|
+
};
|
|
30
|
+
export type EncryptionSchemaFile = {
|
|
31
|
+
database: string;
|
|
32
|
+
collection: string;
|
|
33
|
+
schema: EncryptionSchema;
|
|
34
|
+
};
|
|
35
|
+
export type EncryptionSchemas = Record<string, EncryptionSchema>;
|
|
36
|
+
//# sourceMappingURL=interface.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"interface.d.ts","sourceRoot":"","sources":["../../../src/features/encryption/interface.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,SAAS,CAAA;AAEnC,MAAM,MAAM,wBAAwB,GAChC,gBAAgB,GAChB;IACA,OAAO,EAAE;QACP,SAAS,EAAE,MAAM,CAAA;QACjB,QAAQ,EAAE,MAAM,CAAA;QAChB,QAAQ,CAAC,EAAE,MAAM,CAAA;KAClB,CAAA;CACF,CAAA;AAEH,MAAM,MAAM,gBAAgB,GAAG;IAC7B,QAAQ,EAAE,QAAQ,CAAA;IAClB,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,wBAAwB,CAAC,CAAA;IACpD,eAAe,CAAC,EAAE;QAChB,QAAQ,EAAE,MAAM,CAAA;KACjB,CAAC;CACH,CAAA;AAGD,MAAM,MAAM,8BAA8B,GACtC,sBAAsB,GACtB;IACA,OAAO,EAAE;QACP,SAAS,EAAE,MAAM,CAAA;QACjB,QAAQ,EAAE,MAAM,CAAA;QAChB,KAAK,CAAC,EAAE,CAAC,IAAI,CAAC,CAAA;KACf,CAAA;CACF,CAAA;AAEH,MAAM,MAAM,sBAAsB,GAAG;IACnC,QAAQ,EAAE,QAAQ,CAAA;IAClB,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,8BAA8B,CAAC,CAAA;IAC1D,eAAe,CAAC,EAAE;QAChB,KAAK,EAAE,CAAC,IAAI,CAAC,CAAA;KACd,CAAC;CACH,CAAA;AAED,MAAM,MAAM,oBAAoB,GAAG;IACjC,QAAQ,EAAE,MAAM,CAAA;IAChB,UAAU,EAAE,MAAM,CAAA;IAClB,MAAM,EAAE,gBAAgB,CAAA;CACzB,CAAA;AAED,MAAM,MAAM,iBAAiB,GAAG,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAA"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { EncryptionSchemas } from "./interface";
|
|
2
|
+
/**
|
|
3
|
+
* @experimental
|
|
4
|
+
* Schemas used for Client-Side Level Encryption configuration.
|
|
5
|
+
*
|
|
6
|
+
* **Important:** These schemas do not perform JSON validation.
|
|
7
|
+
*/
|
|
8
|
+
export declare const loadEncryptionSchemas: (rootDir?: string) => Promise<EncryptionSchemas>;
|
|
9
|
+
//# sourceMappingURL=utils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../src/features/encryption/utils.ts"],"names":[],"mappings":"AAEA,OAAO,EAAwB,iBAAiB,EAAE,MAAM,aAAa,CAAA;AAErE;;;;;GAKG;AACH,eAAO,MAAM,qBAAqB,GAAU,gBAAuB,KAAG,OAAO,CAAC,iBAAiB,CAW9F,CAAA"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
12
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
13
|
+
};
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
exports.loadEncryptionSchemas = void 0;
|
|
16
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
17
|
+
const utils_1 = require("../../utils");
|
|
18
|
+
/**
|
|
19
|
+
* @experimental
|
|
20
|
+
* Schemas used for Client-Side Level Encryption configuration.
|
|
21
|
+
*
|
|
22
|
+
* **Important:** These schemas do not perform JSON validation.
|
|
23
|
+
*/
|
|
24
|
+
const loadEncryptionSchemas = (...args_1) => __awaiter(void 0, [...args_1], void 0, function* (rootDir = process.cwd()) {
|
|
25
|
+
const schemasRoot = node_path_1.default.join(rootDir, 'data_sources', 'mongodb-atlas');
|
|
26
|
+
const files = (0, utils_1.recursivelyCollectFiles)(schemasRoot);
|
|
27
|
+
const schemaFiles = files.filter((x) => x.endsWith('encryption.json'));
|
|
28
|
+
return schemaFiles.reduce((acc, filePath) => {
|
|
29
|
+
const { collection, database, schema } = (0, utils_1.readJsonContent)(filePath);
|
|
30
|
+
acc[`${database}.${collection}`] = schema;
|
|
31
|
+
return acc;
|
|
32
|
+
}, {});
|
|
33
|
+
});
|
|
34
|
+
exports.loadEncryptionSchemas = loadEncryptionSchemas;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../src/features/rules/utils.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../src/features/rules/utils.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,EAAe,MAAM,aAAa,CAAA;AAEhD,eAAO,MAAM,SAAS,GAAU,gBAAuB,KAAG,OAAO,CAAC,KAAK,CA6BtE,CAAA"}
|