@flowerforce/flowerbase 1.7.6-beta.0 → 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.
Files changed (63) hide show
  1. package/README.md +125 -1
  2. package/dist/auth/providers/custom-function/controller.d.ts.map +1 -1
  3. package/dist/auth/providers/custom-function/controller.js +3 -8
  4. package/dist/constants.d.ts +10 -0
  5. package/dist/constants.d.ts.map +1 -1
  6. package/dist/constants.js +11 -1
  7. package/dist/features/encryption/interface.d.ts +36 -0
  8. package/dist/features/encryption/interface.d.ts.map +1 -0
  9. package/dist/features/encryption/interface.js +2 -0
  10. package/dist/features/encryption/utils.d.ts +9 -0
  11. package/dist/features/encryption/utils.d.ts.map +1 -0
  12. package/dist/features/encryption/utils.js +34 -0
  13. package/dist/features/rules/utils.d.ts.map +1 -1
  14. package/dist/features/rules/utils.js +1 -11
  15. package/dist/features/triggers/index.d.ts.map +1 -1
  16. package/dist/features/triggers/index.js +4 -0
  17. package/dist/features/triggers/utils.d.ts.map +1 -1
  18. package/dist/features/triggers/utils.js +30 -38
  19. package/dist/index.d.ts +3 -1
  20. package/dist/index.d.ts.map +1 -1
  21. package/dist/index.js +9 -4
  22. package/dist/monitoring/plugin.d.ts.map +1 -1
  23. package/dist/monitoring/plugin.js +31 -0
  24. package/dist/services/mongodb-atlas/index.d.ts.map +1 -1
  25. package/dist/services/mongodb-atlas/index.js +9 -7
  26. package/dist/services/mongodb-atlas/model.d.ts +2 -1
  27. package/dist/services/mongodb-atlas/model.d.ts.map +1 -1
  28. package/dist/utils/index.d.ts +1 -0
  29. package/dist/utils/index.d.ts.map +1 -1
  30. package/dist/utils/index.js +14 -3
  31. package/dist/utils/initializer/mongodbCSFLE.d.ts +69 -0
  32. package/dist/utils/initializer/mongodbCSFLE.d.ts.map +1 -0
  33. package/dist/utils/initializer/mongodbCSFLE.js +131 -0
  34. package/dist/utils/initializer/registerPlugins.d.ts +5 -1
  35. package/dist/utils/initializer/registerPlugins.d.ts.map +1 -1
  36. package/dist/utils/initializer/registerPlugins.js +27 -5
  37. package/package.json +4 -2
  38. package/src/auth/providers/custom-function/controller.ts +4 -10
  39. package/src/constants.ts +11 -2
  40. package/src/features/encryption/interface.ts +46 -0
  41. package/src/features/encryption/utils.ts +22 -0
  42. package/src/features/rules/utils.ts +1 -11
  43. package/src/features/triggers/index.ts +5 -1
  44. package/src/features/triggers/utils.ts +31 -42
  45. package/src/index.ts +10 -2
  46. package/src/monitoring/plugin.ts +33 -0
  47. package/src/monitoring/ui.collections.js +7 -10
  48. package/src/monitoring/ui.css +378 -0
  49. package/src/monitoring/ui.endpoints.js +5 -10
  50. package/src/monitoring/ui.events.js +2 -4
  51. package/src/monitoring/ui.functions.js +64 -71
  52. package/src/monitoring/ui.html +8 -0
  53. package/src/monitoring/ui.js +189 -0
  54. package/src/monitoring/ui.shared.js +237 -2
  55. package/src/monitoring/ui.triggers.js +2 -3
  56. package/src/monitoring/ui.users.js +5 -9
  57. package/src/services/mongodb-atlas/index.ts +10 -13
  58. package/src/services/mongodb-atlas/model.ts +3 -1
  59. package/src/types/fastify-raw-body.d.ts +0 -9
  60. package/src/utils/__tests__/mongodbCSFLE.test.ts +105 -0
  61. package/src/utils/index.ts +12 -1
  62. package/src/utils/initializer/mongodbCSFLE.ts +224 -0
  63. package/src/utils/initializer/registerPlugins.ts +45 -10
@@ -32,6 +32,7 @@ const utils_1 = require("../../monitoring/utils");
32
32
  const machines_1 = require("../../utils/roles/machines");
33
33
  const utils_2 = require("../../utils/roles/machines/utils");
34
34
  const monitoring_1 = require("../monitoring");
35
+ const constants_1 = require("../../constants");
35
36
  const model_1 = require("./model");
36
37
  const utils_3 = require("./utils");
37
38
  //TODO aggiungere no-sql inject security
@@ -333,8 +334,9 @@ const areUpdatedFieldsAllowed = (filtered, updated, updatedPaths) => {
333
334
  return (0, isEqual_1.default)(filtered, updated);
334
335
  return updatedPaths.every((path) => (0, isEqual_1.default)((0, get_1.default)(filtered, path), (0, get_1.default)(updated, path)));
335
336
  };
