@flowerforce/flowerbase 1.7.1 → 1.7.2-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 (34) hide show
  1. package/dist/features/functions/utils.d.ts +1 -0
  2. package/dist/features/functions/utils.d.ts.map +1 -1
  3. package/dist/features/functions/utils.js +1 -0
  4. package/dist/features/triggers/index.js +1 -1
  5. package/dist/monitoring/routes/endpoints.d.ts.map +1 -1
  6. package/dist/monitoring/routes/endpoints.js +39 -11
  7. package/dist/monitoring/routes/users.d.ts.map +1 -1
  8. package/dist/monitoring/routes/users.js +17 -8
  9. package/dist/services/mongodb-atlas/index.d.ts.map +1 -1
  10. package/dist/services/mongodb-atlas/index.js +20 -0
  11. package/dist/services/mongodb-atlas/model.d.ts +1 -0
  12. package/dist/services/mongodb-atlas/model.d.ts.map +1 -1
  13. package/dist/utils/context/helpers.d.ts +6 -0
  14. package/dist/utils/context/helpers.d.ts.map +1 -1
  15. package/dist/utils/context/helpers.js +2 -0
  16. package/dist/utils/rules-matcher/interface.d.ts +10 -0
  17. package/dist/utils/rules-matcher/interface.d.ts.map +1 -1
  18. package/dist/utils/rules-matcher/interface.js +1 -0
  19. package/dist/utils/rules-matcher/utils.d.ts.map +1 -1
  20. package/dist/utils/rules-matcher/utils.js +1 -0
  21. package/package.json +2 -1
  22. package/src/features/functions/utils.ts +5 -0
  23. package/src/features/triggers/index.ts +1 -1
  24. package/src/monitoring/routes/endpoints.ts +39 -9
  25. package/src/monitoring/routes/users.ts +15 -13
  26. package/src/monitoring/ui.endpoints.js +1 -0
  27. package/src/services/mongodb-atlas/__tests__/count.test.ts +33 -0
  28. package/src/services/mongodb-atlas/index.ts +20 -0
  29. package/src/services/mongodb-atlas/model.ts +3 -0
  30. package/src/utils/__tests__/generateContext.ejson.test.ts +52 -0
  31. package/src/utils/__tests__/operators.test.ts +6 -0
  32. package/src/utils/context/helpers.ts +6 -4
  33. package/src/utils/rules-matcher/interface.ts +10 -0
  34. package/src/utils/rules-matcher/utils.ts +2 -0
