@flowerforce/flowerbase 1.2.0 → 1.2.1-beta.10

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 (125) hide show
  1. package/README.md +28 -3
  2. package/dist/auth/controller.d.ts.map +1 -1
  3. package/dist/auth/controller.js +57 -3
  4. package/dist/auth/plugins/jwt.d.ts.map +1 -1
  5. package/dist/auth/plugins/jwt.js +49 -3
  6. package/dist/auth/providers/custom-function/controller.d.ts.map +1 -1
  7. package/dist/auth/providers/custom-function/controller.js +19 -3
  8. package/dist/auth/providers/local-userpass/controller.d.ts.map +1 -1
  9. package/dist/auth/providers/local-userpass/controller.js +125 -71
  10. package/dist/auth/providers/local-userpass/dtos.d.ts +11 -2
  11. package/dist/auth/providers/local-userpass/dtos.d.ts.map +1 -1
  12. package/dist/auth/utils.d.ts +53 -14
  13. package/dist/auth/utils.d.ts.map +1 -1
  14. package/dist/auth/utils.js +46 -63
  15. package/dist/constants.d.ts +13 -0
  16. package/dist/constants.d.ts.map +1 -1
  17. package/dist/constants.js +14 -2
  18. package/dist/features/functions/controller.d.ts.map +1 -1
  19. package/dist/features/functions/controller.js +32 -3
  20. package/dist/features/functions/dtos.d.ts +3 -0
  21. package/dist/features/functions/dtos.d.ts.map +1 -1
  22. package/dist/features/functions/interface.d.ts +3 -0
  23. package/dist/features/functions/interface.d.ts.map +1 -1
  24. package/dist/features/functions/utils.d.ts +2 -1
  25. package/dist/features/functions/utils.d.ts.map +1 -1
  26. package/dist/features/functions/utils.js +19 -7
  27. package/dist/features/rules/utils.d.ts.map +1 -1
  28. package/dist/features/rules/utils.js +11 -2
  29. package/dist/features/triggers/index.d.ts.map +1 -1
  30. package/dist/features/triggers/index.js +48 -7
  31. package/dist/features/triggers/utils.d.ts.map +1 -1
  32. package/dist/features/triggers/utils.js +118 -27
  33. package/dist/index.d.ts +8 -1
  34. package/dist/index.d.ts.map +1 -1
  35. package/dist/index.js +57 -21
  36. package/dist/services/mongodb-atlas/index.d.ts.map +1 -1
  37. package/dist/services/mongodb-atlas/index.js +605 -478
  38. package/dist/services/mongodb-atlas/model.d.ts +2 -1
  39. package/dist/services/mongodb-atlas/model.d.ts.map +1 -1
  40. package/dist/services/mongodb-atlas/utils.d.ts +9 -2
  41. package/dist/services/mongodb-atlas/utils.d.ts.map +1 -1
  42. package/dist/services/mongodb-atlas/utils.js +113 -23
  43. package/dist/shared/handleUserRegistration.d.ts.map +1 -1
  44. package/dist/shared/handleUserRegistration.js +1 -0
  45. package/dist/shared/models/handleUserRegistration.model.d.ts +6 -2
  46. package/dist/shared/models/handleUserRegistration.model.d.ts.map +1 -1
  47. package/dist/utils/context/helpers.d.ts +7 -6
  48. package/dist/utils/context/helpers.d.ts.map +1 -1
  49. package/dist/utils/context/helpers.js +3 -0
  50. package/dist/utils/context/index.d.ts +1 -1
  51. package/dist/utils/context/index.d.ts.map +1 -1
  52. package/dist/utils/context/index.js +176 -5
  53. package/dist/utils/context/interface.d.ts +1 -1
  54. package/dist/utils/context/interface.d.ts.map +1 -1
  55. package/dist/utils/crypto/index.d.ts +1 -0
  56. package/dist/utils/crypto/index.d.ts.map +1 -1
  57. package/dist/utils/crypto/index.js +6 -2
  58. package/dist/utils/initializer/exposeRoutes.d.ts.map +1 -1
  59. package/dist/utils/initializer/exposeRoutes.js +11 -4
  60. package/dist/utils/initializer/registerPlugins.d.ts +3 -1
  61. package/dist/utils/initializer/registerPlugins.d.ts.map +1 -1
  62. package/dist/utils/initializer/registerPlugins.js +9 -6
  63. package/dist/utils/roles/helpers.js +11 -3
  64. package/dist/utils/roles/machines/commonValidators.d.ts.map +1 -1
  65. package/dist/utils/roles/machines/commonValidators.js +10 -6
  66. package/dist/utils/roles/machines/read/B/validators.d.ts +4 -0
  67. package/dist/utils/roles/machines/read/B/validators.d.ts.map +1 -0
  68. package/dist/utils/roles/machines/read/B/validators.js +8 -0
  69. package/dist/utils/roles/machines/read/C/index.d.ts.map +1 -1
  70. package/dist/utils/roles/machines/read/C/index.js +10 -7
  71. package/dist/utils/roles/machines/read/C/validators.d.ts +5 -0
  72. package/dist/utils/roles/machines/read/C/validators.d.ts.map +1 -0
  73. package/dist/utils/roles/machines/read/C/validators.js +29 -0
  74. package/dist/utils/roles/machines/read/D/index.d.ts.map +1 -1
  75. package/dist/utils/roles/machines/read/D/index.js +13 -11
  76. package/dist/utils/rules.d.ts +1 -1
  77. package/dist/utils/rules.d.ts.map +1 -1
  78. package/dist/utils/rules.js +26 -17
  79. package/jest.config.ts +2 -12
  80. package/jest.setup.ts +28 -0
  81. package/package.json +1 -2
  82. package/src/auth/controller.ts +70 -4
  83. package/src/auth/plugins/jwt.test.ts +93 -0
  84. package/src/auth/plugins/jwt.ts +62 -3
  85. package/src/auth/providers/custom-function/controller.ts +22 -5
  86. package/src/auth/providers/local-userpass/controller.ts +168 -96
  87. package/src/auth/providers/local-userpass/dtos.ts +13 -2
  88. package/src/auth/utils.ts +51 -86
  89. package/src/constants.ts +16 -3
  90. package/src/fastify.d.ts +32 -15
  91. package/src/features/functions/controller.ts +51 -3
  92. package/src/features/functions/dtos.ts +3 -0
  93. package/src/features/functions/interface.ts +3 -0
  94. package/src/features/functions/utils.ts +29 -8
  95. package/src/features/rules/utils.ts +11 -2
  96. package/src/features/triggers/index.ts +43 -1
  97. package/src/features/triggers/utils.ts +146 -38
  98. package/src/index.ts +69 -20
  99. package/src/services/mongodb-atlas/__tests__/findOneAndUpdate.test.ts +95 -0
  100. package/src/services/mongodb-atlas/__tests__/utils.test.ts +141 -0
  101. package/src/services/mongodb-atlas/index.ts +241 -90
  102. package/src/services/mongodb-atlas/model.ts +15 -2
  103. package/src/services/mongodb-atlas/utils.ts +158 -22
  104. package/src/shared/handleUserRegistration.ts +3 -3
  105. package/src/shared/models/handleUserRegistration.model.ts +8 -3
  106. package/src/types/fastify-raw-body.d.ts +22 -0
  107. package/src/utils/__tests__/STEP_B_STATES.test.ts +1 -1
  108. package/src/utils/__tests__/STEP_C_STATES.test.ts +1 -1
  109. package/src/utils/__tests__/STEP_D_STATES.test.ts +2 -2
  110. package/src/utils/__tests__/checkIsValidFieldNameFn.test.ts +9 -4
  111. package/src/utils/__tests__/registerPlugins.test.ts +16 -1
  112. package/src/utils/context/helpers.ts +3 -0
  113. package/src/utils/context/index.ts +238 -13
  114. package/src/utils/context/interface.ts +1 -1
  115. package/src/utils/crypto/index.ts +5 -1
  116. package/src/utils/initializer/exposeRoutes.ts +15 -8
  117. package/src/utils/initializer/registerPlugins.ts +15 -7
  118. package/src/utils/roles/helpers.ts +23 -5
  119. package/src/utils/roles/machines/commonValidators.ts +10 -5
  120. package/src/utils/roles/machines/read/B/validators.ts +8 -0
  121. package/src/utils/roles/machines/read/C/index.ts +11 -7
  122. package/src/utils/roles/machines/read/C/validators.ts +21 -0
  123. package/src/utils/roles/machines/read/D/index.ts +22 -12
  124. package/src/utils/rules.ts +31 -22
  125. package/tsconfig.spec.json +7 -0