336
- const getOperators = (collection, { rules, collName, user, run_as_system, monitoringOrigin }) => {
337
+ const getOperators = (mongo, { rules, dbName, collName, user, run_as_system, monitoringOrigin }) => {
337
338
  var _a, _b;
339
+ const collection = mongo.client.db(dbName).collection(collName);
338
340
  const normalizedRules = rules !== null && rules !== void 0 ? rules : {};
339
341
  const collectionRules = normalizedRules[collName];
340
342
  const filters = (_a = collectionRules === null || collectionRules === void 0 ? void 0 : collectionRules.filters) !== null && _a !== void 0 ? _a : [];
@@ -852,6 +854,7 @@ const getOperators = (collection, { rules, collName, user, run_as_system, monito
852
854
  * This allows fine-grained control over what change events a user can observe, based on roles and filters.
853
855
  */
854
856
  watch: (pipelineOrOptions = [], options) => {
857
+ const changestreamCollection = mongo[constants_1.CHANGESTREAM].client.db(dbName).collection(collName);
855
858
  try {
856
859
  const { pipeline, options: watchOptions, extraMatches } = resolveWatchArgs(pipelineOrOptions, options);
857
860
  if (!run_as_system) {
@@ -867,7 +870,7 @@ const getOperators = (collection, { rules, collName, user, run_as_system, monito
867
870
  }
868
871
  : undefined;
869
872
  const formattedPipeline = [firstStep, ...extraMatches, ...pipeline].filter(Boolean);
870
- const result = collection.watch(formattedPipeline, watchOptions);
873
+ const result = changestreamCollection.watch(formattedPipeline, watchOptions);
871
874
  const originalOn = result.on.bind(result);
872
875
  /**
873
876
  * Validates a change event against the user's roles.
@@ -917,7 +920,7 @@ const getOperators = (collection, { rules, collName, user, run_as_system, monito
917
920
  return result;
918
921
  }
919
922
  // System mode: no filtering applied
920
- const result = collection.watch([...extraMatches, ...pipeline], watchOptions);
923
+ const result = changestreamCollection.watch([...extraMatches, ...pipeline], watchOptions);
921
924
  emitMongoEvent('watch');
922
925
  return result;
923
926
  }
@@ -1138,11 +1141,10 @@ const MongodbAtlas = (app, { rules, user, run_as_system, monitoring } = {}) => (
1138
1141
  db: (dbName) => {
1139
1142
  return {
1140
1143
  collection: (collName) => {
1141
- const mongoClient = app.mongo.client;
1142
- const collection = mongoClient.db(dbName).collection(collName);
1143
- return getOperators(collection, {
1144
- rules,
1144
+ return getOperators(app.mongo, {
1145
+ dbName,
1145
1146
  collName,
1147
+ rules,
1146
1148
  user,
1147
1149
  run_as_system,
1148
1150
  monitoringOrigin: monitoring === null || monitoring === void 0 ? void 0 : monitoring.invokedFrom
@@ -22,10 +22,11 @@ export type GetValidRuleParams<T extends Role | Filter> = {
22
22
  record?: WithId<Document> | Document | null;
23
23
  };
24
24
  type Method<T extends keyof Collection<Document>> = Collection<Document>[T];
25
- export type GetOperatorsFunction = (collection: Collection<Document>, { rules, collName, user, run_as_system, monitoringOrigin }: {
25
+ export type GetOperatorsFunction = (mongoInstance: FastifyInstance["mongo"], { rules, dbName, collName, user, run_as_system, monitoringOrigin }: {
26
26
  user?: User;
27
27
  rules?: Rules;
28
28
  run_as_system?: boolean;
29
+ dbName: string;
29
30
  collName: string;
30
31
  monitoringOrigin?: string;
31
32
  }) => {
@@ -1 +1 @@
1
- {"version":3,"file":"model.d.ts","sourceRoot":"","sources":["../../../src/services/mongodb-atlas/model.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"model.d.ts","sourceRoot":"","sources":["../../../src/services/mongodb-atlas/model.ts"],"names":[],"mappings":"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"}
@@ -1,3 +1,4 @@
1
1
  export declare const readFileContent: (filePath: string) => string;
2
2
  export declare const readJsonContent: (filePath: string) => unknown;
3
+ export declare const recursivelyCollectFiles: (dir: string) => string[];
3
4
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,eAAe,GAAI,UAAU,MAAM,WAAuC,CAAA;AACvF,eAAO,MAAM,eAAe,GAAI,UAAU,MAAM,KACL,OAAO,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,eAAe,GAAI,UAAU,MAAM,WAAuC,CAAA;AACvF,eAAO,MAAM,eAAe,GAAI,UAAU,MAAM,KACL,OAAO,CAAA;AAElD,eAAO,MAAM,uBAAuB,GAAI,KAAK,MAAM,KAAG,MAAM,EAQ3D,CAAA"}
@@ -3,9 +3,20 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.readJsonContent = exports.readFileContent = void 0;
7
- const fs_1 = __importDefault(require("fs"));
8
- const readFileContent = (filePath) => fs_1.default.readFileSync(filePath, 'utf-8');
6
+ exports.recursivelyCollectFiles = exports.readJsonContent = exports.readFileContent = void 0;
7
+ const node_fs_1 = __importDefault(require("node:fs"));
8
+ const node_path_1 = __importDefault(require("node:path"));
9
+ const readFileContent = (filePath) => node_fs_1.default.readFileSync(filePath, 'utf-8');
9
10
  exports.readFileContent = readFileContent;
10
11
  const readJsonContent = (filePath) => JSON.parse((0, exports.readFileContent)(filePath));
11
12
  exports.readJsonContent = readJsonContent;
13
+ const recursivelyCollectFiles = (dir) => {
14
+ return node_fs_1.default.readdirSync(dir, { withFileTypes: true }).flatMap((entry) => {
15
+ const fullPath = node_path_1.default.join(dir, entry.name);
16
+ if (entry.isDirectory()) {
17
+ return (0, exports.recursivelyCollectFiles)(fullPath);
18
+ }
19
+ return entry.isFile() ? [fullPath] : [];
20
+ });
21
+ };
22
+ exports.recursivelyCollectFiles = recursivelyCollectFiles;
@@ -0,0 +1,69 @@
1
+ import { UUID, type Document, type AWSEncryptionKeyOptions, type AWSKMSProviderConfiguration, type AzureEncryptionKeyOptions, type AzureKMSProviderConfiguration, type GCPKMSProviderConfiguration, type GCPEncryptionKeyOptions, type KMIPKMSProviderConfiguration, type KMIPEncryptionKeyOptions, type LocalKMSProviderConfiguration, type AutoEncryptionExtraOptions, type AutoEncryptionOptions } from "mongodb";
2
+ import { type EncryptionSchemas } from "../../features/encryption/interface";
3
+ type KMSProviderConfig = {
4
+ /**
5
+ * The alias of the key. It must be referenced in the schema map
6
+ * to select which key to use for encryption.
7
+ */
8
+ keyAlias: string;
9
+ /**
10
+ * KMS Provider name.
11
+ */
12
+ provider: "aws";
13
+ /**
14
+ * KMS Provider specific authorization configuration.
15
+ */
16
+ config: AWSKMSProviderConfiguration;
17
+ /**
18
+ * Configuration of the master key.
19
+ */
20
+ masterKey: AWSEncryptionKeyOptions;
21
+ } | {
22
+ keyAlias: string;
23
+ provider: "azure";
24
+ config: AzureKMSProviderConfiguration;
25
+ masterKey: AzureEncryptionKeyOptions;
26
+ } | {
27
+ keyAlias: string;
28
+ provider: "gcp";
29
+ config: GCPKMSProviderConfiguration;
30
+ masterKey: GCPEncryptionKeyOptions;
31
+ } | {
32
+ keyAlias: string;
33
+ provider: "kmip";
34
+ config: KMIPKMSProviderConfiguration;
35
+ masterKey: KMIPEncryptionKeyOptions;
36
+ } | {
37
+ keyAlias: string;
38
+ provider: "local";
39
+ config: LocalKMSProviderConfiguration;
40
+ };
41
+ export type MongoDbEncryptionConfig = {
42
+ kmsProviders: KMSProviderConfig[];
43
+ /**
44
+ * The Key Vault database name
45
+ * @default encryption
46
+ */
47
+ keyVaultDb?: string;
48
+ /**
49
+ * The Key Vault database collection
50
+ * @default __keyVault
51
+ */
52
+ keyVaultCollection?: string;
53
+ extraOptions?: AutoEncryptionExtraOptions;
54
+ };
55
+ type DataKey = {
56
+ dataKeyId: UUID;
57
+ dataKeyAlias: string;
58
+ };
59
+ export declare const buildSchemaMap: (schemas: EncryptionSchemas, dataKeys: DataKey[]) => Record<string, Document>;
60
+ /**
61
+ * Setup MongoDB Client-Side Field Level Encryption (CSFLE).
62
+ * @see https://www.mongodb.com/docs/manual/core/csfle
63
+ */
64
+ export declare const setupMongoDbCSFLE: (config: MongoDbEncryptionConfig & {
65
+ mongodbUrl: string;
66
+ schemas?: EncryptionSchemas;
67
+ }) => Promise<AutoEncryptionOptions>;
68
+ export {};
69
+ //# sourceMappingURL=mongodbCSFLE.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mongodbCSFLE.d.ts","sourceRoot":"","sources":["../../../src/utils/initializer/mongodbCSFLE.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,IAAI,EAEJ,KAAK,QAAQ,EACb,KAAK,uBAAuB,EAC5B,KAAK,2BAA2B,EAChC,KAAK,yBAAyB,EAC9B,KAAK,6BAA6B,EAClC,KAAK,2BAA2B,EAChC,KAAK,uBAAuB,EAC5B,KAAK,4BAA4B,EACjC,KAAK,wBAAwB,EAC7B,KAAK,6BAA6B,EAClC,KAAK,0BAA0B,EAE/B,KAAK,qBAAqB,EAC3B,MAAM,SAAS,CAAC;AACjB,OAAO,EAAoF,KAAK,iBAAiB,EAAE,MAAM,qCAAqC,CAAC;AAG/J,KAAK,iBAAiB,GAClB;IACA;;;OAGG;IACH,QAAQ,EAAE,MAAM,CAAA;IAChB;;OAEG;IACH,QAAQ,EAAE,KAAK,CAAA;IACf;;OAEG;IACH,MAAM,EAAE,2BAA2B,CAAA;IACnC;;OAEG;IACH,SAAS,EAAE,uBAAuB,CAAA;CACnC,GAAG;IACF,QAAQ,EAAE,MAAM,CAAA;IAChB,QAAQ,EAAE,OAAO,CAAA;IACjB,MAAM,EAAE,6BAA6B,CAAC;IACtC,SAAS,EAAE,yBAAyB,CAAA;CACrC,GAAG;IACF,QAAQ,EAAE,MAAM,CAAA;IAChB,QAAQ,EAAE,KAAK,CAAA;IACf,MAAM,EAAE,2BAA2B,CAAC;IACpC,SAAS,EAAE,uBAAuB,CAAA;CACnC,GAAG;IACF,QAAQ,EAAE,MAAM,CAAA;IAChB,QAAQ,EAAE,MAAM,CAAA;IAChB,MAAM,EAAE,4BAA4B,CAAC;IACrC,SAAS,EAAE,wBAAwB,CAAA;CACpC,GAAG;IACF,QAAQ,EAAE,MAAM,CAAA;IAChB,QAAQ,EAAE,OAAO,CAAA;IACjB,MAAM,EAAE,6BAA6B,CAAC;CACvC,CAAA;AAEH,MAAM,MAAM,uBAAuB,GAAG;IACpC,YAAY,EAAE,iBAAiB,EAAE,CAAC;IAClC;;;OAGG;IACH,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB;;;KAGC;IACD,kBAAkB,CAAC,EAAE,MAAM,CAAA;IAC3B,YAAY,CAAC,EAAE,0BAA0B,CAAA;CAC1C,CAAA;AAOD,KAAK,OAAO,GAAG;IAAE,SAAS,EAAE,IAAI,CAAC;IAAC,YAAY,EAAE,MAAM,CAAA;CAAE,CAAA;AAkFxD,eAAO,MAAM,cAAc,GAAI,SAAS,iBAAiB,EAAE,UAAU,OAAO,EAAE,6BAK7E,CAAA;AAED;;;GAGG;AACH,eAAO,MAAM,iBAAiB,GAC5B,QAAQ,uBAAuB,GAAG;IAAE,UAAU,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,iBAAiB,CAAA;CAAE,KACpF,OAAO,CAAC,qBAAqB,CA8C/B,CAAA"}
@@ -0,0 +1,131 @@
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
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.setupMongoDbCSFLE = exports.buildSchemaMap = void 0;
13
+ const mongodb_1 = require("mongodb");
14
+ const constants_1 = require("../../constants");
15
+ function ensureUniqueKeyAltNameIndex(db, config) {
16
+ return __awaiter(this, void 0, void 0, function* () {
17
+ yield db.collection(config.keyVaultCollection).createIndex({ keyAltNames: 1 }, {
18
+ unique: true,
19
+ partialFilterExpression: { keyAltNames: { $exists: true } },
20
+ });
21
+ });
22
+ }
23
+ /**
24
+ * Ensure provided KMS Providers DEK keys exist in the key vault. If not, they are created.
25
+ */
26
+ function ensureDataEncryptionKeys(clientEncryption, keyVaultDb, config) {
27
+ return __awaiter(this, void 0, void 0, function* () {
28
+ const keys = [];
29
+ for (const kmsProvider of config.kmsProviders) {
30
+ const existingKey = yield keyVaultDb.collection(config.keyVaultCollection).findOne({
31
+ keyAltNames: kmsProvider.keyAlias,
32
+ });
33
+ if ((existingKey === null || existingKey === void 0 ? void 0 : existingKey._id) instanceof mongodb_1.Binary) {
34
+ keys.push({ dataKeyId: existingKey._id, dataKeyAlias: kmsProvider.keyAlias });
35
+ continue;
36
+ }
37
+ const dataKeyId = yield clientEncryption.createDataKey(kmsProvider.provider, {
38
+ masterKey: "masterKey" in kmsProvider ? kmsProvider.masterKey : undefined,
39
+ keyAltNames: [kmsProvider.keyAlias],
40
+ });
41
+ console.log(`[MongoDB Encryption] Created new key with alias ${kmsProvider.keyAlias}`);
42
+ keys.push({ dataKeyId, dataKeyAlias: kmsProvider.keyAlias });
43
+ }
44
+ return keys;
45
+ });
46
+ }
47
+ /**
48
+ * Recursively resolve key aliases in an encryption schema to their corresponding key IDs.
49
+ */
50
+ const resolveKeyAliases = (schema, dataKeys) => {
51
+ var _a, _b;
52
+ if ("encrypt" in schema) {
53
+ if (!schema.encrypt.keyAlias) {
54
+ return schema;
55
+ }
56
+ const keyId = (_a = dataKeys.find(k => k.dataKeyAlias === schema.encrypt.keyAlias)) === null || _a === void 0 ? void 0 : _a.dataKeyId;
57
+ if (!keyId) {
58
+ throw new Error(`Key with alias ${schema.encrypt.keyAlias} could not be found in the Key Vault.`);
59
+ }
60
+ return {
61
+ encrypt: {
62
+ bsonType: schema.encrypt.bsonType,
63
+ algorithm: schema.encrypt.algorithm,
64
+ keyId: [keyId]
65
+ }
66
+ };
67
+ }
68
+ const mappedSchema = {
69
+ bsonType: "object",
70
+ properties: Object.entries(schema.properties).reduce((acc, [property, config]) => {
71
+ acc[property] = resolveKeyAliases(config, dataKeys);
72
+ return acc;
73
+ }, {})
74
+ };
75
+ if (schema.encryptMetadata) {
76
+ const keyId = (_b = dataKeys.find(k => k.dataKeyAlias === schema.encryptMetadata.keyAlias)) === null || _b === void 0 ? void 0 : _b.dataKeyId;
77
+ if (!keyId) {
78
+ throw new Error(`Key with alias ${schema.encryptMetadata.keyAlias} could not be found in the Key Vault.`);
79
+ }
80
+ mappedSchema.encryptMetadata = { keyId: [keyId] };
81
+ }
82
+ return mappedSchema;
83
+ };
84
+ const buildSchemaMap = (schemas, dataKeys) => {
85
+ return Object.entries(schemas).reduce((acc, [key, schema]) => {
86
+ acc[key] = resolveKeyAliases(schema, dataKeys);
87
+ return acc;
88
+ }, {});
89
+ };
90
+ exports.buildSchemaMap = buildSchemaMap;
91
+ /**
92
+ * Setup MongoDB Client-Side Field Level Encryption (CSFLE).
93
+ * @see https://www.mongodb.com/docs/manual/core/csfle
94
+ */
95
+ const setupMongoDbCSFLE = (config) => __awaiter(void 0, void 0, void 0, function* () {
96
+ var _a, _b;
97
+ if (config.kmsProviders.length === 0) {
98
+ throw new Error('At least one KMS Provider is required when using MongoDB encryption');
99
+ }
100
+ const requiredConfig = {
101
+ kmsProviders: config.kmsProviders,
102
+ keyVaultDb: (_a = config.keyVaultDb) !== null && _a !== void 0 ? _a : constants_1.DEFAULT_CONFIG.MONGODB_ENCRYPTION_CONFIG.keyVaultDb,
103
+ keyVaultCollection: (_b = config.keyVaultDb) !== null && _b !== void 0 ? _b : constants_1.DEFAULT_CONFIG.MONGODB_ENCRYPTION_CONFIG.keyVaultCollection,
104
+ };
105
+ const kmsProviders = requiredConfig.kmsProviders.reduce((acc, { provider, config }) => (Object.assign(Object.assign({}, acc), { [provider]: config })), {});
106
+ const keyVaultNamespace = `${requiredConfig.keyVaultDb}.${requiredConfig.keyVaultCollection}`;
107
+ const keyVaultClient = new mongodb_1.MongoClient(config.mongodbUrl, {
108
+ maxPoolSize: 1,
109
+ autoEncryption: {
110
+ keyVaultNamespace,
111
+ kmsProviders,
112
+ extraOptions: config.extraOptions
113
+ }
114
+ });
115
+ yield keyVaultClient.connect();
116
+ const keyVaultDb = keyVaultClient.db(requiredConfig.keyVaultDb);
117
+ yield ensureUniqueKeyAltNameIndex(keyVaultDb, requiredConfig);
118
+ const clientEncryption = new mongodb_1.ClientEncryption(keyVaultClient, {
119
+ keyVaultNamespace,
120
+ kmsProviders,
121
+ });
122
+ const dataKeys = yield ensureDataEncryptionKeys(clientEncryption, keyVaultDb, requiredConfig);
123
+ yield keyVaultClient.close();
124
+ return {
125
+ keyVaultNamespace,
126
+ kmsProviders,
127
+ schemaMap: config.schemas ? (0, exports.buildSchemaMap)(config.schemas, dataKeys) : undefined,
128
+ extraOptions: config.extraOptions
129
+ };
130
+ });
131
+ exports.setupMongoDbCSFLE = setupMongoDbCSFLE;
@@ -1,6 +1,8 @@
1
1
  import { FastifyInstance } from 'fastify';
2
2
  import { CorsConfig } from '../../';
3
3
  import { Functions } from '../../features/functions/interface';
4
+ import { EncryptionSchemas } from '../../features/encryption/interface';
5
+ import { MongoDbEncryptionConfig } from './mongodbCSFLE';
4
6
  type RegisterFunction = FastifyInstance['register'];
5
7
  type RegisterPluginsParams = {
6
8
  register: RegisterFunction;
@@ -8,6 +10,8 @@ type RegisterPluginsParams = {
8
10
  jwtSecret: string;
9
11
  functionsList: Functions;
10
12
  corsConfig?: CorsConfig;
13
+ encryptionSchemas?: EncryptionSchemas;
14
+ mongodbEncryptionConfig?: MongoDbEncryptionConfig;
11
15
  };
12
16
  /**
13
17
  * > Used to register all plugins
@@ -16,6 +20,6 @@ type RegisterPluginsParams = {
16
20
  * @param jwtSecret -> connection jwt
17
21
  * @tested
18
22
  */
19
- export declare const registerPlugins: ({ register, mongodbUrl, jwtSecret, functionsList, corsConfig }: RegisterPluginsParams) => Promise<void>;
23
+ export declare const registerPlugins: ({ register, mongodbUrl, jwtSecret, functionsList, corsConfig, mongodbEncryptionConfig, encryptionSchemas }: RegisterPluginsParams) => Promise<void>;
20
24
  export {};
21
25
  //# sourceMappingURL=registerPlugins.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"registerPlugins.d.ts","sourceRoot":"","sources":["../../../src/utils/initializer/registerPlugins.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,eAAe,EAAE,MAAM,SAAS,CAAA;AAEzC,OAAO,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAA;AAOnC,OAAO,EAAE,SAAS,EAAE,MAAM,oCAAoC,CAAA;AAG9D,KAAK,gBAAgB,GAAG,eAAe,CAAC,UAAU,CAAC,CAAA;AAGnD,KAAK,qBAAqB,GAAG;IAC3B,QAAQ,EAAE,gBAAgB,CAAA;IAC1B,UAAU,EAAE,MAAM,CAAA;IAClB,SAAS,EAAE,MAAM,CAAA;IACjB,aAAa,EAAE,SAAS,CAAA;IACxB,UAAU,CAAC,EAAE,UAAU,CAAA;CACxB,CAAA;AAQD;;;;;;GAMG;AACH,eAAO,MAAM,eAAe,GAAU,gEAMnC,qBAAqB,kBAsBvB,CAAA"}
1
+ {"version":3,"file":"registerPlugins.d.ts","sourceRoot":"","sources":["../../../src/utils/initializer/registerPlugins.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,eAAe,EAAE,MAAM,SAAS,CAAA;AAEzC,OAAO,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAA;AAOnC,OAAO,EAAE,SAAS,EAAE,MAAM,oCAAoC,CAAA;AAC9D,OAAO,EAAE,iBAAiB,EAAE,MAAM,qCAAqC,CAAA;AAEvE,OAAO,EAAqB,uBAAuB,EAAE,MAAM,gBAAgB,CAAA;AAE3E,KAAK,gBAAgB,GAAG,eAAe,CAAC,UAAU,CAAC,CAAA;AAGnD,KAAK,qBAAqB,GAAG;IAC3B,QAAQ,EAAE,gBAAgB,CAAA;IAC1B,UAAU,EAAE,MAAM,CAAA;IAClB,SAAS,EAAE,MAAM,CAAA;IACjB,aAAa,EAAE,SAAS,CAAA;IACxB,UAAU,CAAC,EAAE,UAAU,CAAA;IACvB,iBAAiB,CAAC,EAAE,iBAAiB,CAAA;IACrC,uBAAuB,CAAC,EAAE,uBAAuB,CAAA;CAClD,CAAA;AAQD;;;;;;GAMG;AACH,eAAO,MAAM,eAAe,GAAU,4GAQnC,qBAAqB,kBAwBvB,CAAA"}
@@ -23,6 +23,7 @@ const controller_3 = require("../../auth/providers/custom-function/controller");
23
23
  const controller_4 = require("../../auth/providers/local-userpass/controller");
24
24
  const constants_1 = require("../../constants");
25
25
  const plugin_1 = __importDefault(require("../../monitoring/plugin"));
26
+ const mongodbCSFLE_1 = require("./mongodbCSFLE");
26
27
  /**
27
28
  * > Used to register all plugins
28
29
  * @param register -> the fastify register method
@@ -30,13 +31,15 @@ const plugin_1 = __importDefault(require("../../monitoring/plugin"));
30
31
  * @param jwtSecret -> connection jwt
31
32
  * @tested
32
33
  */
33
- const registerPlugins = (_a) => __awaiter(void 0, [_a], void 0, function* ({ register, mongodbUrl, jwtSecret, functionsList, corsConfig }) {
34
+ const registerPlugins = (_a) => __awaiter(void 0, [_a], void 0, function* ({ register, mongodbUrl, jwtSecret, functionsList, corsConfig, mongodbEncryptionConfig, encryptionSchemas }) {
34
35
  try {
35
36
  const registersConfig = yield getRegisterConfig({
36
37
  mongodbUrl,
37
38
  jwtSecret,
38
39
  corsConfig,
39
- functionsList
40
+ functionsList,
41
+ mongodbEncryptionConfig,
42
+ encryptionSchemas
40
43
  });
41
44
  registersConfig.forEach(({ plugin, options, pluginName }) => {
42
45
  try {
@@ -61,11 +64,14 @@ exports.registerPlugins = registerPlugins;
61
64
  * @param jwtSecret -> connection jwt
62
65
  * @testable
63
66
  */
64
- const getRegisterConfig = (_a) => __awaiter(void 0, [_a], void 0, function* ({ mongodbUrl, jwtSecret, corsConfig }) {
67
+ const getRegisterConfig = (_a) => __awaiter(void 0, [_a], void 0, function* ({ mongodbUrl, jwtSecret, corsConfig, encryptionSchemas, mongodbEncryptionConfig, }) {
65
68
  const corsOptions = corsConfig !== null && corsConfig !== void 0 ? corsConfig : {
66
69
  origin: '*',
67
70
  methods: ['POST', 'GET']
68
71
  };
72
+ const autoEncryption = mongodbEncryptionConfig
73
+ ? yield (0, mongodbCSFLE_1.setupMongoDbCSFLE)(Object.assign({ mongodbUrl, schemas: encryptionSchemas }, mongodbEncryptionConfig))
74
+ : undefined;
69
75
  const baseConfig = [
70
76
  {
71
77
  pluginName: 'cors',
@@ -76,8 +82,24 @@ const getRegisterConfig = (_a) => __awaiter(void 0, [_a], void 0, function* ({ m
76
82
  pluginName: 'fastifyMongodb',
77
83
  plugin: mongodb_1.default,
78
84
  options: {
85
+ url: mongodbUrl,
79
86
  forceClose: true,
80
- url: mongodbUrl
87
+ autoEncryption
88
+ }
89
+ },
90
+ /**
91
+ * When auto-encryption is active, add another MongoDB client with bypass for change streams.
92
+ * The $changeStream operator does not support automatic encryption, only decryption.
93
+ * @see https://www.mongodb.com/docs/manual/core/csfle/reference/supported-operations
94
+ */
95
+ autoEncryption && {
96
+ pluginName: 'fastifyMongodb',
97
+ plugin: mongodb_1.default,
98
+ options: {
99
+ name: "changestream",
100
+ url: mongodbUrl,
101
+ forceClose: true,
102
+ autoEncryption: Object.assign(Object.assign({}, autoEncryption), { bypassAutoEncryption: true })
81
103
  }
82
104
  },
83
105
  {
@@ -133,5 +155,5 @@ const getRegisterConfig = (_a) => __awaiter(void 0, [_a], void 0, function* ({ m
133
155
  options: { basePath: '/monit' }
134
156
  });
135
157
  }
136
- return baseConfig;
158
+ return baseConfig.filter(Boolean);
137
159
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@flowerforce/flowerbase",
3
- "version": "1.7.6-beta.0",
3
+ "version": "1.7.6-beta.1",
4
4
  "description": "",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -14,7 +14,8 @@
14
14
  "scripts": {
15
15
  "test": "npx jest",
16
16
  "build": "rm -rf dist/ && tsc",
17
- "start": "node dist/src/index.ts"
17
+ "start": "node dist/src/index.ts",
18
+ "tsc:noemit": "tsc --noEmit"
18
19
  },
19
20
  "keywords": [],
20
21
  "author": "",
@@ -30,6 +31,7 @@
30
31
  "@fastify/swagger-ui": "^5.2.3",
31
32
  "@fastify/websocket": "^11.2.0",
32
33
  "bson": "^6.8.0",
34
+ "codemirror": "^5.65.16",
33
35
  "dotenv": "^16.4.7",
34
36
  "fastify": "^5.0.0",
35
37
  "fastify-plugin": "^5.0.1",
@@ -32,10 +32,7 @@ export async function customFunctionController(app: FastifyInstance) {
32
32
  app.post<LoginDto>(
33
33
  AUTH_ENDPOINTS.LOGIN,
34
34
  {
35
- schema: LOGIN_SCHEMA,
36
- errorHandler: (_error, _request, reply) => {
37
- reply.code(500).send({ message: 'Internal Server Error' })
38
- }
35
+ schema: LOGIN_SCHEMA
39
36
  },
40
37
  async function (req, reply) {
41
38
  const customFunctionProvider = AUTH_CONFIG.authProviders?.['custom-function']
@@ -82,6 +79,7 @@ export async function customFunctionController(app: FastifyInstance) {
82
79
  }
83
80
  }) as CustomFunctionAuthResult
84
81
 
82
+
85
83
  if (!authResult.id) {
86
84
  reply.code(401).send({ message: 'Unauthorized' })
87
85
  return
@@ -130,7 +128,6 @@ export async function customFunctionController(app: FastifyInstance) {
130
128
  ...(user || {})
131
129
  }
132
130
  }
133
-
134
131
  const refreshToken = this.createRefreshToken(currentUserData)
135
132
  const refreshTokenHash = hashToken(refreshToken)
136
133
  await authDb.collection(refreshTokensCollection).insertOne({
@@ -140,15 +137,12 @@ export async function customFunctionController(app: FastifyInstance) {
140
137
  expiresAt: new Date(Date.now() + refreshTokenTtlMs),
141
138
  revokedAt: null
142
139
  })
143
- const accessToken = this.createAccessToken(currentUserData)
144
-
145
- const responsePayload = {
146
- access_token: accessToken,
140
+ return {
141
+ access_token: this.createAccessToken(currentUserData),
147
142
  refresh_token: refreshToken,
148
143
  device_id: '',
149
144
  user_id: authUser._id.toString()
150
145
  }
151
- reply.code(200).send(responsePayload)
152
146
  }
153
147
  )
154
148
 
package/src/constants.ts CHANGED
@@ -57,6 +57,10 @@ export const DEFAULT_CONFIG = {
57
57
  CORS_OPTIONS: {
58
58
  origin: "*",
59
59
  methods: ["GET", "POST", "PUT", "DELETE"] as ALLOWED_METHODS[]
60
+ },
61
+ MONGODB_ENCRYPTION_CONFIG: {
62
+ keyVaultDb: "encryption",
63
+ keyVaultCollection: "__keyVault"
60
64
  }
61
65
  }
62
66
  export const API_VERSION = `/api/client/${DEFAULT_CONFIG.API_VERSION}`
@@ -82,9 +86,14 @@ export const AUTH_CONFIG = {
82
86
  }
83
87
  }
84
88
 
85
-
86
-
87
89
  export const S3_CONFIG = {
88
90
  ACCESS_KEY_ID: process.env.S3_ACCESS_KEY_ID,
89
91
  SECRET_ACCESS_KEY: process.env.S3_SECRET_ACCESS_KEY
90
92
  }
93
+
94
+ /**
95
+ * Name of the MongoDB client to use for change streams.
96
+ * This may be a separate instance because streams do not work
97
+ * when the main client has auto encryption enabled.
98
+ */
99
+ export const CHANGESTREAM = "changestream"
@@ -0,0 +1,46 @@
1
+ import type { UUID } from "mongodb"
2
+
3
+ export type EncryptionSchemaProperty =
4
+ | EncryptionSchema
5
+ | {
6
+ encrypt: {
7
+ algorithm: string
8
+ bsonType: string
9
+ keyAlias?: string
10
+ }
11
+ }
12
+
13
+ export type EncryptionSchema = {
14
+ bsonType: "object"
15
+ properties: Record<string, EncryptionSchemaProperty>
16
+ encryptMetadata?: {
17
+ keyAlias: string
18
+ },
19
+ }
20
+
21
+
22
+ export type MappedEncryptionSchemaProperty =
23
+ | MappedEncryptionSchema
24
+ | {
25
+ encrypt: {
26
+ algorithm: string
27
+ bsonType: string
28
+ keyId?: [UUID]
29
+ }
30
+ }
31
+
32
+ export type MappedEncryptionSchema = {
33
+ bsonType: "object"
34
+ properties: Record<string, MappedEncryptionSchemaProperty>
35
+ encryptMetadata?: {
36
+ keyId: [UUID]
37
+ },
38
+ }
39
+
40
+ export type EncryptionSchemaFile = {
41
+ database: string
42
+ collection: string
43
+ schema: EncryptionSchema
44
+ }
45
+
46
+ export type EncryptionSchemas = Record<string, EncryptionSchema>
@@ -0,0 +1,22 @@
1
+ import path from "node:path"
2
+ import { readJsonContent, recursivelyCollectFiles } from "../../utils"
3
+ import { EncryptionSchemaFile, EncryptionSchemas } from "./interface"
4
+
5
+ /**
6
+ * @experimental
7
+ * Schemas used for Client-Side Level Encryption configuration.
8
+ *
9
+ * **Important:** These schemas do not perform JSON validation.
10
+ */
11
+ export const loadEncryptionSchemas = async (rootDir = process.cwd()): Promise<EncryptionSchemas> => {
12
+ const schemasRoot = path.join(rootDir, 'data_sources', 'mongodb-atlas')
13
+
14
+ const files = recursivelyCollectFiles(schemasRoot)
15
+ const schemaFiles = files.filter((x) => x.endsWith('encryption.json'))
16
+
17
+ return schemaFiles.reduce((acc, filePath) => {
18
+ const { collection, database, schema } = readJsonContent(filePath) as EncryptionSchemaFile
19
+ acc[`${database}.${collection}`] = schema
20
+ return acc
21
+ }, {} as EncryptionSchemas)
22
+ }
@@ -1,19 +1,9 @@
1
- import fs from 'fs'
2
1
  import path from 'node:path'
3
- import { readJsonContent } from '../../utils'
2
+ import { readJsonContent, recursivelyCollectFiles } from '../../utils'
4
3
  import { Rules, RulesConfig } from './interface'
5
4
 
6
5
  export const loadRules = async (rootDir = process.cwd()): Promise<Rules> => {
7
6
  const rulesRoot = path.join(rootDir, 'data_sources', 'mongodb-atlas')
8
- const recursivelyCollectFiles = (dir: string): string[] => {
9
- return fs.readdirSync(dir, { withFileTypes: true }).flatMap((entry) => {
10
- const fullPath = path.join(dir, entry.name)
11
- if (entry.isDirectory()) {
12
- return recursivelyCollectFiles(fullPath)
13
- }
14
- return entry.isFile() ? [fullPath] : []
15
- })
16
- }
17
7
  const files = recursivelyCollectFiles(rulesRoot)
18
8
  const rulesFiles = files.filter((x) => (x as string).endsWith('rules.json'))
19
9
 
@@ -1,4 +1,4 @@
1
- import { AUTH_CONFIG, AUTH_DB_NAME } from '../../constants'
1
+ import { AUTH_CONFIG, AUTH_DB_NAME, CHANGESTREAM } from '../../constants'
2
2
  import { services } from '../../services'
3
3
  import { Function, Functions } from '../functions/interface'
4
4
  import { ActivateTriggersParams } from './dtos'
@@ -18,6 +18,10 @@ export const activateTriggers = async ({
18
18
  }: ActivateTriggersParams) => {
19
19
  console.log('START ACTIVATION TRIGGERS')
20
20
  try {
21
+ // Ensure the changestream MongoDB client exist, or use the main client
22
+ if (!fastify.mongo[CHANGESTREAM]) {
23
+ fastify.mongo[CHANGESTREAM] = fastify.mongo
24
+ }
21
25
  const triggersToActivate = [...triggersList]
22
26
  if (AUTH_CONFIG.on_user_creation_function_name) {
23
27
  const alreadyDeclared = triggersToActivate.some(