@flowerforce/flowerbase 1.8.4-beta.4 → 1.8.4-beta.5
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 +3 -0
- package/dist/auth/plugins/jwt.d.ts +1 -1
- package/dist/auth/plugins/jwt.d.ts.map +1 -1
- package/dist/features/functions/controller.d.ts.map +1 -1
- package/dist/features/functions/controller.js +29 -2
- package/dist/features/functions/dtos.d.ts +2 -0
- package/dist/features/functions/dtos.d.ts.map +1 -1
- package/dist/features/functions/interface.d.ts +2 -0
- package/dist/features/functions/interface.d.ts.map +1 -1
- package/dist/features/functions/utils.d.ts +3 -1
- package/dist/features/functions/utils.d.ts.map +1 -1
- package/dist/features/functions/utils.js +3 -1
- package/dist/services/index.d.ts +8 -8
- package/dist/services/mongodb-atlas/index.d.ts.map +1 -1
- package/dist/services/mongodb-atlas/index.js +91 -20
- package/dist/services/mongodb-atlas/model.d.ts +2 -0
- package/dist/services/mongodb-atlas/model.d.ts.map +1 -1
- package/dist/utils/context/helpers.d.ts +24 -24
- package/dist/utils/roles/machines/read/D/validators.d.ts +1 -1
- package/dist/utils/roles/machines/read/D/validators.d.ts.map +1 -1
- package/dist/utils/roles/machines/write/C/validators.d.ts +1 -1
- package/dist/utils/roles/machines/write/C/validators.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/features/functions/__tests__/controller.test.ts +42 -2
- package/src/features/functions/__tests__/utils.test.ts +44 -0
- package/src/features/functions/controller.ts +36 -1
- package/src/features/functions/dtos.ts +2 -0
- package/src/features/functions/interface.ts +2 -0
- package/src/features/functions/utils.ts +13 -0
- package/src/services/mongodb-atlas/__tests__/realmCompatibility.test.ts +116 -0
- package/src/services/mongodb-atlas/index.ts +122 -25
- package/src/services/mongodb-atlas/model.ts +8 -0
- package/tsconfig.json +0 -5
- package/tsconfig.spec.json +2 -1
package/README.md
CHANGED
|
@@ -652,6 +652,7 @@ const todos = user.mongoClient('mongodb-atlas')
|
|
|
652
652
|
|
|
653
653
|
await todos.insertOne({ title: 'Ship docs update', done: false })
|
|
654
654
|
const openTodos = await todos.find({ done: false })
|
|
655
|
+
const labels = await todos.distinct('label', { done: false })
|
|
655
656
|
```
|
|
656
657
|
|
|
657
658
|
`@flowerforce/flowerbase-client` supports:
|
|
@@ -661,6 +662,8 @@ const openTodos = await todos.find({ done: false })
|
|
|
661
662
|
- change streams with `watch()` async iterator
|
|
662
663
|
- BSON/EJSON interoperability (`ObjectId`, `Date`, etc.)
|
|
663
664
|
|
|
665
|
+
`bulkWrite()` is available on the MongoDB Atlas wrapper only for privileged functions executed with `run_as_system: true`. Regular client-scoped calls continue to use the per-operation methods (`insertOne`, `updateOne`, `updateMany`, `deleteOne`, `deleteMany`, `insertMany`).
|
|
666
|
+
|
|
664
667
|
## 💡 Use Cases by Feature
|
|
665
668
|
|
|
666
669
|
### 🔐 Authentication
|
|
@@ -9,6 +9,6 @@ type Options = {
|
|
|
9
9
|
* @param {Object} opts - Options for the plugin.
|
|
10
10
|
* @param {string} opts.secret - The secret key used for signing JWTs.
|
|
11
11
|
*/
|
|
12
|
-
declare const _default: (fastify: import("fastify
|
|
12
|
+
declare const _default: (fastify: import("fastify").FastifyInstance<import("fastify").RawServerDefault, import("http").IncomingMessage, import("http").ServerResponse<import("http").IncomingMessage>, import("fastify").FastifyBaseLogger, import("fastify").FastifyTypeProviderDefault>, opts: Options) => Promise<void>;
|
|
13
13
|
export default _default;
|
|
14
14
|
//# sourceMappingURL=jwt.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"jwt.d.ts","sourceRoot":"","sources":["../../../src/auth/plugins/jwt.ts"],"names":[],"mappings":"AAKA,KAAK,OAAO,GAAG;IACb,MAAM,EAAE,MAAM,CAAA;CACf,CAAA;AAkBD;;;;;;;GAOG;
|
|
1
|
+
{"version":3,"file":"jwt.d.ts","sourceRoot":"","sources":["../../../src/auth/plugins/jwt.ts"],"names":[],"mappings":"AAKA,KAAK,OAAO,GAAG;IACb,MAAM,EAAE,MAAM,CAAA;CACf,CAAA;AAkBD;;;;;;;GAOG;iSAC8C,OAAO;AAAxD,wBA4GE"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"controller.d.ts","sourceRoot":"","sources":["../../../src/features/functions/controller.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAA;AAKvC,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAA;
|
|
1
|
+
{"version":3,"file":"controller.d.ts","sourceRoot":"","sources":["../../../src/features/functions/controller.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAA;AAKvC,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAA;AA0IhD,eAAO,MAAM,iCAAiC,GAAI,OAAO,OAAO,KAAG,OA0BlE,CAAA;AAID,eAAO,MAAM,6BAA6B,GAAI,OAAO,OAAO,KAAG,OAgD9D,CAAA;AAqHD,eAAO,MAAM,oCAAoC,GAAI,QAAQ,QAAQ,YAClC,CAAA;AAEnC;;;;;GAKG;AACH,eAAO,MAAM,mBAAmB,EAAE,kBAsSjC,CAAA"}
|
|
@@ -26,6 +26,24 @@ const constants_1 = require("../../constants");
|
|
|
26
26
|
const services_1 = require("../../services");
|
|
27
27
|
const context_1 = require("../../utils/context");
|
|
28
28
|
const utils_1 = require("./utils");
|
|
29
|
+
const SUPPORTED_QUERY_METHODS = [
|
|
30
|
+
'find',
|
|
31
|
+
'findOne',
|
|
32
|
+
'count',
|
|
33
|
+
'countDocuments',
|
|
34
|
+
'distinct',
|
|
35
|
+
'deleteOne',
|
|
36
|
+
'insertOne',
|
|
37
|
+
'updateOne',
|
|
38
|
+
'findOneAndUpdate',
|
|
39
|
+
'aggregate',
|
|
40
|
+
'insertMany',
|
|
41
|
+
'bulkWrite',
|
|
42
|
+
'updateMany',
|
|
43
|
+
'deleteMany'
|
|
44
|
+
];
|
|
45
|
+
const isSupportedQueryMethod = (value) => typeof value === 'string' &&
|
|
46
|
+
SUPPORTED_QUERY_METHODS.includes(value);
|
|
29
47
|
const normalizeUser = (payload) => {
|
|
30
48
|
var _a, _b, _c, _d, _e, _f;
|
|
31
49
|
if (!payload)
|
|
@@ -290,7 +308,10 @@ const functionsController = (app_1, _a) => __awaiter(void 0, [app_1, _a], void 0
|
|
|
290
308
|
if (!serviceFn) {
|
|
291
309
|
throw new Error(`Service "${req.body.service}" does not exist`);
|
|
292
310
|
}
|
|
293
|
-
const [{ database, collection, query, filter, update, projection, options, returnNewDocument, document, documents, pipeline = [] }] = args;
|
|
311
|
+
const [{ database, collection, key, query, filter, update, projection, options, returnNewDocument, document, documents, operations, pipeline = [] }] = args;
|
|
312
|
+
if (!isSupportedQueryMethod(method)) {
|
|
313
|
+
throw new Error(`Unsupported service method "${String(method)}"`);
|
|
314
|
+
}
|
|
294
315
|
const currentMethod = serviceFn(app, { rules, user })
|
|
295
316
|
.db(database)
|
|
296
317
|
.collection(collection)[method];
|
|
@@ -298,6 +319,7 @@ const functionsController = (app_1, _a) => __awaiter(void 0, [app_1, _a], void 0
|
|
|
298
319
|
const operatorsByType = yield (0, utils_1.executeQuery)({
|
|
299
320
|
currentMethod,
|
|
300
321
|
query,
|
|
322
|
+
key,
|
|
301
323
|
filter,
|
|
302
324
|
update,
|
|
303
325
|
projection,
|
|
@@ -305,10 +327,15 @@ const functionsController = (app_1, _a) => __awaiter(void 0, [app_1, _a], void 0
|
|
|
305
327
|
returnNewDocument,
|
|
306
328
|
document,
|
|
307
329
|
documents,
|
|
330
|
+
operations,
|
|
308
331
|
pipeline,
|
|
309
332
|
isClient: true
|
|
310
333
|
});
|
|
311
|
-
const
|
|
334
|
+
const operator = operatorsByType[method];
|
|
335
|
+
if (typeof operator !== 'function') {
|
|
336
|
+
throw new Error(`Unsupported service method "${method}"`);
|
|
337
|
+
}
|
|
338
|
+
const serviceResult = yield operator();
|
|
312
339
|
res.type('application/json');
|
|
313
340
|
return serializeEjson(serviceResult);
|
|
314
341
|
}
|
|
@@ -17,6 +17,7 @@ export type FunctionCallBase64Dto = {
|
|
|
17
17
|
type ArgumentsData = Arguments<{
|
|
18
18
|
database: string;
|
|
19
19
|
collection: string;
|
|
20
|
+
key?: string;
|
|
20
21
|
filter?: Document;
|
|
21
22
|
query: Parameters<GetOperatorsFunction>;
|
|
22
23
|
update: Document;
|
|
@@ -25,6 +26,7 @@ type ArgumentsData = Arguments<{
|
|
|
25
26
|
returnNewDocument?: boolean;
|
|
26
27
|
document: Document;
|
|
27
28
|
documents: Document[];
|
|
29
|
+
operations?: Document[];
|
|
28
30
|
pipeline?: Document[];
|
|
29
31
|
}>;
|
|
30
32
|
export type Base64Function = {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dtos.d.ts","sourceRoot":"","sources":["../../../src/features/functions/dtos.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAA;AAClC,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAA;AAC3C,OAAO,EAAE,oBAAoB,EAAE,MAAM,oCAAoC,CAAA;AAEzE,KAAK,UAAU,GAAG,OAAO,CAAC,MAAM,UAAU,CAAC,oBAAoB,CAAC,EAAE,OAAO,CAAC,CAAA;AAE1E,MAAM,MAAM,eAAe,GACvB;IACA,IAAI,EAAE,UAAU,CAAA;IAChB,SAAS,EAAE,aAAa,CAAA;CACzB,GACC;IACA,SAAS,EAAE,aAAa,CAAA;IACxB,IAAI,EAAE,UAAU,CAAA;IAChB,OAAO,EAAE,eAAe,CAAA;CACzB,CAAA;AAEH,MAAM,MAAM,qBAAqB,GAAG;IAClC,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,cAAc,CAAC,EAAE,MAAM,CAAA;CACxB,CAAA;AAED,KAAK,aAAa,GAAG,SAAS,CAAC;IAC7B,QAAQ,EAAE,MAAM,CAAA;IAChB,UAAU,EAAE,MAAM,CAAA;IAClB,MAAM,CAAC,EAAE,QAAQ,CAAA;IACjB,KAAK,EAAE,UAAU,CAAC,oBAAoB,CAAC,CAAA;IACvC,MAAM,EAAE,QAAQ,CAAA;IAChB,UAAU,CAAC,EAAE,QAAQ,CAAA;IACrB,OAAO,CAAC,EAAE,QAAQ,CAAA;IAClB,iBAAiB,CAAC,EAAE,OAAO,CAAA;IAC3B,QAAQ,EAAE,QAAQ,CAAA;IAClB,SAAS,EAAE,QAAQ,EAAE,CAAA;IACrB,QAAQ,CAAC,EAAE,QAAQ,EAAE,CAAA;CACtB,CAAC,CAAA;AAEF,MAAM,MAAM,cAAc,GAAG;IAC3B,IAAI,EAAE,MAAM,CAAA;IACZ,SAAS,EAAE,QAAQ,EAAE,CAAA;IACrB,OAAO,EAAE,MAAM,CAAA;CAChB,CAAA;AAED,KAAK,QAAQ,GAAG;IACd,QAAQ,EAAE,MAAM,CAAA;IAChB,UAAU,EAAE,MAAM,CAAA;CACnB,CAAA"}
|
|
1
|
+
{"version":3,"file":"dtos.d.ts","sourceRoot":"","sources":["../../../src/features/functions/dtos.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAA;AAClC,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAA;AAC3C,OAAO,EAAE,oBAAoB,EAAE,MAAM,oCAAoC,CAAA;AAEzE,KAAK,UAAU,GAAG,OAAO,CAAC,MAAM,UAAU,CAAC,oBAAoB,CAAC,EAAE,OAAO,CAAC,CAAA;AAE1E,MAAM,MAAM,eAAe,GACvB;IACA,IAAI,EAAE,UAAU,CAAA;IAChB,SAAS,EAAE,aAAa,CAAA;CACzB,GACC;IACA,SAAS,EAAE,aAAa,CAAA;IACxB,IAAI,EAAE,UAAU,CAAA;IAChB,OAAO,EAAE,eAAe,CAAA;CACzB,CAAA;AAEH,MAAM,MAAM,qBAAqB,GAAG;IAClC,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,cAAc,CAAC,EAAE,MAAM,CAAA;CACxB,CAAA;AAED,KAAK,aAAa,GAAG,SAAS,CAAC;IAC7B,QAAQ,EAAE,MAAM,CAAA;IAChB,UAAU,EAAE,MAAM,CAAA;IAClB,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,MAAM,CAAC,EAAE,QAAQ,CAAA;IACjB,KAAK,EAAE,UAAU,CAAC,oBAAoB,CAAC,CAAA;IACvC,MAAM,EAAE,QAAQ,CAAA;IAChB,UAAU,CAAC,EAAE,QAAQ,CAAA;IACrB,OAAO,CAAC,EAAE,QAAQ,CAAA;IAClB,iBAAiB,CAAC,EAAE,OAAO,CAAA;IAC3B,QAAQ,EAAE,QAAQ,CAAA;IAClB,SAAS,EAAE,QAAQ,EAAE,CAAA;IACrB,UAAU,CAAC,EAAE,QAAQ,EAAE,CAAA;IACvB,QAAQ,CAAC,EAAE,QAAQ,EAAE,CAAA;CACtB,CAAC,CAAA;AAEF,MAAM,MAAM,cAAc,GAAG;IAC3B,IAAI,EAAE,MAAM,CAAA;IACZ,SAAS,EAAE,QAAQ,EAAE,CAAA;IACrB,OAAO,EAAE,MAAM,CAAA;CAChB,CAAA;AAED,KAAK,QAAQ,GAAG;IACd,QAAQ,EAAE,MAAM,CAAA;IAChB,UAAU,EAAE,MAAM,CAAA;CACnB,CAAA"}
|
|
@@ -22,12 +22,14 @@ export type ExecuteQueryParams = {
|
|
|
22
22
|
currentMethod: ReturnType<GetOperatorsFunction>[keyof ReturnType<GetOperatorsFunction>];
|
|
23
23
|
query: Parameters<GetOperatorsFunction>;
|
|
24
24
|
update: Document;
|
|
25
|
+
key?: string;
|
|
25
26
|
filter?: Document;
|
|
26
27
|
projection?: Document;
|
|
27
28
|
options?: Document;
|
|
28
29
|
returnNewDocument?: boolean;
|
|
29
30
|
document: Document;
|
|
30
31
|
documents: Document[];
|
|
32
|
+
operations?: Document[];
|
|
31
33
|
pipeline: Document[];
|
|
32
34
|
isClient?: boolean;
|
|
33
35
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"interface.d.ts","sourceRoot":"","sources":["../../../src/features/functions/interface.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,SAAS,CAAA;AACzC,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAA;AAClC,OAAO,EAAE,oBAAoB,EAAE,MAAM,oCAAoC,CAAA;AACzE,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAA;AAE1C,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAA;IACZ,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,aAAa,CAAC,EAAE,OAAO,CAAA;IACvB,gBAAgB,CAAC,EAAE,OAAO,CAAA;CAC3B;AAED,MAAM,MAAM,QAAQ,GAAG,IAAI,CAAC,cAAc,EAAE,MAAM,CAAC,GAAG;IACpD,IAAI,EAAE,MAAM,CAAA;IACZ,UAAU,CAAC,EAAE,MAAM,CAAA;CACpB,CAAA;AAED,MAAM,MAAM,SAAS,GAAG,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAA;AAEhD,MAAM,MAAM,uBAAuB,GAAG;IACpC,GAAG,EAAE,eAAe,CAAA;IACpB,aAAa,EAAE,SAAS,CAAA;IACxB,SAAS,EAAE,KAAK,CAAA;CACjB,CAAA;AAED,MAAM,MAAM,kBAAkB,GAAG;IAC/B,aAAa,EAAE,UAAU,CAAC,oBAAoB,CAAC,CAAC,MAAM,UAAU,CAAC,oBAAoB,CAAC,CAAC,CAAA;IACvF,KAAK,EAAE,UAAU,CAAC,oBAAoB,CAAC,CAAA;IACvC,MAAM,EAAE,QAAQ,CAAA;IAChB,MAAM,CAAC,EAAE,QAAQ,CAAA;IACjB,UAAU,CAAC,EAAE,QAAQ,CAAA;IACrB,OAAO,CAAC,EAAE,QAAQ,CAAA;IAClB,iBAAiB,CAAC,EAAE,OAAO,CAAA;IAC3B,QAAQ,EAAE,QAAQ,CAAA;IAClB,SAAS,EAAE,QAAQ,EAAE,CAAA;IACrB,QAAQ,EAAE,QAAQ,EAAE,CAAA;IACpB,QAAQ,CAAC,EAAE,OAAO,CAAA;CACnB,CAAA;AAED,KAAK,0BAA0B,GAAG;IAChC,aAAa,EAAE,SAAS,CAAA;IACxB,KAAK,EAAE,KAAK,CAAA;CACb,CAAA;AAED,MAAM,MAAM,kBAAkB,GAAG,CAC/B,GAAG,EAAE,eAAe,EACpB,EAAE,aAAa,EAAE,KAAK,EAAE,EAAE,0BAA0B,KACjD,OAAO,CAAC,IAAI,CAAC,CAAA"}
|
|
1
|
+
{"version":3,"file":"interface.d.ts","sourceRoot":"","sources":["../../../src/features/functions/interface.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,SAAS,CAAA;AACzC,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAA;AAClC,OAAO,EAAE,oBAAoB,EAAE,MAAM,oCAAoC,CAAA;AACzE,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAA;AAE1C,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAA;IACZ,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,aAAa,CAAC,EAAE,OAAO,CAAA;IACvB,gBAAgB,CAAC,EAAE,OAAO,CAAA;CAC3B;AAED,MAAM,MAAM,QAAQ,GAAG,IAAI,CAAC,cAAc,EAAE,MAAM,CAAC,GAAG;IACpD,IAAI,EAAE,MAAM,CAAA;IACZ,UAAU,CAAC,EAAE,MAAM,CAAA;CACpB,CAAA;AAED,MAAM,MAAM,SAAS,GAAG,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAA;AAEhD,MAAM,MAAM,uBAAuB,GAAG;IACpC,GAAG,EAAE,eAAe,CAAA;IACpB,aAAa,EAAE,SAAS,CAAA;IACxB,SAAS,EAAE,KAAK,CAAA;CACjB,CAAA;AAED,MAAM,MAAM,kBAAkB,GAAG;IAC/B,aAAa,EAAE,UAAU,CAAC,oBAAoB,CAAC,CAAC,MAAM,UAAU,CAAC,oBAAoB,CAAC,CAAC,CAAA;IACvF,KAAK,EAAE,UAAU,CAAC,oBAAoB,CAAC,CAAA;IACvC,MAAM,EAAE,QAAQ,CAAA;IAChB,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,MAAM,CAAC,EAAE,QAAQ,CAAA;IACjB,UAAU,CAAC,EAAE,QAAQ,CAAA;IACrB,OAAO,CAAC,EAAE,QAAQ,CAAA;IAClB,iBAAiB,CAAC,EAAE,OAAO,CAAA;IAC3B,QAAQ,EAAE,QAAQ,CAAA;IAClB,SAAS,EAAE,QAAQ,EAAE,CAAA;IACrB,UAAU,CAAC,EAAE,QAAQ,EAAE,CAAA;IACvB,QAAQ,EAAE,QAAQ,EAAE,CAAA;IACpB,QAAQ,CAAC,EAAE,OAAO,CAAA;CACnB,CAAA;AAED,KAAK,0BAA0B,GAAG;IAChC,aAAa,EAAE,SAAS,CAAA;IACxB,KAAK,EAAE,KAAK,CAAA;CACb,CAAA;AAED,MAAM,MAAM,kBAAkB,GAAG,CAC/B,GAAG,EAAE,eAAe,EACpB,EAAE,aAAa,EAAE,KAAK,EAAE,EAAE,0BAA0B,KACjD,OAAO,CAAC,IAAI,CAAC,CAAA"}
|
|
@@ -11,17 +11,19 @@ export declare const loadFunctions: (rootDir?: string) => Promise<Functions>;
|
|
|
11
11
|
* @param query -> the query data
|
|
12
12
|
* @param update -> the update Document that should be deserialized
|
|
13
13
|
*/
|
|
14
|
-
export declare const executeQuery: ({ currentMethod, query, update, filter, projection, options, returnNewDocument, document, documents, pipeline, isClient }: ExecuteQueryParams) => Promise<{
|
|
14
|
+
export declare const executeQuery: ({ currentMethod, query, update, key, filter, projection, options, returnNewDocument, document, documents, operations, pipeline, isClient }: ExecuteQueryParams) => Promise<{
|
|
15
15
|
find: () => Promise<any[]>;
|
|
16
16
|
findOne: () => Promise<unknown>;
|
|
17
17
|
count: () => Promise<number>;
|
|
18
18
|
countDocuments: () => Promise<number>;
|
|
19
|
+
distinct: () => Promise<any[]>;
|
|
19
20
|
deleteOne: () => Promise<import("mongodb").DeleteResult>;
|
|
20
21
|
insertOne: () => Promise<import("mongodb").InsertOneResult<Document>>;
|
|
21
22
|
updateOne: () => Promise<import("mongodb").UpdateResult<Document>>;
|
|
22
23
|
findOneAndUpdate: () => Promise<Document | null>;
|
|
23
24
|
aggregate: () => Promise<Document[]>;
|
|
24
25
|
insertMany: () => Promise<import("mongodb").InsertManyResult<Document>>;
|
|
26
|
+
bulkWrite: () => Promise<import("mongodb").BulkWriteResult>;
|
|
25
27
|
updateMany: () => Promise<import("mongodb").UpdateResult<Document>>;
|
|
26
28
|
deleteMany: () => Promise<import("mongodb").DeleteResult>;
|
|
27
29
|
}>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../src/features/functions/utils.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAA;AAGlC,OAAO,EAAE,kBAAkB,EAAE,SAAS,EAAE,MAAM,aAAa,CAAA;AAE3D;;;GAGG;AACH,eAAO,MAAM,aAAa,GAAU,gBAAuB,KAAG,OAAO,CAAC,SAAS,CAwB9E,CAAA;AAED;;;;;GAKG;AACH,eAAO,MAAM,YAAY,GAAU,
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../src/features/functions/utils.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAA;AAGlC,OAAO,EAAE,kBAAkB,EAAE,SAAS,EAAE,MAAM,aAAa,CAAA;AAE3D;;;GAGG;AACH,eAAO,MAAM,aAAa,GAAU,gBAAuB,KAAG,OAAO,CAAC,SAAS,CAwB9E,CAAA;AAED;;;;;GAKG;AACH,eAAO,MAAM,YAAY,GAAU,4IAchC,kBAAkB;;;;;;;;;;;;;;;EAiHpB,CAAA"}
|
|
@@ -58,7 +58,7 @@ exports.loadFunctions = loadFunctions;
|
|
|
58
58
|
* @param query -> the query data
|
|
59
59
|
* @param update -> the update Document that should be deserialized
|
|
60
60
|
*/
|
|
61
|
-
const executeQuery = (_a) => __awaiter(void 0, [_a], void 0, function* ({ currentMethod, query, update, filter, projection, options, returnNewDocument, document, documents, pipeline, isClient = false }) {
|
|
61
|
+
const executeQuery = (_a) => __awaiter(void 0, [_a], void 0, function* ({ currentMethod, query, update, key, filter, projection, options, returnNewDocument, document, documents, operations, pipeline, isClient = false }) {
|
|
62
62
|
const resolvedQuery = typeof query !== 'undefined'
|
|
63
63
|
? query
|
|
64
64
|
: typeof filter !== 'undefined'
|
|
@@ -98,6 +98,7 @@ const executeQuery = (_a) => __awaiter(void 0, [_a], void 0, function* ({ curren
|
|
|
98
98
|
findOne: () => currentMethod(bson_1.EJSON.deserialize(resolvedQuery), resolvedProjection, parsedOptions),
|
|
99
99
|
count: () => currentMethod(bson_1.EJSON.deserialize(resolvedQuery), parsedOptions),
|
|
100
100
|
countDocuments: () => currentMethod(bson_1.EJSON.deserialize(resolvedQuery), parsedOptions),
|
|
101
|
+
distinct: () => currentMethod(key !== null && key !== void 0 ? key : '', bson_1.EJSON.deserialize(resolvedQuery), parsedOptions),
|
|
101
102
|
deleteOne: () => currentMethod(bson_1.EJSON.deserialize(resolvedQuery), parsedOptions),
|
|
102
103
|
insertOne: () => currentMethod(bson_1.EJSON.deserialize(document)),
|
|
103
104
|
updateOne: () => currentMethod(bson_1.EJSON.deserialize(resolvedQuery), bson_1.EJSON.deserialize(resolvedUpdate), parsedOptions),
|
|
@@ -107,6 +108,7 @@ const executeQuery = (_a) => __awaiter(void 0, [_a], void 0, function* ({ curren
|
|
|
107
108
|
isClient)).toArray();
|
|
108
109
|
}),
|
|
109
110
|
insertMany: () => currentMethod(bson_1.EJSON.deserialize(documents)),
|
|
111
|
+
bulkWrite: () => currentMethod(bson_1.EJSON.deserialize(operations !== null && operations !== void 0 ? operations : []), parsedOptions),
|
|
110
112
|
updateMany: () => currentMethod(bson_1.EJSON.deserialize(resolvedQuery), bson_1.EJSON.deserialize(resolvedUpdate)),
|
|
111
113
|
deleteMany: () => currentMethod(bson_1.EJSON.deserialize(resolvedQuery), parsedOptions)
|
|
112
114
|
};
|
package/dist/services/index.d.ts
CHANGED
|
@@ -126,23 +126,23 @@ export declare const services: {
|
|
|
126
126
|
invokedFrom?: string;
|
|
127
127
|
};
|
|
128
128
|
}) => {
|
|
129
|
-
lambda: (region: string) => import("@aws-sdk/client-lambda
|
|
130
|
-
Invoke: (params: import("@aws-sdk/client-lambda
|
|
129
|
+
lambda: (region: string) => import("@aws-sdk/client-lambda").Lambda & {
|
|
130
|
+
Invoke: (params: import("@aws-sdk/client-lambda").InvokeCommandInput) => Promise<Omit<import("@aws-sdk/client-lambda").InvokeCommandOutput, "Payload"> & {
|
|
131
131
|
Payload: {
|
|
132
132
|
text: () => string | undefined;
|
|
133
133
|
};
|
|
134
134
|
}>;
|
|
135
|
-
InvokeAsync: (params: import("@aws-sdk/client-lambda
|
|
135
|
+
InvokeAsync: (params: import("@aws-sdk/client-lambda").InvokeAsyncCommandInput) => Promise<import("@aws-sdk/client-lambda").InvokeAsyncCommandOutput>;
|
|
136
136
|
};
|
|
137
|
-
s3: (region: string) => import("@aws-sdk/client-s3
|
|
138
|
-
PutObject: (params: import("@aws-sdk/client-s3
|
|
139
|
-
GetObject: (params: import("@aws-sdk/client-s3
|
|
140
|
-
getSignedUrl: (operation: "getObject" | "putObject", params: (import("@aws-sdk/client-s3
|
|
137
|
+
s3: (region: string) => import("@aws-sdk/client-s3").S3Client & {
|
|
138
|
+
PutObject: (params: import("@aws-sdk/client-s3").PutObjectCommandInput) => Promise<import("@aws-sdk/client-s3").PutObjectCommandOutput>;
|
|
139
|
+
GetObject: (params: import("@aws-sdk/client-s3").GetObjectCommandInput) => Promise<import("@aws-sdk/client-s3").GetObjectCommandOutput>;
|
|
140
|
+
getSignedUrl: (operation: "getObject" | "putObject", params: (import("@aws-sdk/client-s3").GetObjectCommandInput | import("@aws-sdk/client-s3").PutObjectCommandInput) & {
|
|
141
141
|
Expires?: number;
|
|
142
142
|
}, options?: {
|
|
143
143
|
expiresIn?: number;
|
|
144
144
|
}) => Promise<string>;
|
|
145
|
-
PresignURL: (params: (import("@aws-sdk/client-s3
|
|
145
|
+
PresignURL: (params: (import("@aws-sdk/client-s3").GetObjectCommandInput | import("@aws-sdk/client-s3").PutObjectCommandInput) & {
|
|
146
146
|
Method?: string;
|
|
147
147
|
ExpirationMS?: number;
|
|
148
148
|
Expires?: number;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/services/mongodb-atlas/index.ts"],"names":[],"mappings":"AAKA,OAAO,EAIL,QAAQ,EAQT,MAAM,SAAS,CAAA;AAOhB,OAAO,EAGL,oBAAoB,EAErB,MAAM,SAAS,CAAA;AA8JhB,eAAO,MAAM,kBAAkB,GAAI,OAAO,OAAO,KAAG,OA0BnD,CAAA;AA8BD,eAAO,MAAM,2BAA2B,GAAI,UAAU,QAAQ,EAAE,YAK5D,CAAA;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/services/mongodb-atlas/index.ts"],"names":[],"mappings":"AAKA,OAAO,EAIL,QAAQ,EAQT,MAAM,SAAS,CAAA;AAOhB,OAAO,EAGL,oBAAoB,EAErB,MAAM,SAAS,CAAA;AA8JhB,eAAO,MAAM,kBAAkB,GAAI,OAAO,OAAO,KAAG,OA0BnD,CAAA;AA8BD,eAAO,MAAM,2BAA2B,GAAI,UAAU,QAAQ,EAAE,YAK5D,CAAA;AA+6CJ,QAAA,MAAM,YAAY,EAAE,oBAwBlB,CAAA;AAEF,eAAe,YAAY,CAAA"}
|
|
@@ -408,6 +408,22 @@ const areUpdatedFieldsAllowed = (filtered, updated, updatedPaths) => {
|
|
|
408
408
|
return (0, isEqual_1.default)(filtered, updated);
|
|
409
409
|
return updatedPaths.every((path) => (0, isEqual_1.default)((0, get_1.default)(filtered, path), (0, get_1.default)(updated, path)));
|
|
410
410
|
};
|
|
411
|
+
const appendDistinctValue = (values, candidate) => {
|
|
412
|
+
if (typeof candidate === 'undefined')
|
|
413
|
+
return;
|
|
414
|
+
if (!values.some((entry) => (0, isEqual_1.default)(entry, candidate))) {
|
|
415
|
+
values.push(candidate);
|
|
416
|
+
}
|
|
417
|
+
};
|
|
418
|
+
const collectDistinctValues = (documents, key) => documents.reduce((values, document) => {
|
|
419
|
+
const currentValue = (0, get_1.default)(document, key);
|
|
420
|
+
if (Array.isArray(currentValue)) {
|
|
421
|
+
currentValue.forEach((entry) => appendDistinctValue(values, entry));
|
|
422
|
+
return values;
|
|
423
|
+
}
|
|
424
|
+
appendDistinctValue(values, currentValue);
|
|
425
|
+
return values;
|
|
426
|
+
}, []);
|
|
411
427
|
const getOperators = (mongo, { rules, dbName, collName, user, run_as_system, monitoringOrigin }) => {
|
|
412
428
|
var _a, _b;
|
|
413
429
|
const collection = mongo.client.db(dbName).collection(collName);
|
|
@@ -437,7 +453,39 @@ const getOperators = (mongo, { rules, dbName, collName, user, run_as_system, mon
|
|
|
437
453
|
origin: monitoringOrigin
|
|
438
454
|
});
|
|
439
455
|
};
|
|
440
|
-
|
|
456
|
+
const validateReadableDocument = (currentDoc) => __awaiter(void 0, void 0, void 0, function* () {
|
|
457
|
+
var _a;
|
|
458
|
+
const winningRole = yield (0, utils_2.getWinningRoleAsync)(currentDoc, user, roles);
|
|
459
|
+
logDebug('find winningRole', {
|
|
460
|
+
collection: collName,
|
|
461
|
+
userId: getUserId(user),
|
|
462
|
+
winningRoleName: (_a = winningRole === null || winningRole === void 0 ? void 0 : winningRole.name) !== null && _a !== void 0 ? _a : null,
|
|
463
|
+
rolesLength: roles.length
|
|
464
|
+
});
|
|
465
|
+
const { status, document } = winningRole
|
|
466
|
+
? yield (0, machines_1.checkValidation)(winningRole, {
|
|
467
|
+
type: 'read',
|
|
468
|
+
roles,
|
|
469
|
+
cursor: currentDoc,
|
|
470
|
+
expansions: getValidationExpansions(currentDoc)
|
|
471
|
+
}, user)
|
|
472
|
+
: fallbackAccess(currentDoc);
|
|
473
|
+
return status ? document : undefined;
|
|
474
|
+
});
|
|
475
|
+
const getScopedQuery = (query = {}) => {
|
|
476
|
+
const formattedQuery = (0, utils_3.getFormattedQuery)(filters, query, user);
|
|
477
|
+
const currentQuery = formattedQuery.length ? { $and: formattedQuery } : {};
|
|
478
|
+
const safeQuery = Array.isArray(formattedQuery)
|
|
479
|
+
? (0, utils_3.normalizeQuery)(formattedQuery)
|
|
480
|
+
: formattedQuery;
|
|
481
|
+
return {
|
|
482
|
+
formattedQuery,
|
|
483
|
+
currentQuery,
|
|
484
|
+
safeQuery,
|
|
485
|
+
builtQuery: buildAndQuery(safeQuery)
|
|
486
|
+
};
|
|
487
|
+
};
|
|
488
|
+
const operators = {
|
|
441
489
|
/**
|
|
442
490
|
* Finds a single document in a MongoDB collection with optional role-based filtering and validation.
|
|
443
491
|
*
|
|
@@ -852,25 +900,7 @@ const getOperators = (mongo, { rules, dbName, collName, user, run_as_system, mon
|
|
|
852
900
|
*/
|
|
853
901
|
cursor.toArray = () => __awaiter(void 0, void 0, void 0, function* () {
|
|
854
902
|
const response = yield originalToArray();
|
|
855
|
-
const filteredResponse = yield Promise.all(response.map((currentDoc) =>
|
|
856
|
-
var _a;
|
|
857
|
-
const winningRole = yield (0, utils_2.getWinningRoleAsync)(currentDoc, user, roles);
|
|
858
|
-
logDebug('find winningRole', {
|
|
859
|
-
collection: collName,
|
|
860
|
-
userId: getUserId(user),
|
|
861
|
-
winningRoleName: (_a = winningRole === null || winningRole === void 0 ? void 0 : winningRole.name) !== null && _a !== void 0 ? _a : null,
|
|
862
|
-
rolesLength: roles.length
|
|
863
|
-
});
|
|
864
|
-
const { status, document } = winningRole
|
|
865
|
-
? yield (0, machines_1.checkValidation)(winningRole, {
|
|
866
|
-
type: 'read',
|
|
867
|
-
roles,
|
|
868
|
-
cursor: currentDoc,
|
|
869
|
-
expansions: getValidationExpansions(currentDoc)
|
|
870
|
-
}, user)
|
|
871
|
-
: fallbackAccess(currentDoc);
|
|
872
|
-
return status ? document : undefined;
|
|
873
|
-
})));
|
|
903
|
+
const filteredResponse = yield Promise.all(response.map((currentDoc) => validateReadableDocument(currentDoc)));
|
|
874
904
|
return filteredResponse.filter(Boolean);
|
|
875
905
|
});
|
|
876
906
|
emitMongoEvent('find');
|
|
@@ -928,6 +958,32 @@ const getOperators = (mongo, { rules, dbName, collName, user, run_as_system, mon
|
|
|
928
958
|
throw error;
|
|
929
959
|
}
|
|
930
960
|
}),
|
|
961
|
+
distinct: (key_1, ...args_1) => __awaiter(void 0, [key_1, ...args_1], void 0, function* (key, query = {}, options) {
|
|
962
|
+
try {
|
|
963
|
+
if (!key) {
|
|
964
|
+
throw new Error('distinct key is required');
|
|
965
|
+
}
|
|
966
|
+
if (!run_as_system) {
|
|
967
|
+
(0, utils_3.checkDenyOperation)(normalizedRules, collection.collectionName, model_1.CRUD_OPERATIONS.READ);
|
|
968
|
+
const { currentQuery } = getScopedQuery(query);
|
|
969
|
+
const projectedOptions = Object.assign(Object.assign({}, (options !== null && options !== void 0 ? options : {})), { projection: { _id: 1, [key]: 1 } });
|
|
970
|
+
const documents = yield collection.find(currentQuery, projectedOptions).toArray();
|
|
971
|
+
const readableDocuments = (yield Promise.all(documents.map((currentDoc) => validateReadableDocument(currentDoc)))).filter(Boolean);
|
|
972
|
+
const result = collectDistinctValues(readableDocuments, key);
|
|
973
|
+
emitMongoEvent('distinct');
|
|
974
|
+
return result;
|
|
975
|
+
}
|
|
976
|
+
const result = typeof options === 'undefined'
|
|
977
|
+
? yield collection.distinct(key, query)
|
|
978
|
+
: yield collection.distinct(key, query, options);
|
|
979
|
+
emitMongoEvent('distinct');
|
|
980
|
+
return result;
|
|
981
|
+
}
|
|
982
|
+
catch (error) {
|
|
983
|
+
emitMongoEvent('distinct', undefined, error);
|
|
984
|
+
throw error;
|
|
985
|
+
}
|
|
986
|
+
}),
|
|
931
987
|
/**
|
|
932
988
|
* Watches changes on a MongoDB collection with optional role-based filtering of change events.
|
|
933
989
|
*
|
|
@@ -1129,6 +1185,20 @@ const getOperators = (mongo, { rules, dbName, collName, user, run_as_system, mon
|
|
|
1129
1185
|
throw error;
|
|
1130
1186
|
}
|
|
1131
1187
|
}),
|
|
1188
|
+
bulkWrite: (operations, options) => __awaiter(void 0, void 0, void 0, function* () {
|
|
1189
|
+
try {
|
|
1190
|
+
if (!run_as_system) {
|
|
1191
|
+
throw new Error('bulkWrite is available only when run_as_system is enabled');
|
|
1192
|
+
}
|
|
1193
|
+
const result = yield collection.bulkWrite(operations, options);
|
|
1194
|
+
emitMongoEvent('bulkWrite', { operations: operations.length });
|
|
1195
|
+
return result;
|
|
1196
|
+
}
|
|
1197
|
+
catch (error) {
|
|
1198
|
+
emitMongoEvent('bulkWrite', { operations: Array.isArray(operations) ? operations.length : 0 }, error);
|
|
1199
|
+
throw error;
|
|
1200
|
+
}
|
|
1201
|
+
}),
|
|
1132
1202
|
updateMany: (query, data, options) => __awaiter(void 0, void 0, void 0, function* () {
|
|
1133
1203
|
try {
|
|
1134
1204
|
const normalizedData = normalizeUpdatePayload(data);
|
|
@@ -1239,6 +1309,7 @@ const getOperators = (mongo, { rules, dbName, collName, user, run_as_system, mon
|
|
|
1239
1309
|
}
|
|
1240
1310
|
})
|
|
1241
1311
|
};
|
|
1312
|
+
return operators;
|
|
1242
1313
|
};
|
|
1243
1314
|
const MongodbAtlas = (app, { rules, user, run_as_system, monitoring } = {}) => ({
|
|
1244
1315
|
startSession: (options) => {
|
|
@@ -40,6 +40,8 @@ export type GetOperatorsFunction = (mongoInstance: FastifyInstance["mongo"], { r
|
|
|
40
40
|
countDocuments: (...params: Parameters<Method<'countDocuments'>>) => ReturnType<Method<'countDocuments'>>;
|
|
41
41
|
watch: (...params: Parameters<Method<'watch'>>) => ReturnType<Method<'watch'>>;
|
|
42
42
|
aggregate: (...params: [...Parameters<Method<'aggregate'>>, isClient: boolean]) => ReturnType<Method<'aggregate'>>;
|
|
43
|
+
distinct: (key: Parameters<Method<'distinct'>>[0], filter?: Parameters<Method<'distinct'>>[1], options?: Parameters<Method<'distinct'>>[2]) => ReturnType<Method<'distinct'>>;
|
|
44
|
+
bulkWrite: (...params: Parameters<Method<'bulkWrite'>>) => ReturnType<Method<'bulkWrite'>>;
|
|
43
45
|
insertMany: (...params: Parameters<Method<'insertMany'>>) => ReturnType<Method<'insertMany'>>;
|
|
44
46
|
updateMany: (...params: Parameters<Method<'updateMany'>>) => ReturnType<Method<'updateMany'>>;
|
|
45
47
|
deleteMany: (...params: Parameters<Method<'deleteMany'>>) => ReturnType<Method<'deleteMany'>>;
|
|
@@ -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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"}
|
|
@@ -176,23 +176,23 @@ export declare const generateContextData: ({ user, services, app, rules, current
|
|
|
176
176
|
context: object;
|
|
177
177
|
}>;
|
|
178
178
|
} | {
|
|
179
|
-
lambda: (region: string) => import("@aws-sdk/client-lambda
|
|
180
|
-
Invoke: (params: import("@aws-sdk/client-lambda
|
|
179
|
+
lambda: (region: string) => import("@aws-sdk/client-lambda").Lambda & {
|
|
180
|
+
Invoke: (params: import("@aws-sdk/client-lambda").InvokeCommandInput) => Promise<Omit<import("@aws-sdk/client-lambda").InvokeCommandOutput, "Payload"> & {
|
|
181
181
|
Payload: {
|
|
182
182
|
text: () => string | undefined;
|
|
183
183
|
};
|
|
184
184
|
}>;
|
|
185
|
-
InvokeAsync: (params: import("@aws-sdk/client-lambda
|
|
185
|
+
InvokeAsync: (params: import("@aws-sdk/client-lambda").InvokeAsyncCommandInput) => Promise<import("@aws-sdk/client-lambda").InvokeAsyncCommandOutput>;
|
|
186
186
|
};
|
|
187
|
-
s3: (region: string) => import("@aws-sdk/client-s3
|
|
188
|
-
PutObject: (params: import("@aws-sdk/client-s3
|
|
189
|
-
GetObject: (params: import("@aws-sdk/client-s3
|
|
190
|
-
getSignedUrl: (operation: "getObject" | "putObject", params: (import("@aws-sdk/client-s3
|
|
187
|
+
s3: (region: string) => import("@aws-sdk/client-s3").S3Client & {
|
|
188
|
+
PutObject: (params: import("@aws-sdk/client-s3").PutObjectCommandInput) => Promise<import("@aws-sdk/client-s3").PutObjectCommandOutput>;
|
|
189
|
+
GetObject: (params: import("@aws-sdk/client-s3").GetObjectCommandInput) => Promise<import("@aws-sdk/client-s3").GetObjectCommandOutput>;
|
|
190
|
+
getSignedUrl: (operation: "getObject" | "putObject", params: (import("@aws-sdk/client-s3").GetObjectCommandInput | import("@aws-sdk/client-s3").PutObjectCommandInput) & {
|
|
191
191
|
Expires?: number;
|
|
192
192
|
}, options?: {
|
|
193
193
|
expiresIn?: number;
|
|
194
194
|
}) => Promise<string>;
|
|
195
|
-
PresignURL: (params: (import("@aws-sdk/client-s3
|
|
195
|
+
PresignURL: (params: (import("@aws-sdk/client-s3").GetObjectCommandInput | import("@aws-sdk/client-s3").PutObjectCommandInput) & {
|
|
196
196
|
Method?: string;
|
|
197
197
|
ExpirationMS?: number;
|
|
198
198
|
Expires?: number;
|
|
@@ -328,23 +328,23 @@ export declare const generateContextData: ({ user, services, app, rules, current
|
|
|
328
328
|
context: object;
|
|
329
329
|
}>;
|
|
330
330
|
} | {
|
|
331
|
-
lambda: (region: string) => import("@aws-sdk/client-lambda
|
|
332
|
-
Invoke: (params: import("@aws-sdk/client-lambda
|
|
331
|
+
lambda: (region: string) => import("@aws-sdk/client-lambda").Lambda & {
|
|
332
|
+
Invoke: (params: import("@aws-sdk/client-lambda").InvokeCommandInput) => Promise<Omit<import("@aws-sdk/client-lambda").InvokeCommandOutput, "Payload"> & {
|
|
333
333
|
Payload: {
|
|
334
334
|
text: () => string | undefined;
|
|
335
335
|
};
|
|
336
336
|
}>;
|
|
337
|
-
InvokeAsync: (params: import("@aws-sdk/client-lambda
|
|
337
|
+
InvokeAsync: (params: import("@aws-sdk/client-lambda").InvokeAsyncCommandInput) => Promise<import("@aws-sdk/client-lambda").InvokeAsyncCommandOutput>;
|
|
338
338
|
};
|
|
339
|
-
s3: (region: string) => import("@aws-sdk/client-s3
|
|
340
|
-
PutObject: (params: import("@aws-sdk/client-s3
|
|
341
|
-
GetObject: (params: import("@aws-sdk/client-s3
|
|
342
|
-
getSignedUrl: (operation: "getObject" | "putObject", params: (import("@aws-sdk/client-s3
|
|
339
|
+
s3: (region: string) => import("@aws-sdk/client-s3").S3Client & {
|
|
340
|
+
PutObject: (params: import("@aws-sdk/client-s3").PutObjectCommandInput) => Promise<import("@aws-sdk/client-s3").PutObjectCommandOutput>;
|
|
341
|
+
GetObject: (params: import("@aws-sdk/client-s3").GetObjectCommandInput) => Promise<import("@aws-sdk/client-s3").GetObjectCommandOutput>;
|
|
342
|
+
getSignedUrl: (operation: "getObject" | "putObject", params: (import("@aws-sdk/client-s3").GetObjectCommandInput | import("@aws-sdk/client-s3").PutObjectCommandInput) & {
|
|
343
343
|
Expires?: number;
|
|
344
344
|
}, options?: {
|
|
345
345
|
expiresIn?: number;
|
|
346
346
|
}) => Promise<string>;
|
|
347
|
-
PresignURL: (params: (import("@aws-sdk/client-s3
|
|
347
|
+
PresignURL: (params: (import("@aws-sdk/client-s3").GetObjectCommandInput | import("@aws-sdk/client-s3").PutObjectCommandInput) & {
|
|
348
348
|
Method?: string;
|
|
349
349
|
ExpirationMS?: number;
|
|
350
350
|
Expires?: number;
|
|
@@ -479,23 +479,23 @@ export declare const generateContextData: ({ user, services, app, rules, current
|
|
|
479
479
|
context: object;
|
|
480
480
|
}>;
|
|
481
481
|
} | {
|
|
482
|
-
lambda: (region: string) => import("@aws-sdk/client-lambda
|
|
483
|
-
Invoke: (params: import("@aws-sdk/client-lambda
|
|
482
|
+
lambda: (region: string) => import("@aws-sdk/client-lambda").Lambda & {
|
|
483
|
+
Invoke: (params: import("@aws-sdk/client-lambda").InvokeCommandInput) => Promise<Omit<import("@aws-sdk/client-lambda").InvokeCommandOutput, "Payload"> & {
|
|
484
484
|
Payload: {
|
|
485
485
|
text: () => string | undefined;
|
|
486
486
|
};
|
|
487
487
|
}>;
|
|
488
|
-
InvokeAsync: (params: import("@aws-sdk/client-lambda
|
|
488
|
+
InvokeAsync: (params: import("@aws-sdk/client-lambda").InvokeAsyncCommandInput) => Promise<import("@aws-sdk/client-lambda").InvokeAsyncCommandOutput>;
|
|
489
489
|
};
|
|
490
|
-
s3: (region: string) => import("@aws-sdk/client-s3
|
|
491
|
-
PutObject: (params: import("@aws-sdk/client-s3
|
|
492
|
-
GetObject: (params: import("@aws-sdk/client-s3
|
|
493
|
-
getSignedUrl: (operation: "getObject" | "putObject", params: (import("@aws-sdk/client-s3
|
|
490
|
+
s3: (region: string) => import("@aws-sdk/client-s3").S3Client & {
|
|
491
|
+
PutObject: (params: import("@aws-sdk/client-s3").PutObjectCommandInput) => Promise<import("@aws-sdk/client-s3").PutObjectCommandOutput>;
|
|
492
|
+
GetObject: (params: import("@aws-sdk/client-s3").GetObjectCommandInput) => Promise<import("@aws-sdk/client-s3").GetObjectCommandOutput>;
|
|
493
|
+
getSignedUrl: (operation: "getObject" | "putObject", params: (import("@aws-sdk/client-s3").GetObjectCommandInput | import("@aws-sdk/client-s3").PutObjectCommandInput) & {
|
|
494
494
|
Expires?: number;
|
|
495
495
|
}, options?: {
|
|
496
496
|
expiresIn?: number;
|
|
497
497
|
}) => Promise<string>;
|
|
498
|
-
PresignURL: (params: (import("@aws-sdk/client-s3
|
|
498
|
+
PresignURL: (params: (import("@aws-sdk/client-s3").GetObjectCommandInput | import("@aws-sdk/client-s3").PutObjectCommandInput) & {
|
|
499
499
|
Method?: string;
|
|
500
500
|
ExpirationMS?: number;
|
|
501
501
|
Expires?: number;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import { MachineContext } from '../../interface';
|
|
2
2
|
export declare const checkAdditionalFieldsFn: ({ role }: MachineContext) => boolean;
|
|
3
|
-
export declare const checkIsValidFieldNameFn: (context: MachineContext) => Promise<import("bson
|
|
3
|
+
export declare const checkIsValidFieldNameFn: (context: MachineContext) => Promise<import("bson").Document>;
|
|
4
4
|
//# sourceMappingURL=validators.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validators.d.ts","sourceRoot":"","sources":["../../../../../../src/utils/roles/machines/read/D/validators.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAA;AAEhD,eAAO,MAAM,uBAAuB,GAAI,UAAU,cAAc,YAE/D,CAAA;AAED,eAAO,MAAM,uBAAuB,GAAU,SAAS,cAAc,
|
|
1
|
+
{"version":3,"file":"validators.d.ts","sourceRoot":"","sources":["../../../../../../src/utils/roles/machines/read/D/validators.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAA;AAEhD,eAAO,MAAM,uBAAuB,GAAI,UAAU,cAAc,YAE/D,CAAA;AAED,eAAO,MAAM,uBAAuB,GAAU,SAAS,cAAc,qCAOpE,CAAA"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import { MachineContext } from '../../interface';
|
|
2
2
|
export declare const checkAdditionalFieldsFn: ({ role }: MachineContext) => boolean;
|
|
3
|
-
export declare const checkIsValidFieldNameFn: (context: MachineContext) => Promise<import("bson
|
|
3
|
+
export declare const checkIsValidFieldNameFn: (context: MachineContext) => Promise<import("bson").Document>;
|
|
4
4
|
//# sourceMappingURL=validators.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validators.d.ts","sourceRoot":"","sources":["../../../../../../src/utils/roles/machines/write/C/validators.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAA;AAEhD,eAAO,MAAM,uBAAuB,GAAI,UAAU,cAAc,YAE/D,CAAA;AAED,eAAO,MAAM,uBAAuB,GAAU,SAAS,cAAc,
|
|
1
|
+
{"version":3,"file":"validators.d.ts","sourceRoot":"","sources":["../../../../../../src/utils/roles/machines/write/C/validators.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAA;AAEhD,eAAO,MAAM,uBAAuB,GAAI,UAAU,cAAc,YAE/D,CAAA;AAED,eAAO,MAAM,uBAAuB,GAAU,SAAS,cAAc,qCAIpE,CAAA"}
|
package/package.json
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import Fastify, { FastifyInstance, FastifyReply, FastifyRequest } from 'fastify'
|
|
2
|
+
import { services } from '../../../services'
|
|
2
3
|
import { GenerateContext } from '../../../utils/context'
|
|
3
4
|
import { functionsController } from '../controller'
|
|
4
5
|
|
|
@@ -8,18 +9,19 @@ jest.mock('../../../utils/context', () => ({
|
|
|
8
9
|
|
|
9
10
|
describe('functionsController', () => {
|
|
10
11
|
let app: FastifyInstance
|
|
12
|
+
const originalMongoService = services['mongodb-atlas']
|
|
11
13
|
|
|
12
14
|
beforeEach(async () => {
|
|
13
15
|
app = Fastify()
|
|
14
16
|
|
|
15
17
|
app.decorate('jwtAuthentication', async (request: FastifyRequest, _reply: FastifyReply) => {
|
|
16
|
-
;(request as any).user = {
|
|
18
|
+
; (request as any).user = {
|
|
17
19
|
id: '507f191e810c19729de860ea',
|
|
18
20
|
typ: 'access'
|
|
19
21
|
}
|
|
20
22
|
})
|
|
21
23
|
|
|
22
|
-
|
|
24
|
+
; (GenerateContext as jest.Mock).mockResolvedValue({ ok: true })
|
|
23
25
|
|
|
24
26
|
await app.register(functionsController, {
|
|
25
27
|
functionsList: {
|
|
@@ -33,6 +35,7 @@ describe('functionsController', () => {
|
|
|
33
35
|
})
|
|
34
36
|
|
|
35
37
|
afterEach(async () => {
|
|
38
|
+
services['mongodb-atlas'] = originalMongoService
|
|
36
39
|
await app.close()
|
|
37
40
|
jest.clearAllMocks()
|
|
38
41
|
})
|
|
@@ -57,4 +60,41 @@ describe('functionsController', () => {
|
|
|
57
60
|
})
|
|
58
61
|
)
|
|
59
62
|
})
|
|
63
|
+
|
|
64
|
+
it('passes mongodb-atlas distinct service arguments through POST /call', async () => {
|
|
65
|
+
const distinct = jest.fn().mockResolvedValue(['open'])
|
|
66
|
+
services['mongodb-atlas'] = jest.fn(() => ({
|
|
67
|
+
db: jest.fn().mockReturnValue({
|
|
68
|
+
collection: jest.fn().mockReturnValue({
|
|
69
|
+
distinct
|
|
70
|
+
})
|
|
71
|
+
})
|
|
72
|
+
})) as any
|
|
73
|
+
|
|
74
|
+
const response = await app.inject({
|
|
75
|
+
method: 'POST',
|
|
76
|
+
url: '/call',
|
|
77
|
+
payload: {
|
|
78
|
+
service: 'mongodb-atlas',
|
|
79
|
+
name: 'distinct',
|
|
80
|
+
arguments: [
|
|
81
|
+
{
|
|
82
|
+
database: 'app',
|
|
83
|
+
collection: 'todos',
|
|
84
|
+
key: 'status',
|
|
85
|
+
query: { archived: false },
|
|
86
|
+
options: { maxTimeMS: 250 }
|
|
87
|
+
}
|
|
88
|
+
]
|
|
89
|
+
}
|
|
90
|
+
})
|
|
91
|
+
|
|
92
|
+
expect(response.statusCode).toBe(200)
|
|
93
|
+
expect(JSON.parse(response.body)).toEqual(['open'])
|
|
94
|
+
expect(distinct).toHaveBeenCalledWith(
|
|
95
|
+
'status',
|
|
96
|
+
{ archived: false },
|
|
97
|
+
{ maxTimeMS: 250 }
|
|
98
|
+
)
|
|
99
|
+
})
|
|
60
100
|
})
|
|
@@ -30,4 +30,48 @@ describe('executeQuery', () => {
|
|
|
30
30
|
{ upsert: true }
|
|
31
31
|
)
|
|
32
32
|
})
|
|
33
|
+
|
|
34
|
+
it('passes distinct arguments through to the service method', async () => {
|
|
35
|
+
const currentMethod = jest.fn().mockResolvedValue(['open'])
|
|
36
|
+
|
|
37
|
+
const operators = await executeQuery({
|
|
38
|
+
currentMethod,
|
|
39
|
+
key: 'status',
|
|
40
|
+
query: { archived: false },
|
|
41
|
+
update: {},
|
|
42
|
+
options: { maxTimeMS: 500 }
|
|
43
|
+
} as any)
|
|
44
|
+
|
|
45
|
+
await operators.distinct()
|
|
46
|
+
|
|
47
|
+
expect(currentMethod).toHaveBeenCalledWith(
|
|
48
|
+
'status',
|
|
49
|
+
{ archived: false },
|
|
50
|
+
{ maxTimeMS: 500 }
|
|
51
|
+
)
|
|
52
|
+
})
|
|
53
|
+
|
|
54
|
+
it('passes bulkWrite operations through to the service method', async () => {
|
|
55
|
+
const currentMethod = jest.fn().mockResolvedValue({ acknowledged: true })
|
|
56
|
+
const operations = [
|
|
57
|
+
{
|
|
58
|
+
updateOne: {
|
|
59
|
+
filter: { archived: false },
|
|
60
|
+
update: { $set: { archived: true } }
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
]
|
|
64
|
+
|
|
65
|
+
const operators = await executeQuery({
|
|
66
|
+
currentMethod,
|
|
67
|
+
query: {},
|
|
68
|
+
update: {},
|
|
69
|
+
operations,
|
|
70
|
+
options: { ordered: false }
|
|
71
|
+
} as any)
|
|
72
|
+
|
|
73
|
+
await operators.bulkWrite()
|
|
74
|
+
|
|
75
|
+
expect(currentMethod).toHaveBeenCalledWith(operations, { ordered: false })
|
|
76
|
+
})
|
|
33
77
|
})
|
|
@@ -9,6 +9,29 @@ import { Base64Function, FunctionCallBase64Dto, FunctionCallDto } from './dtos'
|
|
|
9
9
|
import { FunctionController } from './interface'
|
|
10
10
|
import { executeQuery } from './utils'
|
|
11
11
|
|
|
12
|
+
const SUPPORTED_QUERY_METHODS = [
|
|
13
|
+
'find',
|
|
14
|
+
'findOne',
|
|
15
|
+
'count',
|
|
16
|
+
'countDocuments',
|
|
17
|
+
'distinct',
|
|
18
|
+
'deleteOne',
|
|
19
|
+
'insertOne',
|
|
20
|
+
'updateOne',
|
|
21
|
+
'findOneAndUpdate',
|
|
22
|
+
'aggregate',
|
|
23
|
+
'insertMany',
|
|
24
|
+
'bulkWrite',
|
|
25
|
+
'updateMany',
|
|
26
|
+
'deleteMany'
|
|
27
|
+
] as const
|
|
28
|
+
|
|
29
|
+
type SupportedQueryMethod = (typeof SUPPORTED_QUERY_METHODS)[number]
|
|
30
|
+
|
|
31
|
+
const isSupportedQueryMethod = (value: unknown): value is SupportedQueryMethod =>
|
|
32
|
+
typeof value === 'string' &&
|
|
33
|
+
(SUPPORTED_QUERY_METHODS as readonly string[]).includes(value)
|
|
34
|
+
|
|
12
35
|
const normalizeUser = (payload: Record<string, any> | undefined) => {
|
|
13
36
|
if (!payload) return undefined
|
|
14
37
|
const nestedUser =
|
|
@@ -352,6 +375,7 @@ export const functionsController: FunctionController = async (
|
|
|
352
375
|
const [{
|
|
353
376
|
database,
|
|
354
377
|
collection,
|
|
378
|
+
key,
|
|
355
379
|
query,
|
|
356
380
|
filter,
|
|
357
381
|
update,
|
|
@@ -360,9 +384,14 @@ export const functionsController: FunctionController = async (
|
|
|
360
384
|
returnNewDocument,
|
|
361
385
|
document,
|
|
362
386
|
documents,
|
|
387
|
+
operations,
|
|
363
388
|
pipeline = []
|
|
364
389
|
}] = args
|
|
365
390
|
|
|
391
|
+
if (!isSupportedQueryMethod(method)) {
|
|
392
|
+
throw new Error(`Unsupported service method "${String(method)}"`)
|
|
393
|
+
}
|
|
394
|
+
|
|
366
395
|
const currentMethod = serviceFn(app, { rules, user })
|
|
367
396
|
.db(database)
|
|
368
397
|
.collection(collection)[method]
|
|
@@ -371,6 +400,7 @@ export const functionsController: FunctionController = async (
|
|
|
371
400
|
const operatorsByType = await executeQuery({
|
|
372
401
|
currentMethod,
|
|
373
402
|
query,
|
|
403
|
+
key,
|
|
374
404
|
filter,
|
|
375
405
|
update,
|
|
376
406
|
projection,
|
|
@@ -378,10 +408,15 @@ export const functionsController: FunctionController = async (
|
|
|
378
408
|
returnNewDocument,
|
|
379
409
|
document,
|
|
380
410
|
documents,
|
|
411
|
+
operations,
|
|
381
412
|
pipeline,
|
|
382
413
|
isClient: true
|
|
383
414
|
})
|
|
384
|
-
const
|
|
415
|
+
const operator = operatorsByType[method]
|
|
416
|
+
if (typeof operator !== 'function') {
|
|
417
|
+
throw new Error(`Unsupported service method "${method}"`)
|
|
418
|
+
}
|
|
419
|
+
const serviceResult = await operator()
|
|
385
420
|
res.type('application/json')
|
|
386
421
|
return serializeEjson(serviceResult)
|
|
387
422
|
}
|
|
@@ -23,6 +23,7 @@ export type FunctionCallBase64Dto = {
|
|
|
23
23
|
type ArgumentsData = Arguments<{
|
|
24
24
|
database: string
|
|
25
25
|
collection: string
|
|
26
|
+
key?: string
|
|
26
27
|
filter?: Document
|
|
27
28
|
query: Parameters<GetOperatorsFunction>
|
|
28
29
|
update: Document
|
|
@@ -31,6 +32,7 @@ type ArgumentsData = Arguments<{
|
|
|
31
32
|
returnNewDocument?: boolean
|
|
32
33
|
document: Document
|
|
33
34
|
documents: Document[]
|
|
35
|
+
operations?: Document[]
|
|
34
36
|
pipeline?: Document[]
|
|
35
37
|
}>
|
|
36
38
|
|
|
@@ -27,12 +27,14 @@ export type ExecuteQueryParams = {
|
|
|
27
27
|
currentMethod: ReturnType<GetOperatorsFunction>[keyof ReturnType<GetOperatorsFunction>]
|
|
28
28
|
query: Parameters<GetOperatorsFunction>
|
|
29
29
|
update: Document
|
|
30
|
+
key?: string
|
|
30
31
|
filter?: Document
|
|
31
32
|
projection?: Document
|
|
32
33
|
options?: Document
|
|
33
34
|
returnNewDocument?: boolean
|
|
34
35
|
document: Document
|
|
35
36
|
documents: Document[]
|
|
37
|
+
operations?: Document[]
|
|
36
38
|
pipeline: Document[]
|
|
37
39
|
isClient?: boolean
|
|
38
40
|
}
|
|
@@ -45,12 +45,14 @@ export const executeQuery = async ({
|
|
|
45
45
|
currentMethod,
|
|
46
46
|
query,
|
|
47
47
|
update,
|
|
48
|
+
key,
|
|
48
49
|
filter,
|
|
49
50
|
projection,
|
|
50
51
|
options,
|
|
51
52
|
returnNewDocument,
|
|
52
53
|
document,
|
|
53
54
|
documents,
|
|
55
|
+
operations,
|
|
54
56
|
pipeline,
|
|
55
57
|
isClient = false
|
|
56
58
|
}: ExecuteQueryParams) => {
|
|
@@ -113,6 +115,12 @@ export const executeQuery = async ({
|
|
|
113
115
|
EJSON.deserialize(resolvedQuery),
|
|
114
116
|
parsedOptions
|
|
115
117
|
),
|
|
118
|
+
distinct: () =>
|
|
119
|
+
(currentMethod as ReturnType<GetOperatorsFunction>['distinct'])(
|
|
120
|
+
key ?? '',
|
|
121
|
+
EJSON.deserialize(resolvedQuery),
|
|
122
|
+
parsedOptions
|
|
123
|
+
),
|
|
116
124
|
deleteOne: () =>
|
|
117
125
|
(currentMethod as ReturnType<GetOperatorsFunction>['deleteOne'])(
|
|
118
126
|
EJSON.deserialize(resolvedQuery),
|
|
@@ -144,6 +152,11 @@ export const executeQuery = async ({
|
|
|
144
152
|
(currentMethod as ReturnType<GetOperatorsFunction>['insertMany'])(
|
|
145
153
|
EJSON.deserialize(documents)
|
|
146
154
|
),
|
|
155
|
+
bulkWrite: () =>
|
|
156
|
+
(currentMethod as ReturnType<GetOperatorsFunction>['bulkWrite'])(
|
|
157
|
+
EJSON.deserialize(operations ?? []),
|
|
158
|
+
parsedOptions
|
|
159
|
+
),
|
|
147
160
|
updateMany: () =>
|
|
148
161
|
(currentMethod as ReturnType<GetOperatorsFunction>['updateMany'])(
|
|
149
162
|
EJSON.deserialize(resolvedQuery),
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
/// <reference types="jest" />
|
|
2
|
+
|
|
1
3
|
import { ObjectId } from 'mongodb'
|
|
2
4
|
import MongoDbAtlas from '..'
|
|
3
5
|
import { Rules } from '../../../features/rules/interface'
|
|
@@ -178,6 +180,70 @@ describe('mongodb-atlas Realm compatibility', () => {
|
|
|
178
180
|
)
|
|
179
181
|
})
|
|
180
182
|
|
|
183
|
+
it('forwards bulkWrite to the underlying collection in system mode', async () => {
|
|
184
|
+
const operations = [
|
|
185
|
+
{
|
|
186
|
+
updateOne: {
|
|
187
|
+
filter: { done: false },
|
|
188
|
+
update: { $set: { done: true } }
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
]
|
|
192
|
+
const bulkWriteResult = {
|
|
193
|
+
acknowledged: true,
|
|
194
|
+
matchedCount: 1,
|
|
195
|
+
modifiedCount: 1,
|
|
196
|
+
insertedCount: 0,
|
|
197
|
+
deletedCount: 0,
|
|
198
|
+
upsertedCount: 0,
|
|
199
|
+
insertedIds: {},
|
|
200
|
+
upsertedIds: {}
|
|
201
|
+
}
|
|
202
|
+
const bulkWrite = jest.fn().mockResolvedValue(bulkWriteResult)
|
|
203
|
+
const collection = {
|
|
204
|
+
collectionName: 'todos',
|
|
205
|
+
bulkWrite
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
const operators = MongoDbAtlas(createAppWithCollection(collection) as any, {
|
|
209
|
+
run_as_system: true
|
|
210
|
+
}).db('db').collection('todos')
|
|
211
|
+
|
|
212
|
+
const result = await operators.bulkWrite(operations as any, { ordered: false } as any)
|
|
213
|
+
|
|
214
|
+
expect(result).toEqual(bulkWriteResult)
|
|
215
|
+
expect(bulkWrite).toHaveBeenCalledWith(operations, { ordered: false })
|
|
216
|
+
})
|
|
217
|
+
|
|
218
|
+
it('rejects bulkWrite outside run_as_system mode', async () => {
|
|
219
|
+
const bulkWrite = jest.fn()
|
|
220
|
+
const collection = {
|
|
221
|
+
collectionName: 'todos',
|
|
222
|
+
bulkWrite
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
const operators = MongoDbAtlas(createAppWithCollection(collection) as any, {
|
|
226
|
+
rules: createRules(),
|
|
227
|
+
user: { id: 'user-1' }
|
|
228
|
+
}).db('db').collection('todos')
|
|
229
|
+
|
|
230
|
+
await expect(
|
|
231
|
+
operators.bulkWrite(
|
|
232
|
+
[
|
|
233
|
+
{
|
|
234
|
+
updateOne: {
|
|
235
|
+
filter: { done: false },
|
|
236
|
+
update: { $set: { done: true } }
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
] as any,
|
|
240
|
+
{ ordered: false } as any
|
|
241
|
+
)
|
|
242
|
+
).rejects.toThrow('bulkWrite is available only when run_as_system is enabled')
|
|
243
|
+
|
|
244
|
+
expect(bulkWrite).not.toHaveBeenCalled()
|
|
245
|
+
})
|
|
246
|
+
|
|
181
247
|
it('supports operator updates in updateMany without using invalid aggregate stages', async () => {
|
|
182
248
|
const id = new ObjectId()
|
|
183
249
|
const find = jest.fn().mockReturnValue({
|
|
@@ -513,6 +579,56 @@ describe('mongodb-atlas Realm compatibility', () => {
|
|
|
513
579
|
expect(result.insertedIds).toEqual([id0, id1])
|
|
514
580
|
})
|
|
515
581
|
|
|
582
|
+
it('computes distinct values from readable documents only', async () => {
|
|
583
|
+
const find = jest.fn().mockReturnValue({
|
|
584
|
+
toArray: jest.fn().mockResolvedValue([
|
|
585
|
+
{ _id: new ObjectId(), visible: 'A', secret: 'internal-1' },
|
|
586
|
+
{ _id: new ObjectId(), visible: 'A', secret: 'internal-2' },
|
|
587
|
+
{ _id: new ObjectId(), visible: 'B', secret: 'internal-1' }
|
|
588
|
+
])
|
|
589
|
+
})
|
|
590
|
+
const collection = {
|
|
591
|
+
collectionName: 'todos',
|
|
592
|
+
find
|
|
593
|
+
}
|
|
594
|
+
const operators = MongoDbAtlas(createAppWithCollection(collection) as any, {
|
|
595
|
+
rules: createRules({
|
|
596
|
+
roles: [
|
|
597
|
+
{
|
|
598
|
+
name: 'reader',
|
|
599
|
+
apply_when: {},
|
|
600
|
+
insert: true,
|
|
601
|
+
delete: true,
|
|
602
|
+
search: true,
|
|
603
|
+
read: true,
|
|
604
|
+
write: true,
|
|
605
|
+
fields: {
|
|
606
|
+
visible: { read: true },
|
|
607
|
+
secret: { read: false, write: false }
|
|
608
|
+
}
|
|
609
|
+
} as any
|
|
610
|
+
]
|
|
611
|
+
}),
|
|
612
|
+
user: { id: 'user-1' }
|
|
613
|
+
}).db('db').collection('todos')
|
|
614
|
+
|
|
615
|
+
const visibleResult = await operators.distinct('visible', { archived: false })
|
|
616
|
+
const secretResult = await operators.distinct('secret', { archived: false })
|
|
617
|
+
|
|
618
|
+
expect(visibleResult).toEqual(['A', 'B'])
|
|
619
|
+
expect(secretResult).toEqual([])
|
|
620
|
+
expect(find).toHaveBeenNthCalledWith(
|
|
621
|
+
1,
|
|
622
|
+
{ $and: [{ archived: false }] },
|
|
623
|
+
{ projection: { _id: 1, visible: 1 } }
|
|
624
|
+
)
|
|
625
|
+
expect(find).toHaveBeenNthCalledWith(
|
|
626
|
+
2,
|
|
627
|
+
{ $and: [{ archived: false }] },
|
|
628
|
+
{ projection: { _id: 1, secret: 1 } }
|
|
629
|
+
)
|
|
630
|
+
})
|
|
631
|
+
|
|
516
632
|
it('exposes startSession and delegates to the underlying MongoClient', async () => {
|
|
517
633
|
const mockSession = { withTransaction: jest.fn() }
|
|
518
634
|
const startSession = jest.fn().mockReturnValue(mockSession)
|
|
@@ -492,6 +492,26 @@ const areUpdatedFieldsAllowed = (
|
|
|
492
492
|
return updatedPaths.every((path) => isEqual(get(filtered, path), get(updated, path)))
|
|
493
493
|
}
|
|
494
494
|
|
|
495
|
+
const appendDistinctValue = (values: unknown[], candidate: unknown) => {
|
|
496
|
+
if (typeof candidate === 'undefined') return
|
|
497
|
+
if (!values.some((entry) => isEqual(entry, candidate))) {
|
|
498
|
+
values.push(candidate)
|
|
499
|
+
}
|
|
500
|
+
}
|
|
501
|
+
|
|
502
|
+
const collectDistinctValues = (documents: Document[], key: string) =>
|
|
503
|
+
documents.reduce<unknown[]>((values, document) => {
|
|
504
|
+
const currentValue = get(document, key)
|
|
505
|
+
|
|
506
|
+
if (Array.isArray(currentValue)) {
|
|
507
|
+
currentValue.forEach((entry) => appendDistinctValue(values, entry))
|
|
508
|
+
return values
|
|
509
|
+
}
|
|
510
|
+
|
|
511
|
+
appendDistinctValue(values, currentValue)
|
|
512
|
+
return values
|
|
513
|
+
}, [])
|
|
514
|
+
|
|
495
515
|
const getOperators: GetOperatorsFunction = (
|
|
496
516
|
mongo,
|
|
497
517
|
{ rules, dbName, collName, user, run_as_system, monitoringOrigin }
|
|
@@ -535,7 +555,48 @@ const getOperators: GetOperatorsFunction = (
|
|
|
535
555
|
})
|
|
536
556
|
}
|
|
537
557
|
|
|
538
|
-
|
|
558
|
+
const validateReadableDocument = async (currentDoc: Document) => {
|
|
559
|
+
const winningRole = await getWinningRoleAsync(currentDoc, user, roles)
|
|
560
|
+
|
|
561
|
+
logDebug('find winningRole', {
|
|
562
|
+
collection: collName,
|
|
563
|
+
userId: getUserId(user),
|
|
564
|
+
winningRoleName: winningRole?.name ?? null,
|
|
565
|
+
rolesLength: roles.length
|
|
566
|
+
})
|
|
567
|
+
|
|
568
|
+
const { status, document } = winningRole
|
|
569
|
+
? await checkValidation(
|
|
570
|
+
winningRole,
|
|
571
|
+
{
|
|
572
|
+
type: 'read',
|
|
573
|
+
roles,
|
|
574
|
+
cursor: currentDoc,
|
|
575
|
+
expansions: getValidationExpansions(currentDoc)
|
|
576
|
+
},
|
|
577
|
+
user
|
|
578
|
+
)
|
|
579
|
+
: fallbackAccess(currentDoc)
|
|
580
|
+
|
|
581
|
+
return status ? document : undefined
|
|
582
|
+
}
|
|
583
|
+
|
|
584
|
+
const getScopedQuery = (query: MongoFilter<Document> = {}) => {
|
|
585
|
+
const formattedQuery = getFormattedQuery(filters, query, user)
|
|
586
|
+
const currentQuery = formattedQuery.length ? { $and: formattedQuery } : {}
|
|
587
|
+
const safeQuery = Array.isArray(formattedQuery)
|
|
588
|
+
? normalizeQuery(formattedQuery)
|
|
589
|
+
: formattedQuery
|
|
590
|
+
|
|
591
|
+
return {
|
|
592
|
+
formattedQuery,
|
|
593
|
+
currentQuery,
|
|
594
|
+
safeQuery,
|
|
595
|
+
builtQuery: buildAndQuery(safeQuery)
|
|
596
|
+
}
|
|
597
|
+
}
|
|
598
|
+
|
|
599
|
+
const operators: ReturnType<GetOperatorsFunction> = {
|
|
539
600
|
/**
|
|
540
601
|
* Finds a single document in a MongoDB collection with optional role-based filtering and validation.
|
|
541
602
|
*
|
|
@@ -1068,30 +1129,7 @@ const getOperators: GetOperatorsFunction = (
|
|
|
1068
1129
|
const response = await originalToArray()
|
|
1069
1130
|
|
|
1070
1131
|
const filteredResponse = await Promise.all(
|
|
1071
|
-
response.map(
|
|
1072
|
-
const winningRole = await getWinningRoleAsync(currentDoc, user, roles)
|
|
1073
|
-
|
|
1074
|
-
logDebug('find winningRole', {
|
|
1075
|
-
collection: collName,
|
|
1076
|
-
userId: getUserId(user),
|
|
1077
|
-
winningRoleName: winningRole?.name ?? null,
|
|
1078
|
-
rolesLength: roles.length
|
|
1079
|
-
})
|
|
1080
|
-
const { status, document } = winningRole
|
|
1081
|
-
? await checkValidation(
|
|
1082
|
-
winningRole,
|
|
1083
|
-
{
|
|
1084
|
-
type: 'read',
|
|
1085
|
-
roles,
|
|
1086
|
-
cursor: currentDoc,
|
|
1087
|
-
expansions: getValidationExpansions(currentDoc)
|
|
1088
|
-
},
|
|
1089
|
-
user
|
|
1090
|
-
)
|
|
1091
|
-
: fallbackAccess(currentDoc)
|
|
1092
|
-
|
|
1093
|
-
return status ? document : undefined
|
|
1094
|
-
})
|
|
1132
|
+
response.map((currentDoc) => validateReadableDocument(currentDoc))
|
|
1095
1133
|
)
|
|
1096
1134
|
|
|
1097
1135
|
return filteredResponse.filter(Boolean) as WithId<Document>[]
|
|
@@ -1164,6 +1202,45 @@ const getOperators: GetOperatorsFunction = (
|
|
|
1164
1202
|
throw error
|
|
1165
1203
|
}
|
|
1166
1204
|
},
|
|
1205
|
+
distinct: async (key, query = {}, options) => {
|
|
1206
|
+
try {
|
|
1207
|
+
if (!key) {
|
|
1208
|
+
throw new Error('distinct key is required')
|
|
1209
|
+
}
|
|
1210
|
+
|
|
1211
|
+
if (!run_as_system) {
|
|
1212
|
+
checkDenyOperation(
|
|
1213
|
+
normalizedRules,
|
|
1214
|
+
collection.collectionName,
|
|
1215
|
+
CRUD_OPERATIONS.READ
|
|
1216
|
+
)
|
|
1217
|
+
|
|
1218
|
+
const { currentQuery } = getScopedQuery(query)
|
|
1219
|
+
const projectedOptions = {
|
|
1220
|
+
...(options ?? {}),
|
|
1221
|
+
projection: { _id: 1, [key]: 1 }
|
|
1222
|
+
} as FindOptions
|
|
1223
|
+
const documents = await collection.find(currentQuery, projectedOptions).toArray()
|
|
1224
|
+
const readableDocuments = (
|
|
1225
|
+
await Promise.all(documents.map((currentDoc) => validateReadableDocument(currentDoc)))
|
|
1226
|
+
).filter(Boolean) as Document[]
|
|
1227
|
+
const result = collectDistinctValues(readableDocuments, key)
|
|
1228
|
+
|
|
1229
|
+
emitMongoEvent('distinct')
|
|
1230
|
+
return result
|
|
1231
|
+
}
|
|
1232
|
+
|
|
1233
|
+
const result =
|
|
1234
|
+
typeof options === 'undefined'
|
|
1235
|
+
? await collection.distinct(key, query)
|
|
1236
|
+
: await collection.distinct(key, query, options)
|
|
1237
|
+
emitMongoEvent('distinct')
|
|
1238
|
+
return result
|
|
1239
|
+
} catch (error) {
|
|
1240
|
+
emitMongoEvent('distinct', undefined, error)
|
|
1241
|
+
throw error
|
|
1242
|
+
}
|
|
1243
|
+
},
|
|
1167
1244
|
/**
|
|
1168
1245
|
* Watches changes on a MongoDB collection with optional role-based filtering of change events.
|
|
1169
1246
|
*
|
|
@@ -1450,6 +1527,24 @@ const getOperators: GetOperatorsFunction = (
|
|
|
1450
1527
|
throw error
|
|
1451
1528
|
}
|
|
1452
1529
|
},
|
|
1530
|
+
bulkWrite: async (operations, options) => {
|
|
1531
|
+
try {
|
|
1532
|
+
if (!run_as_system) {
|
|
1533
|
+
throw new Error('bulkWrite is available only when run_as_system is enabled')
|
|
1534
|
+
}
|
|
1535
|
+
|
|
1536
|
+
const result = await collection.bulkWrite(operations, options)
|
|
1537
|
+
emitMongoEvent('bulkWrite', { operations: operations.length })
|
|
1538
|
+
return result
|
|
1539
|
+
} catch (error) {
|
|
1540
|
+
emitMongoEvent(
|
|
1541
|
+
'bulkWrite',
|
|
1542
|
+
{ operations: Array.isArray(operations) ? operations.length : 0 },
|
|
1543
|
+
error
|
|
1544
|
+
)
|
|
1545
|
+
throw error
|
|
1546
|
+
}
|
|
1547
|
+
},
|
|
1453
1548
|
updateMany: async (query, data, options) => {
|
|
1454
1549
|
try {
|
|
1455
1550
|
const normalizedData = normalizeUpdatePayload(data as Document)
|
|
@@ -1602,6 +1697,8 @@ const getOperators: GetOperatorsFunction = (
|
|
|
1602
1697
|
}
|
|
1603
1698
|
}
|
|
1604
1699
|
}
|
|
1700
|
+
|
|
1701
|
+
return operators
|
|
1605
1702
|
}
|
|
1606
1703
|
|
|
1607
1704
|
const MongodbAtlas: MongodbAtlasFunction = (
|
|
@@ -93,6 +93,14 @@ export type GetOperatorsFunction = (
|
|
|
93
93
|
aggregate: (
|
|
94
94
|
...params: [...Parameters<Method<'aggregate'>>, isClient: boolean]
|
|
95
95
|
) => ReturnType<Method<'aggregate'>>
|
|
96
|
+
distinct: (
|
|
97
|
+
key: Parameters<Method<'distinct'>>[0],
|
|
98
|
+
filter?: Parameters<Method<'distinct'>>[1],
|
|
99
|
+
options?: Parameters<Method<'distinct'>>[2]
|
|
100
|
+
) => ReturnType<Method<'distinct'>>
|
|
101
|
+
bulkWrite: (
|
|
102
|
+
...params: Parameters<Method<'bulkWrite'>>
|
|
103
|
+
) => ReturnType<Method<'bulkWrite'>>
|
|
96
104
|
insertMany: (
|
|
97
105
|
...params: Parameters<Method<'insertMany'>>
|
|
98
106
|
) => ReturnType<Method<'insertMany'>>
|
package/tsconfig.json
CHANGED
|
@@ -8,13 +8,8 @@
|
|
|
8
8
|
"declarationMap": true,
|
|
9
9
|
"noImplicitAny": true,
|
|
10
10
|
"strict": true,
|
|
11
|
-
"moduleResolution": "node",
|
|
12
11
|
"esModuleInterop": true,
|
|
13
12
|
"skipLibCheck": true,
|
|
14
|
-
"baseUrl": ".",
|
|
15
|
-
"paths": {
|
|
16
|
-
"*": ["../../node_modules/*"]
|
|
17
|
-
},
|
|
18
13
|
"lib": ["ES2021", "DOM"]
|
|
19
14
|
},
|
|
20
15
|
"include": ["src/**/*"],
|