@@ -12,7 +12,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
12
12
  return (mod && mod.__esModule) ? mod : { "default": mod };
13
13
  };
14
14
  Object.defineProperty(exports, "__esModule", { value: true });
15
- exports.generateToken = exports.comparePassword = exports.hashPassword = void 0;
15
+ exports.hashToken = exports.generateToken = exports.comparePassword = exports.hashPassword = void 0;
16
16
  const node_crypto_1 = __importDefault(require("node:crypto"));
17
17
  const node_util_1 = require("node:util");
18
18
  const scrypt = (0, node_util_1.promisify)(node_crypto_1.default.scrypt);
@@ -47,7 +47,11 @@ exports.comparePassword = comparePassword;
47
47
  * > Generate a random token
48
48
  * @param length -> the token length
49
49
  */
50
- const generateToken = (length = 32) => {
50
+ const generateToken = (length = 64) => {
51
51
  return node_crypto_1.default.randomBytes(length).toString('hex');
52
52
  };
53
53
  exports.generateToken = generateToken;
54
+ const hashToken = (token) => {
55
+ return node_crypto_1.default.createHash('sha256').update(token).digest('hex');
56
+ };
57
+ exports.hashToken = hashToken;
@@ -1 +1 @@
1
- {"version":3,"file":"exposeRoutes.d.ts","sourceRoot":"","sources":["../../../src/utils/initializer/exposeRoutes.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,eAAe,EAAE,MAAM,SAAS,CAAA;AAOzC;;;;GAIG;AACH,eAAO,MAAM,YAAY,GAAU,SAAS,eAAe,kBAiE1D,CAAA"}
1
+ {"version":3,"file":"exposeRoutes.d.ts","sourceRoot":"","sources":["../../../src/utils/initializer/exposeRoutes.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,eAAe,EAAE,MAAM,SAAS,CAAA;AAOzC;;;;GAIG;AACH,eAAO,MAAM,YAAY,GAAU,SAAS,eAAe,kBA0E1D,CAAA"}
@@ -23,12 +23,19 @@ const crypto_1 = require("../crypto");
23
23
  const exposeRoutes = (fastify) => __awaiter(void 0, void 0, void 0, function* () {
24
24
  try {
25
25
  fastify.get(`${constants_1.API_VERSION}/app/:appId/location`, (req) => __awaiter(void 0, void 0, void 0, function* () {
26
- return ({
26
+ var _a, _b, _c;
27
+ const schema = (_a = constants_1.DEFAULT_CONFIG === null || constants_1.DEFAULT_CONFIG === void 0 ? void 0 : constants_1.DEFAULT_CONFIG.HTTPS_SCHEMA) !== null && _a !== void 0 ? _a : 'http';
28
+ const headerHost = (_b = req.headers.host) !== null && _b !== void 0 ? _b : 'localhost:3000';
29
+ const hostname = headerHost.split(':')[0];
30
+ const port = (_c = constants_1.DEFAULT_CONFIG === null || constants_1.DEFAULT_CONFIG === void 0 ? void 0 : constants_1.DEFAULT_CONFIG.PORT) !== null && _c !== void 0 ? _c : 3000;
31
+ const host = `${hostname}:${port}`;
32
+ const wsSchema = 'wss';
33
+ return {
27
34
  deployment_model: 'LOCAL',
28
35
  location: 'IE',
29
- hostname: `${constants_1.DEFAULT_CONFIG.HTTPS_SCHEMA}://${req.headers.host}`,
30
- ws_hostname: `${constants_1.DEFAULT_CONFIG.HTTPS_SCHEMA === 'https' ? 'wss' : 'ws'}://${req.headers.host}`
31
- });
36
+ hostname: `${schema}://${host}`,
37
+ ws_hostname: `${wsSchema}://${host}`
38
+ };
32
39
  }));
33
40
  fastify.get('/health', () => __awaiter(void 0, void 0, void 0, function* () {
34
41
  return ({
@@ -1,4 +1,5 @@
1
1
  import { FastifyInstance } from 'fastify';
2
+ import { CorsConfig } from '../../';
2
3
  import { Functions } from '../../features/functions/interface';
3
4
  type RegisterFunction = FastifyInstance['register'];
4
5
  type RegisterPluginsParams = {
@@ -6,6 +7,7 @@ type RegisterPluginsParams = {
6
7
  mongodbUrl: string;
7
8
  jwtSecret: string;
8
9
  functionsList: Functions;
10
+ corsConfig?: CorsConfig;
9
11
  };
10
12
  /**
11
13
  * > Used to register all plugins
@@ -14,6 +16,6 @@ type RegisterPluginsParams = {
14
16
  * @param jwtSecret -> connection jwt
15
17
  * @tested
16
18
  */
17
- export declare const registerPlugins: ({ register, mongodbUrl, jwtSecret, functionsList }: RegisterPluginsParams) => Promise<void>;
19
+ export declare const registerPlugins: ({ register, mongodbUrl, jwtSecret, functionsList, corsConfig }: RegisterPluginsParams) => Promise<void>;
18
20
  export {};
19
21
  //# sourceMappingURL=registerPlugins.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"registerPlugins.d.ts","sourceRoot":"","sources":["../../../src/utils/initializer/registerPlugins.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,eAAe,EAAE,MAAM,SAAS,CAAA;AAOzC,OAAO,EAAE,SAAS,EAAE,MAAM,oCAAoC,CAAA;AAE9D,KAAK,gBAAgB,GAAG,eAAe,CAAC,UAAU,CAAC,CAAA;AAGnD,KAAK,qBAAqB,GAAG;IAC3B,QAAQ,EAAE,gBAAgB,CAAA;IAC1B,UAAU,EAAE,MAAM,CAAA;IAClB,SAAS,EAAE,MAAM,CAAA;IACjB,aAAa,EAAE,SAAS,CAAA;CACzB,CAAA;AAQD;;;;;;GAMG;AACH,eAAO,MAAM,eAAe,GAAU,oDAKnC,qBAAqB,kBAoBvB,CAAA"}
1
+ {"version":3,"file":"registerPlugins.d.ts","sourceRoot":"","sources":["../../../src/utils/initializer/registerPlugins.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,eAAe,EAAE,MAAM,SAAS,CAAA;AAEzC,OAAO,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAA;AAMnC,OAAO,EAAE,SAAS,EAAE,MAAM,oCAAoC,CAAA;AAE9D,KAAK,gBAAgB,GAAG,eAAe,CAAC,UAAU,CAAC,CAAA;AAGnD,KAAK,qBAAqB,GAAG;IAC3B,QAAQ,EAAE,gBAAgB,CAAA;IAC1B,UAAU,EAAE,MAAM,CAAA;IAClB,SAAS,EAAE,MAAM,CAAA;IACjB,aAAa,EAAE,SAAS,CAAA;IACxB,UAAU,CAAC,EAAE,UAAU,CAAA;CACxB,CAAA;AAQD;;;;;;GAMG;AACH,eAAO,MAAM,eAAe,GAAU,gEAMnC,qBAAqB,kBAsBvB,CAAA"}
@@ -28,11 +28,12 @@ const constants_1 = require("../../constants");
28
28
  * @param jwtSecret -> connection jwt
29
29
  * @tested
30
30
  */
31
- const registerPlugins = (_a) => __awaiter(void 0, [_a], void 0, function* ({ register, mongodbUrl, jwtSecret, functionsList }) {
31
+ const registerPlugins = (_a) => __awaiter(void 0, [_a], void 0, function* ({ register, mongodbUrl, jwtSecret, functionsList, corsConfig }) {
32
32
  try {
33
33
  const registersConfig = yield getRegisterConfig({
34
34
  mongodbUrl,
35
35
  jwtSecret,
36
+ corsConfig,
36
37
  functionsList
37
38
  });
38
39
  registersConfig.forEach(({ plugin, options, pluginName }) => {
@@ -43,6 +44,7 @@ const registerPlugins = (_a) => __awaiter(void 0, [_a], void 0, function* ({ reg
43
44
  catch (e) {
44
45
  console.log('Registration FAILED --->', pluginName);
45
46
  console.log('Error --->', e);
47
+ throw e;
46
48
  }
47
49
  });
48
50
  }
@@ -57,15 +59,16 @@ exports.registerPlugins = registerPlugins;
57
59
  * @param jwtSecret -> connection jwt
58
60
  * @testable
59
61
  */
60
- const getRegisterConfig = (_a) => __awaiter(void 0, [_a], void 0, function* ({ mongodbUrl, jwtSecret }) {
62
+ const getRegisterConfig = (_a) => __awaiter(void 0, [_a], void 0, function* ({ mongodbUrl, jwtSecret, corsConfig }) {
63
+ const corsOptions = corsConfig !== null && corsConfig !== void 0 ? corsConfig : {
64
+ origin: '*',
65
+ methods: ['POST', 'GET']
66
+ };
61
67
  return [
62
68
  {
63
69
  pluginName: 'cors',
64
70
  plugin: cors_1.default,
65
- options: {
66
- origin: '*',
67
- methods: ['POST', 'GET', 'DELETE']
68
- }
71
+ options: corsOptions
69
72
  },
70
73
  {
71
74
  pluginName: 'fastifyMongodb',
@@ -31,13 +31,20 @@ const evaluateExpression = (params, expression, user) => __awaiter(void 0, void
31
31
  });
32
32
  exports.evaluateExpression = evaluateExpression;
33
33
  const evaluateComplexExpression = (condition, params, user) => __awaiter(void 0, void 0, void 0, function* () {
34
+ var _a;
34
35
  const [key, config] = condition;
35
- const { name } = config['%function'];
36
+ const functionConfig = config['%function'];
37
+ const { name, arguments: fnArguments } = functionConfig;
36
38
  const functionsList = state_1.StateManager.select('functions');
37
39
  const app = state_1.StateManager.select('app');
38
40
  const currentFunction = functionsList[name];
41
+ const expansionContext = Object.assign(Object.assign(Object.assign({}, params.expansions), params.cursor), { '%%root': params.cursor, '%%user': user, '%%true': true, '%%false': false });
42
+ const expandedArguments = fnArguments && fnArguments.length
43
+ ? ((_a = (0, rules_1.expandQuery)({ args: fnArguments }, expansionContext)
44
+ .args) !== null && _a !== void 0 ? _a : [])
45
+ : [params.cursor];
39
46
  const response = yield (0, context_1.GenerateContext)({
40
- args: [params.cursor],
47
+ args: expandedArguments,
41
48
  app,
42
49
  rules: state_1.StateManager.select("rules"),
43
50
  user,
@@ -45,5 +52,6 @@ const evaluateComplexExpression = (condition, params, user) => __awaiter(void 0,
45
52
  functionsList,
46
53
  services: services_1.services
47
54
  });
48
- return key === '%%true' ? response : !response;
55
+ const isTruthy = Boolean(response);
56
+ return key === '%%true' ? isTruthy : !isTruthy;
49
57
  });
@@ -1 +1 @@
1
- {"version":3,"file":"commonValidators.d.ts","sourceRoot":"","sources":["../../../../src/utils/roles/machines/commonValidators.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,0BAA0B,EAAE,MAAM,cAAc,CAAA;AACzD,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAA;AAK5C,eAAO,MAAM,yBAAyB,GACpC,wBAAwB,cAAc,EACtC,aAAa,MAAM,0BAA0B,qBAS9C,CAAA;AAED,eAAO,MAAM,6BAA6B,GACxC,wBAAwB,cAAc,EACtC,aAAa,cAAc,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,iCAK9C,CAAA;AAED,eAAO,MAAM,yBAAyB,GAAI,UAAU,cAAc,YAEjE,CAAA"}
1
+ {"version":3,"file":"commonValidators.d.ts","sourceRoot":"","sources":["../../../../src/utils/roles/machines/commonValidators.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,0BAA0B,EAAE,MAAM,cAAc,CAAA;AACzD,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAA;AAK5C,eAAO,MAAM,yBAAyB,GACpC,wBAAwB,cAAc,EACtC,aAAa,MAAM,0BAA0B,qBAS9C,CAAA;AAED,eAAO,MAAM,6BAA6B,GACxC,wBAAwB,cAAc,EACtC,aAAa,cAAc,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,iCAQ9C,CAAA;AAED,eAAO,MAAM,yBAAyB,GAAI,UAAU,cAAc,YAIjE,CAAA"}
@@ -12,7 +12,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
12
12
  exports.checkFieldsPropertyExists = exports.evaluateTopLevelPermissionsFn = exports.evaluateDocumentFiltersFn = void 0;
13
13
  const someAsync_1 = require("../../helpers/someAsync");
14
14
  const helpers_1 = require("../helpers");
15
- const readOnlyPermissions = ['read'];
15
+ const readOnlyPermissions = ['read', 'search'];
16
16
  const readWritePermissions = ['write', 'delete', 'insert', ...readOnlyPermissions];
17
17
  const evaluateDocumentFiltersFn = (_a, currentType_1) => __awaiter(void 0, [_a, currentType_1], void 0, function* ({ params, role, user }, currentType) {
18
18
  var _b;
@@ -21,13 +21,17 @@ const evaluateDocumentFiltersFn = (_a, currentType_1) => __awaiter(void 0, [_a,
21
21
  });
22
22
  exports.evaluateDocumentFiltersFn = evaluateDocumentFiltersFn;
23
23
  const evaluateTopLevelPermissionsFn = (_a, currentType_1) => __awaiter(void 0, [_a, currentType_1], void 0, function* ({ params, role, user }, currentType) {
24
- return role[currentType]
25
- ? yield (0, helpers_1.evaluateExpression)(params, role[currentType], user)
26
- : undefined;
24
+ const permission = role === null || role === void 0 ? void 0 : role[currentType];
25
+ if (typeof permission === 'undefined') {
26
+ return undefined;
27
+ }
28
+ return yield (0, helpers_1.evaluateExpression)(params, permission, user);
27
29
  });
28
30
  exports.evaluateTopLevelPermissionsFn = evaluateTopLevelPermissionsFn;
29
31
  const checkFieldsPropertyExists = ({ role }) => {
30
- var _a;
31
- return !!Object.keys((_a = role.fields) !== null && _a !== void 0 ? _a : {}).length;
32
+ var _a, _b;
33
+ const hasFields = !!Object.keys((_a = role === null || role === void 0 ? void 0 : role.fields) !== null && _a !== void 0 ? _a : {}).length;
34
+ const hasAdditional = !!Object.keys((_b = role === null || role === void 0 ? void 0 : role.additional_fields) !== null && _b !== void 0 ? _b : {}).length;
35
+ return hasFields || hasAdditional;
32
36
  };
33
37
  exports.checkFieldsPropertyExists = checkFieldsPropertyExists;
@@ -0,0 +1,4 @@
1
+ import { MachineContext } from '../../interface';
2
+ export declare const evaluateDocumentFiltersReadFn: (context: MachineContext) => Promise<boolean>;
3
+ export declare const evaluateDocumentFiltersWriteFn: (context: MachineContext) => Promise<boolean>;
4
+ //# sourceMappingURL=validators.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validators.d.ts","sourceRoot":"","sources":["../../../../../../src/utils/roles/machines/read/B/validators.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAA;AAGhD,eAAO,MAAM,6BAA6B,GAAI,SAAS,cAAc,qBACzB,CAAA;AAE5C,eAAO,MAAM,8BAA8B,GAAI,SAAS,cAAc,qBACzB,CAAA"}
@@ -0,0 +1,8 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.evaluateDocumentFiltersWriteFn = exports.evaluateDocumentFiltersReadFn = void 0;
4
+ const commonValidators_1 = require("../../commonValidators");
5
+ const evaluateDocumentFiltersReadFn = (context) => (0, commonValidators_1.evaluateDocumentFiltersFn)(context, 'read');
6
+ exports.evaluateDocumentFiltersReadFn = evaluateDocumentFiltersReadFn;
7
+ const evaluateDocumentFiltersWriteFn = (context) => (0, commonValidators_1.evaluateDocumentFiltersFn)(context, 'write');
8
+ exports.evaluateDocumentFiltersWriteFn = evaluateDocumentFiltersWriteFn;
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../../src/utils/roles/machines/read/C/index.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAA;AAGxC,eAAO,MAAM,aAAa,EAAE,MAsC3B,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../../src/utils/roles/machines/read/C/index.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAA;AAGxC,eAAO,MAAM,aAAa,EAAE,MAyC3B,CAAA"}
@@ -10,7 +10,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
10
10
  };
11
11
  Object.defineProperty(exports, "__esModule", { value: true });
12
12
  exports.STEP_C_STATES = void 0;
13
- const commonValidators_1 = require("../../commonValidators");
13
+ const validators_1 = require("./validators");
14
14
  const utils_1 = require("../../utils");
15
15
  exports.STEP_C_STATES = {
16
16
  evaluateTopLevelRead: (_a) => __awaiter(void 0, [_a], void 0, function* ({ context, next, endValidation }) {
@@ -20,10 +20,13 @@ exports.STEP_C_STATES = {
20
20
  step: 1,
21
21
  stepName: 'evaluateTopLevelRead'
22
22
  });
23
- const check = yield (0, commonValidators_1.evaluateTopLevelPermissionsFn)(context, 'read');
24
- return check
25
- ? endValidation({ success: true })
26
- : next('evaluateTopLevelWrite', { check });
23
+ const check = yield (0, validators_1.evaluateTopLevelReadFn)(context);
24
+ if (check) {
25
+ return (0, validators_1.checkFieldsPropertyExists)(context)
26
+ ? next('checkFieldsProperty')
27
+ : endValidation({ success: true });
28
+ }
29
+ return next('evaluateTopLevelWrite', { check });
27
30
  }),
28
31
  evaluateTopLevelWrite: (_a) => __awaiter(void 0, [_a], void 0, function* ({ context, next, endValidation }) {
29
32
  var _b;
@@ -33,7 +36,7 @@ exports.STEP_C_STATES = {
33
36
  step: 2,
34
37
  stepName: 'evaluateTopLevelWrite'
35
38
  });
36
- const check = yield (0, commonValidators_1.evaluateTopLevelPermissionsFn)(context, 'write');
39
+ const check = yield (0, validators_1.evaluateTopLevelWriteFn)(context);
37
40
  if (check)
38
41
  return endValidation({ success: true });
39
42
  return ((_b = context === null || context === void 0 ? void 0 : context.prevParams) === null || _b === void 0 ? void 0 : _b.check) === false
@@ -47,7 +50,7 @@ exports.STEP_C_STATES = {
47
50
  step: 3,
48
51
  stepName: 'checkFieldsProperty'
49
52
  });
50
- const check = (0, commonValidators_1.checkFieldsPropertyExists)(context);
53
+ const check = (0, validators_1.checkFieldsPropertyExists)(context);
51
54
  return goToNextValidationStage(check ? 'checkIsValidFieldName' : 'checkAdditionalFields');
52
55
  })
53
56
  };
@@ -0,0 +1,5 @@
1
+ import { MachineContext } from '../../interface';
2
+ export declare const evaluateTopLevelReadFn: (context: MachineContext) => Promise<boolean | undefined>;
3
+ export declare const evaluateTopLevelWriteFn: (context: MachineContext) => Promise<boolean | undefined>;
4
+ export { checkFieldsPropertyExists } from '../../commonValidators';
5
+ //# sourceMappingURL=validators.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validators.d.ts","sourceRoot":"","sources":["../../../../../../src/utils/roles/machines/read/C/validators.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAA;AAMhD,eAAO,MAAM,sBAAsB,GAAU,SAAS,cAAc,iCAKnE,CAAA;AAED,eAAO,MAAM,uBAAuB,GAAU,SAAS,cAAc,iCAKpE,CAAA;AAED,OAAO,EAAE,yBAAyB,EAAE,MAAM,wBAAwB,CAAA"}
@@ -0,0 +1,29 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.checkFieldsPropertyExists = exports.evaluateTopLevelWriteFn = exports.evaluateTopLevelReadFn = void 0;
13
+ const commonValidators_1 = require("../../commonValidators");
14
+ const evaluateTopLevelReadFn = (context) => __awaiter(void 0, void 0, void 0, function* () {
15
+ if (context.params.type !== 'read') {
16
+ return false;
17
+ }
18
+ return (0, commonValidators_1.evaluateTopLevelPermissionsFn)(context, 'read');
19
+ });
20
+ exports.evaluateTopLevelReadFn = evaluateTopLevelReadFn;
21
+ const evaluateTopLevelWriteFn = (context) => __awaiter(void 0, void 0, void 0, function* () {
22
+ if (!['read', 'write'].includes(context.params.type)) {
23
+ return undefined;
24
+ }
25
+ return (0, commonValidators_1.evaluateTopLevelPermissionsFn)(context, 'write');
26
+ });
27
+ exports.evaluateTopLevelWriteFn = evaluateTopLevelWriteFn;
28
+ var commonValidators_2 = require("../../commonValidators");
29
+ Object.defineProperty(exports, "checkFieldsPropertyExists", { enumerable: true, get: function () { return commonValidators_2.checkFieldsPropertyExists; } });
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../../src/utils/roles/machines/read/D/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAA;AAIxC,eAAO,MAAM,aAAa,EAAE,MAqB3B,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../../src/utils/roles/machines/read/D/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAkB,MAAM,EAAE,MAAM,iBAAiB,CAAA;AAqBxD,eAAO,MAAM,aAAa,EAAE,MAa3B,CAAA"}
@@ -12,6 +12,16 @@ Object.defineProperty(exports, "__esModule", { value: true });
12
12
  exports.STEP_D_STATES = void 0;
13
13
  const utils_1 = require("../../utils");
14
14
  const validators_1 = require("./validators");
15
+ const runCheckIsValidFieldName = (_a) => __awaiter(void 0, [_a], void 0, function* ({ context, endValidation }) {
16
+ (0, utils_1.logMachineInfo)({
17
+ enabled: context.enableLog,
18
+ machine: 'D',
19
+ step: 2,
20
+ stepName: 'checkIsValidFieldName'
21
+ });
22
+ const document = (0, validators_1.checkIsValidFieldNameFn)(context);
23
+ return endValidation({ success: !!Object.keys(document).length, document });
24
+ });
15
25
  exports.STEP_D_STATES = {
16
26
  checkAdditionalFields: (_a) => __awaiter(void 0, [_a], void 0, function* ({ context, next, endValidation }) {
17
27
  (0, utils_1.logMachineInfo)({
@@ -21,16 +31,8 @@ exports.STEP_D_STATES = {
21
31
  stepName: 'checkAdditionalFields'
22
32
  });
23
33
  const check = (0, validators_1.checkAdditionalFieldsFn)(context);
24
- return check ? next('checkIsValidFieldName') : endValidation({ success: false });
34
+ return check ? next('evaluateRead') : endValidation({ success: false });
25
35
  }),
26
- checkIsValidFieldName: (_a) => __awaiter(void 0, [_a], void 0, function* ({ context, endValidation }) {
27
- (0, utils_1.logMachineInfo)({
28
- enabled: context.enableLog,
29
- machine: 'D',
30
- step: 2,
31
- stepName: 'checkIsValidFieldName'
32
- });
33
- const document = (0, validators_1.checkIsValidFieldNameFn)(context);
34
- return endValidation({ success: !!Object.keys(document).length, document });
35
- })
36
+ evaluateRead: runCheckIsValidFieldName,
37
+ checkIsValidFieldName: runCheckIsValidFieldName
36
38
  };
@@ -1,2 +1,2 @@
1
- export declare function expandQuery(template: Record<string, unknown>, objs: Record<string, unknown>): any;
1
+ export declare function expandQuery(template: Record<string, unknown>, objs: Record<string, unknown>): Record<string, unknown>;
2
2
  //# sourceMappingURL=rules.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"rules.d.ts","sourceRoot":"","sources":["../../src/utils/rules.ts"],"names":[],"mappings":"AAOA,wBAAgB,WAAW,CACzB,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACjC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,OAqB9B"}
1
+ {"version":3,"file":"rules.d.ts","sourceRoot":"","sources":["../../src/utils/rules.ts"],"names":[],"mappings":"AAkCA,wBAAgB,WAAW,CACzB,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACjC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAES,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAC9D"}
@@ -5,23 +5,32 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.expandQuery = expandQuery;
7
7
  const get_1 = __importDefault(require("lodash/get"));
8
- const removeExtraColons = (val) => {
9
- return val === null || val === void 0 ? void 0 : val.toString().replace(/:+/g, ":");
8
+ const resolvePlaceholder = (value, objs) => {
9
+ if (!value.startsWith('%%'))
10
+ return value;
11
+ const path = value.slice(2);
12
+ const [rootKey, ...rest] = path.split('.');
13
+ const rootToken = `%%${rootKey}`;
14
+ const rootValue = objs[rootToken];
15
+ if (!rest.length) {
16
+ return rootValue === undefined ? value : rootValue;
17
+ }
18
+ const resolved = (0, get_1.default)(rootValue, rest.join('.'));
19
+ return resolved === undefined ? value : resolved;
10
20
  };
11
- // Funzione che espande dinamicamente i placeholder con supporto per percorsi annidati
21
+ const expandValue = (input, objs) => {
22
+ if (Array.isArray(input)) {
23
+ return input.map((item) => expandValue(item, objs));
24
+ }
25
+ if (input && typeof input === 'object') {
26
+ return Object.fromEntries(Object.entries(input).map(([key, val]) => [key, expandValue(val, objs)]));
27
+ }
28
+ if (typeof input === 'string') {
29
+ return resolvePlaceholder(input, objs);
30
+ }
31
+ return input;
32
+ };
33
+ // Espande dinamicamente i placeholder con supporto per array e percorsi annidati
12
34
  function expandQuery(template, objs) {
13
- let expandedQuery = JSON.stringify(template); // Converti l'oggetto in una stringa per sostituire i placeholder
14
- const regex = /:\s*"%%([a-zA-Z0-9_.]+)"/g;
15
- Object.keys(objs).forEach(() => {
16
- // Espandi tutti i placeholder %%values.<nested.property>
17
- const callback = (match, path) => {
18
- const value = (0, get_1.default)(objs, `%%${path}`); // Recupera il valore annidato da values
19
- const finalValue = typeof value === 'string' ? `"${value}"` : value && JSON.stringify(value);
20
- // TODO tolto i primi : creava questo tipo di oggetto {"userId"::"%%user.id"}
21
- const val = `:${value !== undefined ? finalValue : match}`; // Sostituisci se esiste, altrimenti lascia il placeholder
22
- return removeExtraColons(val);
23
- };
24
- expandedQuery = expandedQuery.replace(regex, callback);
25
- });
26
- return JSON.parse(expandedQuery); // Converti la stringa JSON di nuovo in un oggetto
35
+ return expandValue(template, objs);
27
36
  }
package/jest.config.ts CHANGED
@@ -4,21 +4,11 @@ module.exports = {
4
4
  '^.+\\.[tj]s$': [
5
5
  'ts-jest',
6
6
  {
7
- tsconfig: './tsconfig.json'
7
+ tsconfig: '<rootDir>/tsconfig.json'
8
8
  }
9
9
  ]
10
10
  },
11
- collectCoverage: false,
12
- collectCoverageFrom: ['./**/*.ts'],
13
- coverageDirectory: 'coverage',
14
- coverageThreshold: {
15
- global: {
16
- branches: 50,
17
- functions: 90,
18
- lines: 90,
19
- statements: 90
20
- }
21
- },
11
+ setupFilesAfterEnv: ['<rootDir>/jest.setup.ts'],
22
12
  testEnvironment: 'node',
23
13
  testMatch: ['./**/*.test.ts']
24
14
  }
package/jest.setup.ts ADDED
@@ -0,0 +1,28 @@
1
+ import { Blob as NodeBlob } from 'buffer'
2
+ import path from 'node:path'
3
+
4
+ if (!process.env.FLOWERBASE_APP_PATH) {
5
+ process.env.FLOWERBASE_APP_PATH = path.resolve(__dirname, '../../tests/e2e/app')
6
+ }
7
+
8
+ const BaseBlob = typeof globalThis.Blob !== 'undefined' ? globalThis.Blob : NodeBlob
9
+
10
+ type PolyfillFilePropertyBag = FilePropertyBag & {
11
+ name?: string
12
+ }
13
+
14
+ class FilePolyfill extends BaseBlob {
15
+ lastModified: number
16
+ name: string
17
+
18
+ constructor(bits?: Iterable<BlobPart>, options?: FilePropertyBag) {
19
+ super(bits, options as FilePropertyBag)
20
+ const fileOptions = options as PolyfillFilePropertyBag
21
+ this.name = fileOptions?.name ?? ''
22
+ this.lastModified = fileOptions?.lastModified ?? Date.now()
23
+ }
24
+ }
25
+
26
+ if (typeof globalThis.File === 'undefined') {
27
+ globalThis.File = FilePolyfill as unknown as typeof File
28
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@flowerforce/flowerbase",
3
- "version": "1.2.0",
3
+ "version": "1.2.1-beta.10",
4
4
  "description": "",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -25,7 +25,6 @@
25
25
  "@fastify/mongodb": "^9.0.1",
26
26
  "@fastify/swagger": "^9.5.1",
27
27
  "@fastify/swagger-ui": "^5.2.3",
28
- "@sendgrid/mail": "^8.1.4",
29
28
  "aws-sdk": "^2.1692.0",
30
29
  "bson": "^6.8.0",
31
30
  "dotenv": "^16.4.7",
@@ -1,8 +1,9 @@
1
1
  import { ObjectId } from 'bson'
2
2
  import { FastifyInstance } from 'fastify'
3
- import { AUTH_CONFIG, DB_NAME } from '../constants'
3
+ import { AUTH_CONFIG, DB_NAME, DEFAULT_CONFIG } from '../constants'
4
4
  import { SessionCreatedDto } from './dtos'
5
5
  import { AUTH_ENDPOINTS, AUTH_ERRORS } from './utils'
6
+ import { hashToken } from '../utils/crypto'
6
7
 
7
8
  const HANDLER_TYPE = 'preHandler'
8
9
 
@@ -12,9 +13,19 @@ const HANDLER_TYPE = 'preHandler'
12
13
  * @param {FastifyInstance} app - The Fastify instance.
13
14
  */
14
15
  export async function authController(app: FastifyInstance) {
15
- const { authCollection, userCollection } = AUTH_CONFIG
16
+ const { authCollection, userCollection, refreshTokensCollection } = AUTH_CONFIG
16
17
 
17
18
  const db = app.mongo.client.db(DB_NAME)
19
+ const refreshTokenTtlMs = DEFAULT_CONFIG.REFRESH_TOKEN_TTL_DAYS * 24 * 60 * 60 * 1000
20
+
21
+ try {
22
+ await db.collection(refreshTokensCollection).createIndex(
23
+ { expiresAt: 1 },
24
+ { expireAfterSeconds: 0 }
25
+ )
26
+ } catch (error) {
27
+ console.error('Failed to ensure refresh token TTL index', error)
28
+ }
18
29
 
19
30
  app.addHook(HANDLER_TYPE, app.jwtAuthentication)
20
31
 
@@ -26,6 +37,9 @@ export async function authController(app: FastifyInstance) {
26
37
  * @returns {Promise<Object>} A promise resolving with the user's profile data.
27
38
  */
28
39
  app.get(AUTH_ENDPOINTS.PROFILE, async function (req) {
40
+ if (req.user.typ !== 'access') {
41
+ throw new Error('Access token required')
42
+ }
29
43
  const user = await db
30
44
  .collection<Record<string, unknown>>(authCollection)
31
45
  .findOne({ _id: ObjectId.createFromHexString(req.user.id) })
@@ -56,6 +70,21 @@ export async function authController(app: FastifyInstance) {
56
70
  throw new Error(AUTH_ERRORS.INVALID_TOKEN)
57
71
  }
58
72
 
73
+ const authHeader = req.headers.authorization
74
+ if (!authHeader?.startsWith('Bearer ')) {
75
+ throw new Error(AUTH_ERRORS.INVALID_TOKEN)
76
+ }
77
+ const refreshToken = authHeader.slice('Bearer '.length).trim()
78
+ const refreshTokenHash = hashToken(refreshToken)
79
+ const storedToken = await db.collection(refreshTokensCollection).findOne({
80
+ tokenHash: refreshTokenHash,
81
+ revokedAt: null,
82
+ expiresAt: { $gt: new Date() }
83
+ })
84
+ if (!storedToken) {
85
+ throw new Error(AUTH_ERRORS.INVALID_TOKEN)
86
+ }
87
+
59
88
  const auth_user = await db
60
89
  ?.collection(authCollection)
61
90
  .findOne({ _id: new this.mongo.ObjectId(req.user.sub) })
@@ -82,8 +111,45 @@ export async function authController(app: FastifyInstance) {
82
111
  */
83
112
  app.delete(
84
113
  AUTH_ENDPOINTS.SESSION,
85
- async function () {
86
- return { status: "ok" }
114
+ async function (req, res) {
115
+ const authHeader = req.headers.authorization
116
+ if (!authHeader?.startsWith('Bearer ')) {
117
+ res.status(204)
118
+ return
119
+ }
120
+ const refreshToken = authHeader.slice('Bearer '.length).trim()
121
+ const refreshTokenHash = hashToken(refreshToken)
122
+ const now = new Date()
123
+ const expiresAt = new Date(Date.now() + refreshTokenTtlMs)
124
+ const updateResult = await db.collection(refreshTokensCollection).findOneAndUpdate(
125
+ { tokenHash: refreshTokenHash },
126
+ {
127
+ $set: {
128
+ revokedAt: now,
129
+ expiresAt
130
+ }
131
+ },
132
+ { returnDocument: 'after' }
133
+ )
134
+
135
+ const fromToken = req.user?.sub
136
+ let userId = updateResult?.value?.userId
137
+ if (!userId && fromToken) {
138
+ try {
139
+ userId = new ObjectId(fromToken)
140
+ } catch {
141
+ userId = fromToken
142
+ }
143
+ }
144
+
145
+ if (userId && authCollection) {
146
+ await db.collection(authCollection).updateOne(
147
+ { _id: userId },
148
+ { $set: { lastLogoutAt: now } }
149
+ )
150
+ }
151
+
152
+ return { status: 'ok' }
87
153
  }
88
154
  )
89
155
  }