@@ -15,6 +15,7 @@ export declare const executeQuery: ({ currentMethod, query, update, filter, proj
15
15
  find: () => Promise<any[]>;
16
16
  findOne: () => Promise<unknown>;
17
17
  count: () => Promise<number>;
18
+ countDocuments: () => Promise<number>;
18
19
  deleteOne: () => Promise<import("mongodb").DeleteResult>;
19
20
  insertOne: () => Promise<import("mongodb").InsertOneResult<Document>>;
20
21
  updateOne: () => Promise<unknown> | import("mongodb").FindCursor<any> | import("mongodb").ChangeStream<Document, Document> | import("mongodb").AggregationCursor<Document>;
@@ -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,2HAYhC,kBAAkB;;;;;;;;;;;;EA4FpB,CAAA"}
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,2HAYhC,kBAAkB;;;;;;;;;;;;;EAiGpB,CAAA"}
@@ -97,6 +97,7 @@ const executeQuery = (_a) => __awaiter(void 0, [_a], void 0, function* ({ curren
97
97
  }),
98
98
  findOne: () => currentMethod(bson_1.EJSON.deserialize(resolvedQuery), resolvedProjection, parsedOptions),
99
99
  count: () => currentMethod(bson_1.EJSON.deserialize(resolvedQuery), parsedOptions),
100
+ countDocuments: () => currentMethod(bson_1.EJSON.deserialize(resolvedQuery), parsedOptions),
100
101
  deleteOne: () => currentMethod(bson_1.EJSON.deserialize(resolvedQuery), parsedOptions),
101
102
  insertOne: () => currentMethod(bson_1.EJSON.deserialize(document)),
102
103
  updateOne: () => currentMethod(bson_1.EJSON.deserialize(resolvedQuery), bson_1.EJSON.deserialize(resolvedUpdate)),
@@ -44,7 +44,7 @@ const activateTriggers = (_a) => __awaiter(void 0, [_a], void 0, function* ({ fa
44
44
  triggersToActivate.push({
45
45
  fileName: '__auto_on_user_creation_trigger__.json',
46
46
  content: {
47
- name: 'onUserCreation',
47
+ name: constants_1.AUTH_CONFIG.on_user_creation_function_name,
48
48
  type: 'AUTHENTICATION',
49
49
  disabled: false,
50
50
  config: {
@@ -1 +1 @@
1
- {"version":3,"file":"endpoints.d.ts","sourceRoot":"","sources":["../../../src/monitoring/routes/endpoints.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,SAAS,CAAA;AAG9C,OAAO,EAAiB,YAAY,EAAY,MAAM,UAAU,CAAA;AAgBhE,MAAM,MAAM,kBAAkB,GAAG;IAC/B,MAAM,EAAE,MAAM,CAAA;IACd,WAAW,EAAE,OAAO,CAAA;IACpB,QAAQ,EAAE,CAAC,KAAK,EAAE,YAAY,KAAK,IAAI,CAAA;CACxC,CAAA;AAsCD,eAAO,MAAM,sBAAsB,GAAI,KAAK,eAAe,EAAE,MAAM,kBAAkB,SAyEpF,CAAA"}
1
+ {"version":3,"file":"endpoints.d.ts","sourceRoot":"","sources":["../../../src/monitoring/routes/endpoints.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,SAAS,CAAA;AAG9C,OAAO,EAAiB,YAAY,EAAY,MAAM,UAAU,CAAA;AAiBhE,MAAM,MAAM,kBAAkB,GAAG;IAC/B,MAAM,EAAE,MAAM,CAAA;IACd,WAAW,EAAE,OAAO,CAAA;IACpB,QAAQ,EAAE,CAAC,KAAK,EAAE,YAAY,KAAK,IAAI,CAAA;CACxC,CAAA;AA0CD,eAAO,MAAM,sBAAsB,GAAI,KAAK,eAAe,EAAE,MAAM,kBAAkB,SAkGpF,CAAA"}
@@ -35,6 +35,9 @@ const buildQueryString = (query) => {
35
35
  });
36
36
  return params.toString();
37
37
  };
38
+ const normalizeRoute = (value) => {
39
+ return (value || '').replace(/^\/+/, '').trim();
40
+ };
38
41
  const normalizeHeaders = (headers) => {
39
42
  const normalized = {};
40
43
  if (!headers)
@@ -62,7 +65,7 @@ const registerEndpointRoutes = (app, deps) => {
62
65
  return { items: endpoints };
63
66
  }));
64
67
  app.post(`${prefix}/api/endpoints/invoke`, (req, reply) => __awaiter(void 0, void 0, void 0, function* () {
65
- var _a, _b;
68
+ var _a, _b, _c, _d;
66
69
  if (!allowInvoke) {
67
70
  reply.code(403);
68
71
  return { error: 'Endpoint invocation disabled' };
@@ -78,10 +81,13 @@ const registerEndpointRoutes = (app, deps) => {
78
81
  reply.code(400);
79
82
  return { error: 'Project ID not available' };
80
83
  }
81
- const normalizedRoute = route.replace(/^\/+/, '');
84
+ const normalizedRoute = normalizeRoute(route);
82
85
  const rawMethod = (body.method || 'POST').toUpperCase();
83
86
  const method = rawMethod;
84
87
  const effectiveMethod = (rawMethod === 'ALL' ? 'POST' : rawMethod);
88
+ const functionName = (_b = body.functionName) === null || _b === void 0 ? void 0 : _b.trim();
89
+ const functionsList = state_1.StateManager.select('functions');
90
+ const runAsSystem = functionName ? !!((_c = functionsList === null || functionsList === void 0 ? void 0 : functionsList[functionName]) === null || _c === void 0 ? void 0 : _c.run_as_system) : undefined;
85
91
  const queryString = buildQueryString(body.query);
86
92
  const encodedProjectId = encodeURIComponent(projectId);
87
93
  const baseUrl = `/app/${encodedProjectId}/endpoint/${normalizedRoute}`;
@@ -106,21 +112,43 @@ const registerEndpointRoutes = (app, deps) => {
106
112
  headers,
107
113
  payload
108
114
  };
109
- const response = yield app.inject(injectOptions);
110
- const parsedBody = parseInjectResponse(response.payload);
111
- const responseHeaders = {};
112
- Object.entries((_b = response.headers) !== null && _b !== void 0 ? _b : {}).forEach(([key, value]) => {
113
- if (value === undefined)
114
- return;
115
- responseHeaders[key] = Array.isArray(value) ? value.join(', ') : String(value);
116
- });
117
115
  addEvent({
118
116
  id: (0, utils_1.createEventId)(),
119
117
  ts: Date.now(),
120
118
  type: 'http_endpoint',
121
119
  source: 'monit',
122
120
  message: `${rawMethod} ${route}`,
123
- data: (0, utils_1.sanitize)({ method: effectiveMethod, route, query: body.query, headers: body.headers, payload: body.payload })
121
+ data: (0, utils_1.sanitize)({
122
+ method: effectiveMethod,
123
+ route,
124
+ query: body.query,
125
+ headers: body.headers,
126
+ payload: body.payload,
127
+ functionName
128
+ })
129
+ });
130
+ if (functionName) {
131
+ addEvent({
132
+ id: (0, utils_1.createEventId)(),
133
+ ts: Date.now(),
134
+ type: 'function',
135
+ source: 'monit',
136
+ message: `invoke ${functionName}`,
137
+ data: (0, utils_1.sanitize)({
138
+ name: functionName,
139
+ runAsSystem,
140
+ invokedFrom: functionName,
141
+ endpoint: { method: rawMethod, route }
142
+ })
143
+ });
144
+ }
145
+ const response = yield app.inject(injectOptions);
146
+ const parsedBody = parseInjectResponse(response.payload);
147
+ const responseHeaders = {};
148
+ Object.entries((_d = response.headers) !== null && _d !== void 0 ? _d : {}).forEach(([key, value]) => {
149
+ if (value === undefined)
150
+ return;
151
+ responseHeaders[key] = Array.isArray(value) ? value.join(', ') : String(value);
124
152
  });
125
153
  const result = {
126
154
  statusCode: response.statusCode,
@@ -1 +1 @@
1
- {"version":3,"file":"users.d.ts","sourceRoot":"","sources":["../../../src/monitoring/routes/users.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,SAAS,CAAA;AAO9C,OAAO,EAAiB,YAAY,EAAY,MAAM,UAAU,CAAA;AAEhE,MAAM,MAAM,cAAc,GAAG;IAC3B,MAAM,EAAE,MAAM,CAAA;IACd,QAAQ,EAAE,CAAC,KAAK,EAAE,YAAY,KAAK,IAAI,CAAA;CACxC,CAAA;AAYD,eAAO,MAAM,kBAAkB,GAAI,KAAK,eAAe,EAAE,MAAM,cAAc,SAoP5E,CAAA"}
1
+ {"version":3,"file":"users.d.ts","sourceRoot":"","sources":["../../../src/monitoring/routes/users.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,SAAS,CAAA;AAO9C,OAAO,EAAiB,YAAY,EAAY,MAAM,UAAU,CAAA;AAEhE,MAAM,MAAM,cAAc,GAAG;IAC3B,MAAM,EAAE,MAAM,CAAA;IACd,QAAQ,EAAE,CAAC,KAAK,EAAE,YAAY,KAAK,IAAI,CAAA;CACxC,CAAA;AAYD,eAAO,MAAM,kBAAkB,GAAI,KAAK,eAAe,EAAE,MAAM,cAAc,SAsP5E,CAAA"}
@@ -122,7 +122,7 @@ const registerUserRoutes = (app, deps) => {
122
122
  };
123
123
  }));
124
124
  app.post(`${prefix}/api/users`, (req, reply) => __awaiter(void 0, void 0, void 0, function* () {
125
- var _a, _b, _c;
125
+ var _a, _b;
126
126
  const body = req.body;
127
127
  const email = (_a = body === null || body === void 0 ? void 0 : body.email) === null || _a === void 0 ? void 0 : _a.toLowerCase();
128
128
  const password = body === null || body === void 0 ? void 0 : body.password;
@@ -140,13 +140,22 @@ const registerUserRoutes = (app, deps) => {
140
140
  provider: handleUserRegistration_model_1.PROVIDER.LOCAL_USERPASS
141
141
  })({ email, password });
142
142
  const userId = (_b = result === null || result === void 0 ? void 0 : result.insertedId) === null || _b === void 0 ? void 0 : _b.toString();
143
- if (userId && constants_1.AUTH_CONFIG.userCollection && constants_1.AUTH_CONFIG.user_id_field) {
144
- const db = app.mongo.client.db(constants_1.DB_NAME);
145
- const customData = (_c = body === null || body === void 0 ? void 0 : body.customData) !== null && _c !== void 0 ? _c : {};
146
- yield db.collection(constants_1.AUTH_CONFIG.userCollection).updateOne({ [constants_1.AUTH_CONFIG.user_id_field]: userId }, {
147
- $set: Object.assign(Object.assign({}, customData), { [constants_1.AUTH_CONFIG.user_id_field]: userId })
148
- }, { upsert: true });
149
- }
143
+ /*
144
+ non deve essere fatto, solo i trigger creano gli users
145
+ if (userId && AUTH_CONFIG.userCollection && AUTH_CONFIG.user_id_field) {
146
+ const db = app.mongo.client.db(DB_NAME)
147
+ const customData = body?.customData ?? {}
148
+ await db.collection(AUTH_CONFIG.userCollection).updateOne(
149
+ { [AUTH_CONFIG.user_id_field]: userId },
150
+ {
151
+ $set: {
152
+ ...customData,
153
+ [AUTH_CONFIG.user_id_field]: userId
154
+ }
155
+ },
156
+ { upsert: true }
157
+ )
158
+ } */
150
159
  addEvent({
151
160
  id: (0, utils_2.createEventId)(),
152
161
  ts: Date.now(),
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/services/mongodb-atlas/index.ts"],"names":[],"mappings":"AAgBA,OAAO,EAAyC,oBAAoB,EAAE,MAAM,SAAS,CAAA;AA0+BrF,QAAA,MAAM,YAAY,EAAE,oBAuBlB,CAAA;AAEF,eAAe,YAAY,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/services/mongodb-atlas/index.ts"],"names":[],"mappings":"AAgBA,OAAO,EAAyC,oBAAoB,EAAE,MAAM,SAAS,CAAA;AA8/BrF,QAAA,MAAM,YAAY,EAAE,oBAuBlB,CAAA;AAEF,eAAe,YAAY,CAAA"}
@@ -536,6 +536,26 @@ const getOperators = (collection, { rules, collName, user, run_as_system, monito
536
536
  throw error;
537
537
  }
538
538
  }),
539
+ countDocuments: (query, options) => __awaiter(void 0, void 0, void 0, function* () {
540
+ try {
541
+ if (!run_as_system) {
542
+ (0, utils_3.checkDenyOperation)(normalizedRules, collection.collectionName, model_1.CRUD_OPERATIONS.READ);
543
+ const formattedQuery = (0, utils_3.getFormattedQuery)(filters, query, user);
544
+ const currentQuery = formattedQuery.length ? { $and: formattedQuery } : {};
545
+ logService('countDocuments query', { collName, currentQuery });
546
+ const result = yield collection.countDocuments(currentQuery, options);
547
+ emitMongoEvent('countDocuments');
548
+ return result;
549
+ }
550
+ const result = yield collection.countDocuments(query, options);
551
+ emitMongoEvent('countDocuments');
552
+ return result;
553
+ }
554
+ catch (error) {
555
+ emitMongoEvent('countDocuments', undefined, error);
556
+ throw error;
557
+ }
558
+ }),
539
559
  /**
540
560
  * Watches changes on a MongoDB collection with optional role-based filtering of change events.
541
561
  *
@@ -35,6 +35,7 @@ export type GetOperatorsFunction = (collection: Collection<Document>, { rules, c
35
35
  findOneAndUpdate: (filter: MongoFilter<Document>, update: UpdateFilter<Document> | Document[], options?: FindOneAndUpdateOptions) => Promise<Document | null>;
36
36
  find: (filter?: MongoFilter<Document>, projection?: Document, options?: FindOptions) => FindCursor;
37
37
  count: (...params: Parameters<Method<'countDocuments'>>) => ReturnType<Method<'countDocuments'>>;
38
+ countDocuments: (...params: Parameters<Method<'countDocuments'>>) => ReturnType<Method<'countDocuments'>>;
38
39
  watch: (...params: Parameters<Method<'watch'>>) => ReturnType<Method<'watch'>>;
39
40
  aggregate: (...params: [...Parameters<Method<'aggregate'>>, isClient: boolean]) => ReturnType<Method<'aggregate'>>;
40
41
  insertMany: (...params: Parameters<Method<'insertMany'>>) => ReturnType<Method<'insertMany'>>;
@@ -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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"}
@@ -17,6 +17,12 @@ type JwtUtils = {
17
17
  */
18
18
  export declare const generateContextData: ({ user, services, app, rules, currentFunction, functionName, functionsList, GenerateContext, request }: GenerateContextDataParams) => {
19
19
  BSON: typeof mongodb.BSON;
20
+ EJSON: {
21
+ parse: (text: string, options?: mongodb.BSON.EJSONOptions) => any;
22
+ stringify: (value: any, replacer?: (number | string)[] | ((this: any, key: string, value: any) => any) | mongodb.BSON.EJSONOptions, space?: string | number, options?: mongodb.BSON.EJSONOptions) => string;
23
+ serialize: (value: any, options?: mongodb.BSON.EJSONOptions) => mongodb.BSON.Document;
24
+ deserialize: (ejson: mongodb.BSON.Document, options?: mongodb.BSON.EJSONOptions) => any;
25
+ };
20
26
  Buffer: BufferConstructor;
21
27
  utils: {
22
28
  jwt: JwtUtils;
@@ -1 +1 @@
1
- {"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../../../src/utils/context/helpers.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAA;AAE1C,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAA;AAE3C,OAAO,EAAE,yBAAyB,EAAE,MAAM,aAAa,CAAA;AAEvD,KAAK,QAAQ,GAAG;IACd,MAAM,EAAE,CACN,aAAa,EAAE,MAAM,EACrB,OAAO,EAAE,OAAO,EAChB,MAAM,EAAE,MAAM,GAAG,MAAM,EACvB,kBAAkB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KACzC,MAAM,CAAA;IACX,MAAM,EAAE,CACN,SAAS,EAAE,MAAM,EACjB,GAAG,EAAE,MAAM,GAAG,MAAM,EACpB,YAAY,CAAC,EAAE,OAAO,EACtB,sBAAsB,CAAC,EAAE,MAAM,EAAE,KAC9B,OAAO,CAAA;CACb,CAAA;AAgFD;;;;;;;;;GASG;AACH,eAAO,MAAM,mBAAmB,GAAI,wGAUjC,yBAAyB;;;;;;;uBA2DP,SAAS;yBAGP,SAAS;;;;;;;;;;;;;;;;;;uBAcb,MAAM;;;;;;+BA3CU,MAAM,OAAO,QAAQ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8BApBpB,CAAC;iCAAa,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;0BAAf,CAAC;6BAAa,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;0BAAf,CAAC;6BAAa,CAAC;;;;;;;;;;;;;;;4BAwE3B,MAAM,OAAO,aAAa,WAAW,SAAS;;;CAgBrE,CAAA"}
1
+ {"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../../../src/utils/context/helpers.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAA;AAE1C,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAA;AAE3C,OAAO,EAAE,yBAAyB,EAAE,MAAM,aAAa,CAAA;AAGvD,KAAK,QAAQ,GAAG;IACd,MAAM,EAAE,CACN,aAAa,EAAE,MAAM,EACrB,OAAO,EAAE,OAAO,EAChB,MAAM,EAAE,MAAM,GAAG,MAAM,EACvB,kBAAkB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KACzC,MAAM,CAAA;IACX,MAAM,EAAE,CACN,SAAS,EAAE,MAAM,EACjB,GAAG,EAAE,MAAM,GAAG,MAAM,EACpB,YAAY,CAAC,EAAE,OAAO,EACtB,sBAAsB,CAAC,EAAE,MAAM,EAAE,KAC9B,OAAO,CAAA;CACb,CAAA;AAgFD;;;;;;;;;GASG;AACH,eAAO,MAAM,mBAAmB,GAAI,wGAUjC,yBAAyB;;;;;;;;;;;;;uBA4DP,SAAS;yBAGP,SAAS;;;;;;;;;;;;;;;;;;uBAcb,MAAM;;;;;;+BA5CU,MAAM,OAAO,QAAQ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8BApBzC,CAAC;iCAAa,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;0BAAf,CAAC;6BAAa,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;0BAAf,CAAC;6BAAa,CAAC;;;;;;;;;;;;;;;4BAyEN,MAAM,OAAO,aAAa,WAAW,SAAS;;;CAgBrE,CAAA"}
@@ -36,6 +36,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
36
36
  exports.generateContextData = void 0;
37
37
  const mongodb_1 = require("@fastify/mongodb");
38
38
  const jwt = __importStar(require("jsonwebtoken"));
39
+ const bson_1 = require("bson");
39
40
  const normalizePayload = (payload) => {
40
41
  if (typeof payload !== 'string')
41
42
  return payload;
@@ -147,6 +148,7 @@ const generateContextData = ({ user, services, app, rules, currentFunction, func
147
148
  };
148
149
  return {
149
150
  BSON,
151
+ EJSON: bson_1.EJSON,
150
152
  Buffer,
151
153
  utils,
152
154
  console: {
@@ -291,6 +291,15 @@ export type Operators = {
291
291
  * @returns
292
292
  */
293
293
  $all: OperatorsFunction;
294
+ /**
295
+ * @param a
296
+ * @param b
297
+ *
298
+ * Checks whether the length of the user input array is equal to the rule value.
299
+ *
300
+ * @returns
301
+ */
302
+ $size: OperatorsFunction;
294
303
  /**
295
304
  * @param a
296
305
  * @param b
@@ -318,6 +327,7 @@ export declare enum RulesOperators {
318
327
  $in = "$in",
319
328
  $nin = "$nin",
320
329
  $all = "$all",
330
+ $size = "$size",
321
331
  $regex = "$regex"
322
332
  }
323
333
  export type RulesOperatorsInArray<T> = Partial<{
@@ -1 +1 @@
1
- {"version":3,"file":"interface.d.ts","sourceRoot":"","sources":["../../../src/utils/rules-matcher/interface.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"interface.d.ts","sourceRoot":"","sources":["../../../src/utils/rules-matcher/interface.ts"],"names":[],"mappings":"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"}
@@ -17,6 +17,7 @@ var RulesOperators;
17
17
  RulesOperators["$in"] = "$in";
18
18
  RulesOperators["$nin"] = "$nin";
19
19
  RulesOperators["$all"] = "$all";
20
+ RulesOperators["$size"] = "$size";
20
21
  RulesOperators["$regex"] = "$regex";
21
22
  })(RulesOperators || (exports.RulesOperators = RulesOperators = {}));
22
23
  var RulesModes;
@@ -1 +1 @@
1
- {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../src/utils/rules-matcher/utils.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,SAAS,EAAE,iBAAiB,EAAe,MAAM,aAAa,CAAA;AAIvE;;GAEG;AACH,QAAA,MAAM,iBAAiB,EAAE,iBAsNxB,CAAA;AAED;;GAEG;AACH,eAAO,MAAM,SAAS,EAAE,SAsDvB,CAAA;AAID,eAAe,iBAAiB,CAAA"}
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../src/utils/rules-matcher/utils.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,SAAS,EAAE,iBAAiB,EAAe,MAAM,aAAa,CAAA;AAIvE;;GAEG;AACH,QAAA,MAAM,iBAAiB,EAAE,iBAsNxB,CAAA;AAED;;GAEG;AACH,eAAO,MAAM,SAAS,EAAE,SAwDvB,CAAA;AAID,eAAe,iBAAiB,CAAA"}
@@ -209,6 +209,7 @@ exports.operators = {
209
209
  .forceArray(b)
210
210
  .every((c) => (0, intersection_1.default)(rulesMatcherUtils.forceArray(a), rulesMatcherUtils.forceArray(c))
211
211
  .length),
212
+ $size: (a, b) => Array.isArray(a) && a.length === parseFloat(b),
212
213
  $regex: (a, b, opt) => rulesMatcherUtils
213
214
  .forceArray(b)
214
215
  .some((c) => (c instanceof RegExp ? c.test(a) : new RegExp(c, opt).test(a)))
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@flowerforce/flowerbase",
3
- "version": "1.7.1",
3
+ "version": "1.7.2-beta.1",
4
4
  "description": "",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -49,6 +49,7 @@
49
49
  "@eslint/js": "^9.12.0",
50
50
  "@types/cors": "^2.8.17",
51
51
  "@types/jest": "^29.5.14",
52
+ "@types/jsonwebtoken": "^9.0.10",
52
53
  "@types/lodash": "^4.17.9",
53
54
  "@types/node": "22.6.1",
54
55
  "@types/node-cron": "^3.0.11",
@@ -108,6 +108,11 @@ export const executeQuery = async ({
108
108
  EJSON.deserialize(resolvedQuery),
109
109
  parsedOptions
110
110
  ),
111
+ countDocuments: () =>
112
+ (currentMethod as ReturnType<GetOperatorsFunction>['countDocuments'])(
113
+ EJSON.deserialize(resolvedQuery),
114
+ parsedOptions
115
+ ),
111
116
  deleteOne: () =>
112
117
  (currentMethod as ReturnType<GetOperatorsFunction>['deleteOne'])(
113
118
  EJSON.deserialize(resolvedQuery),
@@ -30,7 +30,7 @@ export const activateTriggers = async ({
30
30
  triggersToActivate.push({
31
31
  fileName: '__auto_on_user_creation_trigger__.json',
32
32
  content: {
33
- name: 'onUserCreation',
33
+ name: AUTH_CONFIG.on_user_creation_function_name,
34
34
  type: 'AUTHENTICATION',
35
35
  disabled: false,
36
36
  config: {
@@ -10,6 +10,7 @@ type EndpointInvokeBody = {
10
10
  query?: Record<string, unknown>
11
11
  headers?: Record<string, unknown>
12
12
  payload?: unknown
13
+ functionName?: string
13
14
  }
14
15
 
15
16
  type EndpointResponse = {
@@ -41,6 +42,10 @@ const buildQueryString = (query?: Record<string, unknown>) => {
41
42
  return params.toString()
42
43
  }
43
44
 
45
+ const normalizeRoute = (value?: string) => {
46
+ return (value || '').replace(/^\/+/, '').trim()
47
+ }
48
+
44
49
  const normalizeHeaders = (headers?: Record<string, unknown>) => {
45
50
  const normalized: Record<string, string> = {}
46
51
  if (!headers) return normalized
@@ -84,10 +89,13 @@ export const registerEndpointRoutes = (app: FastifyInstance, deps: EndpointRoute
84
89
  reply.code(400)
85
90
  return { error: 'Project ID not available' }
86
91
  }
87
- const normalizedRoute = route.replace(/^\/+/, '')
92
+ const normalizedRoute = normalizeRoute(route)
88
93
  const rawMethod = (body.method || 'POST').toUpperCase()
89
94
  const method = rawMethod as InjectOptions['method']
90
95
  const effectiveMethod = (rawMethod === 'ALL' ? 'POST' : rawMethod) as InjectOptions['method']
96
+ const functionName = body.functionName?.trim()
97
+ const functionsList = StateManager.select('functions') as Record<string, { run_as_system?: boolean }>
98
+ const runAsSystem = functionName ? !!functionsList?.[functionName]?.run_as_system : undefined
91
99
  const queryString = buildQueryString(body.query)
92
100
  const encodedProjectId = encodeURIComponent(projectId)
93
101
  const baseUrl = `/app/${encodedProjectId}/endpoint/${normalizedRoute}`
@@ -111,20 +119,42 @@ export const registerEndpointRoutes = (app: FastifyInstance, deps: EndpointRoute
111
119
  headers,
112
120
  payload
113
121
  }
114
- const response = await app.inject(injectOptions) as InjectResponse
115
- const parsedBody = parseInjectResponse(response.payload)
116
- const responseHeaders: Record<string, string> = {}
117
- Object.entries(response.headers ?? {}).forEach(([key, value]) => {
118
- if (value === undefined) return
119
- responseHeaders[key] = Array.isArray(value) ? value.join(', ') : String(value)
120
- })
121
122
  addEvent({
122
123
  id: createEventId(),
123
124
  ts: Date.now(),
124
125
  type: 'http_endpoint',
125
126
  source: 'monit',
126
127
  message: `${rawMethod} ${route}`,
127
- data: sanitize({ method: effectiveMethod, route, query: body.query, headers: body.headers, payload: body.payload })
128
+ data: sanitize({
129
+ method: effectiveMethod,
130
+ route,
131
+ query: body.query,
132
+ headers: body.headers,
133
+ payload: body.payload,
134
+ functionName
135
+ })
136
+ })
137
+ if (functionName) {
138
+ addEvent({
139
+ id: createEventId(),
140
+ ts: Date.now(),
141
+ type: 'function',
142
+ source: 'monit',
143
+ message: `invoke ${functionName}`,
144
+ data: sanitize({
145
+ name: functionName,
146
+ runAsSystem,
147
+ invokedFrom: functionName,
148
+ endpoint: { method: rawMethod, route }
149
+ })
150
+ })
151
+ }
152
+ const response = await app.inject(injectOptions) as InjectResponse
153
+ const parsedBody = parseInjectResponse(response.payload)
154
+ const responseHeaders: Record<string, string> = {}
155
+ Object.entries(response.headers ?? {}).forEach(([key, value]) => {
156
+ if (value === undefined) return
157
+ responseHeaders[key] = Array.isArray(value) ? value.join(', ') : String(value)
128
158
  })
129
159
  const result: EndpointResponse = {
130
160
  statusCode: response.statusCode,
@@ -149,20 +149,22 @@ export const registerUserRoutes = (app: FastifyInstance, deps: UserRoutesDeps) =
149
149
 
150
150
  const userId = result?.insertedId?.toString()
151
151
 
152
+ /*
153
+ non deve essere fatto, solo i trigger creano gli users
152
154
  if (userId && AUTH_CONFIG.userCollection && AUTH_CONFIG.user_id_field) {
153
- const db = app.mongo.client.db(DB_NAME)
154
- const customData = body?.customData ?? {}
155
- await db.collection(AUTH_CONFIG.userCollection).updateOne(
156
- { [AUTH_CONFIG.user_id_field]: userId },
157
- {
158
- $set: {
159
- ...customData,
160
- [AUTH_CONFIG.user_id_field]: userId
161
- }
162
- },
163
- { upsert: true }
164
- )
165
- }
155
+ const db = app.mongo.client.db(DB_NAME)
156
+ const customData = body?.customData ?? {}
157
+ await db.collection(AUTH_CONFIG.userCollection).updateOne(
158
+ { [AUTH_CONFIG.user_id_field]: userId },
159
+ {
160
+ $set: {
161
+ ...customData,
162
+ [AUTH_CONFIG.user_id_field]: userId
163
+ }
164
+ },
165
+ { upsert: true }
166
+ )
167
+ } */
166
168
 
167
169
  addEvent({
168
170
  id: createEventId(),
@@ -351,6 +351,7 @@
351
351
  method: 'POST',
352
352
  body: JSON.stringify({
353
353
  route: state.selectedEndpoint.route,
354
+ functionName: state.selectedEndpoint.function_name,
354
355
  method,
355
356
  query,
356
357
  headers,
@@ -84,4 +84,37 @@ describe('mongodb-atlas count', () => {
84
84
  expect(result).toBe(42)
85
85
  expect(countDocuments).toHaveBeenCalledWith({ workspace: 'workspace-2' }, options)
86
86
  })
87
+
88
+ it('supports countDocuments alias with RBAC filtering', async () => {
89
+ const countDocuments = jest.fn().mockResolvedValue(3)
90
+ const collection = {
91
+ collectionName: 'todos',
92
+ countDocuments
93
+ }
94
+
95
+ const rules = {
96
+ filters: [
97
+ {
98
+ name: 'ownerFilter',
99
+ query: { ownerId: 'user-1' },
100
+ apply_when: {}
101
+ }
102
+ ]
103
+ }
104
+
105
+ const operators = MongoDbAtlas(createAppWithCollection(collection) as any, {
106
+ rules: createRules(rules),
107
+ user: { id: 'user-1' }
108
+ })
109
+ .db('db')
110
+ .collection('todos')
111
+
112
+ const result = await operators.countDocuments({ workspace: 'workspace-1' })
113
+
114
+ expect(result).toBe(3)
115
+ expect(countDocuments).toHaveBeenCalledWith(
116
+ { $and: [{ ownerId: 'user-1' }, { workspace: 'workspace-1' }] },
117
+ undefined
118
+ )
119
+ })
87
120
  })
@@ -628,6 +628,26 @@ const getOperators: GetOperatorsFunction = (
628
628
  throw error
629
629
  }
630
630
  },
631
+ countDocuments: async (query, options) => {
632
+ try {
633
+ if (!run_as_system) {
634
+ checkDenyOperation(normalizedRules, collection.collectionName, CRUD_OPERATIONS.READ)
635
+ const formattedQuery = getFormattedQuery(filters, query, user)
636
+ const currentQuery = formattedQuery.length ? { $and: formattedQuery } : {}
637
+ logService('countDocuments query', { collName, currentQuery })
638
+ const result = await collection.countDocuments(currentQuery, options)
639
+ emitMongoEvent('countDocuments')
640
+ return result
641
+ }
642
+
643
+ const result = await collection.countDocuments(query, options)
644
+ emitMongoEvent('countDocuments')
645
+ return result
646
+ } catch (error) {
647
+ emitMongoEvent('countDocuments', undefined, error)
648
+ throw error
649
+ }
650
+ },
631
651
  /**
632
652
  * Watches changes on a MongoDB collection with optional role-based filtering of change events.
633
653
  *
@@ -81,6 +81,9 @@ export type GetOperatorsFunction = (
81
81
  count: (
82
82
  ...params: Parameters<Method<'countDocuments'>>
83
83
  ) => ReturnType<Method<'countDocuments'>>
84
+ countDocuments: (
85
+ ...params: Parameters<Method<'countDocuments'>>
86
+ ) => ReturnType<Method<'countDocuments'>>
84
87
  watch: (...params: Parameters<Method<'watch'>>) => ReturnType<Method<'watch'>>
85
88
  aggregate: (
86
89
  ...params: [...Parameters<Method<'aggregate'>>, isClient: boolean]
@@ -0,0 +1,52 @@
1
+ import { EJSON } from 'bson'
2
+ import { ObjectId } from 'mongodb'
3
+ import { Function, Functions } from '../../features/functions/interface'
4
+ import { FunctionsQueue } from '../../features/functions/queue'
5
+ import { StateManager } from '../../state'
6
+ import { Services } from '../../services/interface'
7
+ import { GenerateContext } from '../context'
8
+
9
+ describe('GenerateContext with function using EJSON', () => {
10
+ beforeEach(() => {
11
+ StateManager.setData('functionsQueue', new FunctionsQueue())
12
+ })
13
+
14
+ it('runs a function that uses EJSON in the sandbox', async () => {
15
+ const objectId = new ObjectId('65b7f1c5e1c6d44f8a1b2c3d')
16
+ const createdAt = new Date('2025-01-01T00:00:00.000Z')
17
+
18
+ const currentFunction: Function = {
19
+ code: `
20
+ module.exports = (doc) => {
21
+ return EJSON.serialize({ _id: doc._id, createdAt: doc.createdAt })
22
+ }
23
+ `
24
+ }
25
+
26
+ const functionsList: Functions = {
27
+ usesEjson: currentFunction
28
+ }
29
+
30
+ const services: Services = {
31
+ api: jest.fn().mockReturnValue({}),
32
+ aws: jest.fn().mockReturnValue({}),
33
+ auth: jest.fn().mockReturnValue({}),
34
+ 'mongodb-atlas': jest.fn().mockReturnValue({})
35
+ } as unknown as Services
36
+
37
+ const result = await GenerateContext({
38
+ args: [EJSON.serialize({ _id: objectId, createdAt })],
39
+ app: {} as any,
40
+ rules: {},
41
+ user: {},
42
+ currentFunction,
43
+ functionsList,
44
+ services
45
+ })
46
+
47
+ expect(result).toEqual({
48
+ _id: { $oid: objectId.toHexString() },
49
+ createdAt: { $date: '2025-01-01T00:00:00Z' }
50
+ })
51
+ })
52
+ })
@@ -86,6 +86,12 @@ describe('operators', () => {
86
86
  expect(operators.$all({ name: 'ciao' }, [{ name: 'ciao' }, 4, 5])).toBe(false)
87
87
  expect(operators.$all([{ name: 'ciao' }, 4, 5], [{ name: 'ciao' }, 4, 5])).toBe(false)
88
88
  })
89
+ it('should check array size', () => {
90
+ expect(operators.$size([1, 2, 3], 3)).toBe(true)
91
+ expect(operators.$size([1, 2, 3], 2)).toBe(false)
92
+ expect(operators.$size([], 0)).toBe(true)
93
+ expect(operators.$size('not-array', 0)).toBe(false)
94
+ })
89
95
  it('should check regex', () => {
90
96
  const emailRegex = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/
91
97
  expect(operators.$regex('test@gmail.com', emailRegex)).toBe(true)
@@ -3,6 +3,7 @@ import * as jwt from 'jsonwebtoken'
3
3
  import { Arguments } from '../../auth/dtos'
4
4
  import { Function } from '../../features/functions/interface'
5
5
  import { GenerateContextDataParams } from './interface'
6
+ import { EJSON } from 'bson'
6
7
 
7
8
  type JwtUtils = {
8
9
  encode: (
@@ -121,10 +122,10 @@ export const generateContextData = ({
121
122
  const BSON = mongodb.BSON
122
123
  const Binary = BSON?.Binary as
123
124
  | (typeof mongodb.BSON.Binary & {
124
- fromBase64?: (base64: string, subType?: number) => mongodb.BSON.Binary | Uint8Array
125
- fromBase64Binary?: (base64: string, subType?: number) => mongodb.BSON.Binary
126
- __fb_fromBase64Wrapped?: boolean
127
- })
125
+ fromBase64?: (base64: string, subType?: number) => mongodb.BSON.Binary | Uint8Array
126
+ fromBase64Binary?: (base64: string, subType?: number) => mongodb.BSON.Binary
127
+ __fb_fromBase64Wrapped?: boolean
128
+ })
128
129
  | undefined
129
130
 
130
131
  if (Binary && typeof Binary.fromBase64 !== 'function') {
@@ -173,6 +174,7 @@ export const generateContextData = ({
173
174
 
174
175
  return {
175
176
  BSON,
177
+ EJSON,
176
178
  Buffer,
177
179
  utils,
178
180
  console: {
@@ -311,6 +311,15 @@ export type Operators = {
311
311
  * @returns
312
312
  */
313
313
  $all: OperatorsFunction
314
+ /**
315
+ * @param a
316
+ * @param b
317
+ *
318
+ * Checks whether the length of the user input array is equal to the rule value.
319
+ *
320
+ * @returns
321
+ */
322
+ $size: OperatorsFunction
314
323
  /**
315
324
  * @param a
316
325
  * @param b
@@ -339,6 +348,7 @@ export enum RulesOperators {
339
348
  $in = '$in',
340
349
  $nin = '$nin',
341
350
  $all = '$all',
351
+ $size = '$size',
342
352
  $regex = '$regex'
343
353
  }
344
354
 
@@ -277,6 +277,8 @@ export const operators: Operators = {
277
277
  .length
278
278
  ),
279
279
 
280
+ $size: (a, b) => Array.isArray(a) && a.length === parseFloat(b),
281
+
280
282
  $regex: (a, b, opt) =>
281
283
  rulesMatcherUtils
282
284
  .forceArray(b)