@flowerforce/flowerbase 1.2.1-beta.8 → 1.3.0

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 (91) hide show
  1. package/CHANGELOG.md +74 -0
  2. package/README.md +9 -3
  3. package/dist/auth/controller.d.ts.map +1 -1
  4. package/dist/auth/controller.js +2 -2
  5. package/dist/auth/plugins/jwt.js +3 -3
  6. package/dist/auth/providers/anon-user/controller.d.ts +8 -0
  7. package/dist/auth/providers/anon-user/controller.d.ts.map +1 -0
  8. package/dist/auth/providers/anon-user/controller.js +90 -0
  9. package/dist/auth/providers/anon-user/dtos.d.ts +10 -0
  10. package/dist/auth/providers/anon-user/dtos.d.ts.map +1 -0
  11. package/dist/auth/providers/anon-user/dtos.js +2 -0
  12. package/dist/auth/providers/custom-function/controller.d.ts.map +1 -1
  13. package/dist/auth/providers/custom-function/controller.js +32 -35
  14. package/dist/auth/providers/custom-function/dtos.d.ts +4 -1
  15. package/dist/auth/providers/custom-function/dtos.d.ts.map +1 -1
  16. package/dist/auth/providers/local-userpass/controller.d.ts.map +1 -1
  17. package/dist/auth/providers/local-userpass/controller.js +41 -33
  18. package/dist/auth/providers/local-userpass/dtos.d.ts +6 -0
  19. package/dist/auth/providers/local-userpass/dtos.d.ts.map +1 -1
  20. package/dist/auth/utils.d.ts +24 -1
  21. package/dist/auth/utils.d.ts.map +1 -1
  22. package/dist/auth/utils.js +13 -1
  23. package/dist/constants.d.ts +4 -0
  24. package/dist/constants.d.ts.map +1 -1
  25. package/dist/constants.js +7 -3
  26. package/dist/features/functions/controller.d.ts.map +1 -1
  27. package/dist/features/functions/controller.js +31 -12
  28. package/dist/features/functions/dtos.d.ts +3 -0
  29. package/dist/features/functions/dtos.d.ts.map +1 -1
  30. package/dist/features/functions/interface.d.ts +3 -0
  31. package/dist/features/functions/interface.d.ts.map +1 -1
  32. package/dist/features/functions/utils.d.ts +2 -2
  33. package/dist/features/functions/utils.d.ts.map +1 -1
  34. package/dist/features/functions/utils.js +19 -8
  35. package/dist/features/triggers/index.d.ts.map +1 -1
  36. package/dist/features/triggers/index.js +49 -7
  37. package/dist/features/triggers/interface.d.ts +1 -0
  38. package/dist/features/triggers/interface.d.ts.map +1 -1
  39. package/dist/features/triggers/utils.d.ts.map +1 -1
  40. package/dist/features/triggers/utils.js +67 -26
  41. package/dist/index.d.ts.map +1 -1
  42. package/dist/index.js +18 -12
  43. package/dist/services/mongodb-atlas/index.d.ts.map +1 -1
  44. package/dist/services/mongodb-atlas/index.js +2 -2
  45. package/dist/services/mongodb-atlas/model.d.ts +2 -2
  46. package/dist/services/mongodb-atlas/model.d.ts.map +1 -1
  47. package/dist/services/mongodb-atlas/utils.d.ts.map +1 -1
  48. package/dist/services/mongodb-atlas/utils.js +3 -1
  49. package/dist/shared/handleUserRegistration.d.ts.map +1 -1
  50. package/dist/shared/handleUserRegistration.js +66 -1
  51. package/dist/shared/models/handleUserRegistration.model.d.ts +2 -1
  52. package/dist/shared/models/handleUserRegistration.model.d.ts.map +1 -1
  53. package/dist/shared/models/handleUserRegistration.model.js +1 -0
  54. package/dist/utils/context/helpers.d.ts +5 -5
  55. package/dist/utils/context/helpers.d.ts.map +1 -1
  56. package/dist/utils/context/index.d.ts.map +1 -1
  57. package/dist/utils/context/index.js +12 -14
  58. package/dist/utils/initializer/exposeRoutes.js +1 -1
  59. package/dist/utils/initializer/registerPlugins.d.ts.map +1 -1
  60. package/dist/utils/initializer/registerPlugins.js +12 -4
  61. package/dist/utils/rules-matcher/utils.d.ts.map +1 -1
  62. package/dist/utils/rules-matcher/utils.js +3 -0
  63. package/package.json +1 -1
  64. package/src/auth/controller.ts +5 -2
  65. package/src/auth/plugins/jwt.ts +5 -5
  66. package/src/auth/providers/anon-user/controller.ts +91 -0
  67. package/src/auth/providers/anon-user/dtos.ts +10 -0
  68. package/src/auth/providers/custom-function/controller.ts +34 -39
  69. package/src/auth/providers/custom-function/dtos.ts +5 -1
  70. package/src/auth/providers/local-userpass/controller.ts +56 -43
  71. package/src/auth/providers/local-userpass/dtos.ts +7 -0
  72. package/src/auth/utils.ts +22 -1
  73. package/src/constants.ts +5 -1
  74. package/src/features/functions/controller.ts +42 -12
  75. package/src/features/functions/dtos.ts +3 -0
  76. package/src/features/functions/interface.ts +3 -0
  77. package/src/features/functions/utils.ts +26 -9
  78. package/src/features/triggers/index.ts +44 -1
  79. package/src/features/triggers/interface.ts +1 -0
  80. package/src/features/triggers/utils.ts +89 -37
  81. package/src/index.ts +18 -12
  82. package/src/services/mongodb-atlas/index.ts +654 -654
  83. package/src/services/mongodb-atlas/model.ts +2 -2
  84. package/src/services/mongodb-atlas/utils.ts +3 -0
  85. package/src/shared/handleUserRegistration.ts +83 -2
  86. package/src/shared/models/handleUserRegistration.model.ts +2 -1
  87. package/src/utils/__tests__/registerPlugins.test.ts +5 -1
  88. package/src/utils/context/index.ts +32 -36
  89. package/src/utils/initializer/exposeRoutes.ts +1 -1
  90. package/src/utils/initializer/registerPlugins.ts +8 -0
  91. package/src/utils/rules-matcher/utils.ts +3 -0
package/CHANGELOG.md CHANGED
@@ -1,3 +1,77 @@
1
+ ## 1.3.0 (2026-01-14)
2
+
3
+
4
+ ### 🚀 Features
5
+
6
+ - add createdAt on collection auth_user ([87d4e81](https://github.com/flowerforce/flowerbase/commit/87d4e81))
7
+
8
+ - add log error ([fde3fb1](https://github.com/flowerforce/flowerbase/commit/fde3fb1))
9
+
10
+ - safe aggregate ([d715444](https://github.com/flowerforce/flowerbase/commit/d715444))
11
+
12
+ - fix rules and tests ([0bbc9c6](https://github.com/flowerforce/flowerbase/commit/0bbc9c6))
13
+
14
+ - remove sendgrid module ([f7b3d5f](https://github.com/flowerforce/flowerbase/commit/f7b3d5f))
15
+
16
+ - security check ([aec94cc](https://github.com/flowerforce/flowerbase/commit/aec94cc))
17
+
18
+ - add rate limit auth ([346fb12](https://github.com/flowerforce/flowerbase/commit/346fb12))
19
+
20
+ - add basic auth swagger UI ([ac6b331](https://github.com/flowerforce/flowerbase/commit/ac6b331))
21
+
22
+ - add rate limit reset password ([c9dcf48](https://github.com/flowerforce/flowerbase/commit/c9dcf48))
23
+
24
+ - check refresh token ([db8204d](https://github.com/flowerforce/flowerbase/commit/db8204d))
25
+
26
+ - add findOneAndUpdate ([9ac5b1e](https://github.com/flowerforce/flowerbase/commit/9ac5b1e))
27
+
28
+ - add confirm user with custom function ([da8990d](https://github.com/flowerforce/flowerbase/commit/da8990d))
29
+
30
+ - add catch error functions ([ef05b22](https://github.com/flowerforce/flowerbase/commit/ef05b22))
31
+
32
+ - add anon-user ([2ed0086](https://github.com/flowerforce/flowerbase/commit/2ed0086))
33
+
34
+ - add rate limit register ([74eb725](https://github.com/flowerforce/flowerbase/commit/74eb725))
35
+
36
+ - add %%root record in rule ([6a95425](https://github.com/flowerforce/flowerbase/commit/6a95425))
37
+
38
+
39
+ ### 🩹 Fixes
40
+
41
+ - cors methods ([c570d3a](https://github.com/flowerforce/flowerbase/commit/c570d3a))
42
+
43
+ - check missing currentFunction ([7be4845](https://github.com/flowerforce/flowerbase/commit/7be4845))
44
+
45
+ - reset password endpoint and auth tests ([daef161](https://github.com/flowerforce/flowerbase/commit/daef161))
46
+
47
+ - reset password ([0dcb9f6](https://github.com/flowerforce/flowerbase/commit/0dcb9f6))
48
+
49
+ - payload reset password legacy ([1219fd1](https://github.com/flowerforce/flowerbase/commit/1219fd1))
50
+
51
+ - exports and import modulo in functions ([f5d0b96](https://github.com/flowerforce/flowerbase/commit/f5d0b96))
52
+
53
+ - revoke token ([8ac3084](https://github.com/flowerforce/flowerbase/commit/8ac3084))
54
+
55
+ - payload findOneAndUpdate ([5545232](https://github.com/flowerforce/flowerbase/commit/5545232))
56
+
57
+ - trigger auth ([b376b30](https://github.com/flowerforce/flowerbase/commit/b376b30))
58
+
59
+ - user auto confirm ([2639e70](https://github.com/flowerforce/flowerbase/commit/2639e70))
60
+
61
+ - args auth event trigger ([dc78945](https://github.com/flowerforce/flowerbase/commit/dc78945))
62
+
63
+ - async aggregate ([53ea8e7](https://github.com/flowerforce/flowerbase/commit/53ea8e7))
64
+
65
+ - trigger crash ([d517f97](https://github.com/flowerforce/flowerbase/commit/d517f97))
66
+
67
+ - user id jwt ([bfae07c](https://github.com/flowerforce/flowerbase/commit/bfae07c))
68
+
69
+ - location hostname ([0e831ad](https://github.com/flowerforce/flowerbase/commit/0e831ad))
70
+
71
+ - add error 401 custom auth ([d8b2eda](https://github.com/flowerforce/flowerbase/commit/d8b2eda))
72
+
73
+ - **localUserPassController:** userWithCustomData ([3d8e257](https://github.com/flowerforce/flowerbase/commit/3d8e257))
74
+
1
75
  ## 1.2.0 (2025-10-14)
2
76
 
3
77
 
package/README.md CHANGED
@@ -229,11 +229,12 @@ However, all users will be required to reset their passwords since it is not pos
229
229
 
230
230
  ### ✅ Supported Auth Method
231
231
 
232
- The only authentication mode currently re-implemented in `@flowerforce/flowerbase` is:
232
+ The authentication modes currently re-implemented in `@flowerforce/flowerbase` are:
233
233
 
234
234
  - Local Email/Password (local-userpass)
235
+ - Anonymous (anon-user)
235
236
 
236
- > Other methods (OAuth, API key, anonymous, etc.) are not supported yet.
237
+ > Other methods (OAuth, API key, etc.) are not supported yet.
237
238
 
238
239
  #### Example user:
239
240
  ```js
@@ -270,13 +271,18 @@ Example
270
271
  "name": "local-userpass",
271
272
  "type": "local-userpass",
272
273
  "disabled": false,
273
- "auth_collection": "my-users-collection" //custom collection name
274
+ "auth_collection": "my-users-collection", //custom collection name
274
275
  "config": {
275
276
  "autoConfirm": true,
276
277
  "resetPasswordSubject": "reset",
277
278
  "resetPasswordUrl": "https://my.app.url/password-reset",
278
279
  "runConfirmationFunction": false
279
280
  }
281
+ },
282
+ "anon-user": {
283
+ "name": "anon-user",
284
+ "type": "anon-user",
285
+ "disabled": false
280
286
  }
281
287
  }
282
288
 
@@ -1 +1 @@
1
- {"version":3,"file":"controller.d.ts","sourceRoot":"","sources":["../../src/auth/controller.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,eAAe,EAAE,MAAM,SAAS,CAAA;AAQzC;;;;GAIG;AACH,wBAAsB,cAAc,CAAC,GAAG,EAAE,eAAe,iBA4IxD"}
1
+ {"version":3,"file":"controller.d.ts","sourceRoot":"","sources":["../../src/auth/controller.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,eAAe,EAAE,MAAM,SAAS,CAAA;AAQzC;;;;GAIG;AACH,wBAAsB,cAAc,CAAC,GAAG,EAAE,eAAe,iBA+IxD"}
@@ -12,8 +12,8 @@ Object.defineProperty(exports, "__esModule", { value: true });
12
12
  exports.authController = authController;
13
13
  const bson_1 = require("bson");
14
14
  const constants_1 = require("../constants");
15
- const utils_1 = require("./utils");
16
15
  const crypto_1 = require("../utils/crypto");
16
+ const utils_1 = require("./utils");
17
17
  const HANDLER_TYPE = 'preHandler';
18
18
  /**
19
19
  * Controller for handling user authentication, profile retrieval, and session management.
@@ -95,7 +95,7 @@ function authController(app) {
95
95
  : {};
96
96
  res.status(201);
97
97
  return {
98
- access_token: this.createAccessToken(Object.assign(Object.assign({}, auth_user), { user_data: user }))
98
+ access_token: this.createAccessToken(Object.assign(Object.assign({}, auth_user), { user_data: Object.assign(Object.assign({}, user), { id: req.user.sub }) }))
99
99
  };
100
100
  });
101
101
  });
@@ -88,8 +88,8 @@ exports.default = (0, fastify_plugin_1.default)(function (fastify, opts) {
88
88
  });
89
89
  fastify.decorate('createAccessToken', function (user) {
90
90
  const id = user._id.toString();
91
- const userDataId = user.user_data._id.toString();
92
- const user_data = Object.assign({ _id: userDataId, id: userDataId, email: user.email }, user.user_data);
91
+ // const userDataId = user.user_data._id.toString()
92
+ const user_data = Object.assign(Object.assign({}, user.user_data), { _id: id, id: id, email: user.email });
93
93
  return this.jwt.sign({
94
94
  typ: 'access',
95
95
  id,
@@ -99,7 +99,7 @@ exports.default = (0, fastify_plugin_1.default)(function (fastify, opts) {
99
99
  }, {
100
100
  iss: BAAS_ID,
101
101
  jti: BAAS_ID,
102
- sub: user._id.toJSON(),
102
+ sub: id,
103
103
  expiresIn: '300m'
104
104
  });
105
105
  });
@@ -0,0 +1,8 @@
1
+ import { FastifyInstance } from 'fastify';
2
+ /**
3
+ * Controller for handling anonymous user login.
4
+ * @testable
5
+ * @param {FastifyInstance} app - The Fastify instance.
6
+ */
7
+ export declare function anonUserController(app: FastifyInstance): Promise<void>;
8
+ //# sourceMappingURL=controller.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"controller.d.ts","sourceRoot":"","sources":["../../../../src/auth/providers/anon-user/controller.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,SAAS,CAAA;AAOzC;;;;GAIG;AACH,wBAAsB,kBAAkB,CAAC,GAAG,EAAE,eAAe,iBA8E5D"}
@@ -0,0 +1,90 @@
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.anonUserController = anonUserController;
13
+ const constants_1 = require("../../../constants");
14
+ const crypto_1 = require("../../../utils/crypto");
15
+ const handleUserRegistration_model_1 = require("../../../shared/models/handleUserRegistration.model");
16
+ const utils_1 = require("../../utils");
17
+ /**
18
+ * Controller for handling anonymous user login.
19
+ * @testable
20
+ * @param {FastifyInstance} app - The Fastify instance.
21
+ */
22
+ function anonUserController(app) {
23
+ return __awaiter(this, void 0, void 0, function* () {
24
+ const db = app.mongo.client.db(constants_1.DB_NAME);
25
+ const { authCollection, refreshTokensCollection, providers } = constants_1.AUTH_CONFIG;
26
+ const refreshTokenTtlMs = constants_1.DEFAULT_CONFIG.REFRESH_TOKEN_TTL_DAYS * 24 * 60 * 60 * 1000;
27
+ const anonUserTtlSeconds = constants_1.DEFAULT_CONFIG.ANON_USER_TTL_SECONDS;
28
+ try {
29
+ yield db.collection(authCollection).createIndex({ createdAt: 1 }, {
30
+ expireAfterSeconds: anonUserTtlSeconds,
31
+ partialFilterExpression: { 'identities.provider_type': handleUserRegistration_model_1.PROVIDER.ANON_USER }
32
+ });
33
+ }
34
+ catch (error) {
35
+ console.error('Failed to ensure anonymous user TTL index', error);
36
+ }
37
+ app.post(utils_1.AUTH_ENDPOINTS.LOGIN, function () {
38
+ return __awaiter(this, void 0, void 0, function* () {
39
+ const anonProvider = providers === null || providers === void 0 ? void 0 : providers['anon-user'];
40
+ if (anonProvider === null || anonProvider === void 0 ? void 0 : anonProvider.disabled) {
41
+ throw new Error('Anonymous authentication disabled');
42
+ }
43
+ const now = new Date();
44
+ const insertResult = yield db.collection(authCollection).insertOne({
45
+ status: 'confirmed',
46
+ createdAt: now,
47
+ custom_data: {},
48
+ identities: [
49
+ {
50
+ provider_type: handleUserRegistration_model_1.PROVIDER.ANON_USER,
51
+ provider_data: {}
52
+ }
53
+ ]
54
+ });
55
+ const userId = insertResult.insertedId;
56
+ yield db.collection(authCollection).updateOne({ _id: userId }, {
57
+ $set: {
58
+ identities: [
59
+ {
60
+ id: userId.toString(),
61
+ provider_id: userId.toString(),
62
+ provider_type: handleUserRegistration_model_1.PROVIDER.ANON_USER,
63
+ provider_data: {}
64
+ }
65
+ ]
66
+ }
67
+ });
68
+ const currentUserData = {
69
+ _id: userId,
70
+ user_data: {}
71
+ };
72
+ const refreshToken = this.createRefreshToken(currentUserData);
73
+ const refreshTokenHash = (0, crypto_1.hashToken)(refreshToken);
74
+ yield db.collection(refreshTokensCollection).insertOne({
75
+ userId,
76
+ tokenHash: refreshTokenHash,
77
+ createdAt: now,
78
+ expiresAt: new Date(Date.now() + refreshTokenTtlMs),
79
+ revokedAt: null
80
+ });
81
+ return {
82
+ access_token: this.createAccessToken(currentUserData),
83
+ refresh_token: refreshToken,
84
+ device_id: '',
85
+ user_id: userId.toString()
86
+ };
87
+ });
88
+ });
89
+ });
90
+ }
@@ -0,0 +1,10 @@
1
+ export type LoginSuccessDto = {
2
+ access_token: string;
3
+ device_id: string;
4
+ refresh_token: string;
5
+ user_id: string;
6
+ };
7
+ export interface LoginDto {
8
+ Reply: LoginSuccessDto;
9
+ }
10
+ //# sourceMappingURL=dtos.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dtos.d.ts","sourceRoot":"","sources":["../../../../src/auth/providers/anon-user/dtos.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,eAAe,GAAG;IAC5B,YAAY,EAAE,MAAM,CAAA;IACpB,SAAS,EAAE,MAAM,CAAA;IACjB,aAAa,EAAE,MAAM,CAAA;IACrB,OAAO,EAAE,MAAM,CAAA;CAChB,CAAA;AAED,MAAM,WAAW,QAAQ;IACvB,KAAK,EAAE,eAAe,CAAA;CACvB"}
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -1 +1 @@
1
- {"version":3,"file":"controller.d.ts","sourceRoot":"","sources":["../../../../src/auth/providers/custom-function/controller.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,SAAS,CAAA;AAgBzC;;;;GAIG;AACH,wBAAsB,wBAAwB,CAAC,GAAG,EAAE,eAAe,iBA8FlE"}
1
+ {"version":3,"file":"controller.d.ts","sourceRoot":"","sources":["../../../../src/auth/providers/custom-function/controller.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,SAAS,CAAA;AASzC;;;;GAIG;AACH,wBAAsB,wBAAwB,CAAC,GAAG,EAAE,eAAe,iBAgGlE"}
@@ -8,14 +8,9 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
8
8
  step((generator = generator.apply(thisArg, _arguments || [])).next());
9
9
  });
10
10
  };
11
- var __importDefault = (this && this.__importDefault) || function (mod) {
12
- return (mod && mod.__esModule) ? mod : { "default": mod };
13
- };
14
11
  Object.defineProperty(exports, "__esModule", { value: true });
15
12
  exports.customFunctionController = customFunctionController;
16
13
  const constants_1 = require("../../../constants");
17
- const handleUserRegistration_1 = __importDefault(require("../../../shared/handleUserRegistration"));
18
- const handleUserRegistration_model_1 = require("../../../shared/models/handleUserRegistration.model");
19
14
  const state_1 = require("../../../state");
20
15
  const context_1 = require("../../../utils/context");
21
16
  const crypto_1 = require("../../../utils/crypto");
@@ -31,7 +26,7 @@ function customFunctionController(app) {
31
26
  const functionsList = state_1.StateManager.select('functions');
32
27
  const services = state_1.StateManager.select('services');
33
28
  const db = app.mongo.client.db(constants_1.DB_NAME);
34
- const { refreshTokensCollection } = constants_1.AUTH_CONFIG;
29
+ const { authCollection, refreshTokensCollection } = constants_1.AUTH_CONFIG;
35
30
  const refreshTokenTtlMs = constants_1.DEFAULT_CONFIG.REFRESH_TOKEN_TTL_DAYS * 24 * 60 * 60 * 1000;
36
31
  /**
37
32
  * Endpoint for user login.
@@ -42,7 +37,7 @@ function customFunctionController(app) {
42
37
  */
43
38
  app.post(utils_1.AUTH_ENDPOINTS.LOGIN, {
44
39
  schema: schema_1.LOGIN_SCHEMA
45
- }, function (req) {
40
+ }, function (req, reply) {
46
41
  return __awaiter(this, void 0, void 0, function* () {
47
42
  const { providers } = constants_1.AUTH_CONFIG;
48
43
  const authFunctionName = providers["custom-function"].authFunctionName;
@@ -50,7 +45,7 @@ function customFunctionController(app) {
50
45
  throw new Error("Missing Auth Function");
51
46
  }
52
47
  const { ips, host, hostname, url, method, ip, id } = req;
53
- const res = yield (0, context_1.GenerateContext)({
48
+ const authResult = yield (0, context_1.GenerateContext)({
54
49
  args: [
55
50
  req.body
56
51
  ],
@@ -70,34 +65,36 @@ function customFunctionController(app) {
70
65
  id
71
66
  }
72
67
  });
73
- if (res.id) {
74
- const user = yield (0, handleUserRegistration_1.default)(app, { run_as_system: true, skipUserCheck: true, provider: handleUserRegistration_model_1.PROVIDER.CUSTOM_FUNCTION })({ email: res.id, password: (0, utils_1.generatePassword)() });
75
- if (!(user === null || user === void 0 ? void 0 : user.insertedId)) {
76
- throw new Error('Failed to register custom user');
77
- }
78
- const currentUserData = {
79
- _id: user.insertedId,
80
- user_data: {
81
- _id: user.insertedId
82
- }
83
- };
84
- const refreshToken = this.createRefreshToken(currentUserData);
85
- const refreshTokenHash = (0, crypto_1.hashToken)(refreshToken);
86
- yield db.collection(refreshTokensCollection).insertOne({
87
- userId: user.insertedId,
88
- tokenHash: refreshTokenHash,
89
- createdAt: new Date(),
90
- expiresAt: new Date(Date.now() + refreshTokenTtlMs),
91
- revokedAt: null
92
- });
93
- return {
94
- access_token: this.createAccessToken(currentUserData),
95
- refresh_token: refreshToken,
96
- device_id: '',
97
- user_id: user.insertedId.toString()
98
- };
68
+ if (!authResult.id) {
69
+ reply.code(401).send({ message: 'Unauthorized' });
70
+ return;
71
+ }
72
+ const authUser = yield db.collection(authCollection).findOne({ email: authResult.id });
73
+ if (!authUser) {
74
+ reply.code(401).send({ message: 'Unauthorized' });
75
+ return;
99
76
  }
100
- throw new Error("Authentication Failed");
77
+ const currentUserData = {
78
+ _id: authUser._id,
79
+ user_data: {
80
+ _id: authUser._id
81
+ }
82
+ };
83
+ const refreshToken = this.createRefreshToken(currentUserData);
84
+ const refreshTokenHash = (0, crypto_1.hashToken)(refreshToken);
85
+ yield db.collection(refreshTokensCollection).insertOne({
86
+ userId: authUser._id,
87
+ tokenHash: refreshTokenHash,
88
+ createdAt: new Date(),
89
+ expiresAt: new Date(Date.now() + refreshTokenTtlMs),
90
+ revokedAt: null
91
+ });
92
+ return {
93
+ access_token: this.createAccessToken(currentUserData),
94
+ refresh_token: refreshToken,
95
+ device_id: '',
96
+ user_id: authUser._id.toString()
97
+ };
101
98
  });
102
99
  });
103
100
  });
@@ -8,8 +8,11 @@ export type LoginSuccessDto = {
8
8
  refresh_token: string;
9
9
  user_id: string;
10
10
  };
11
+ export type LoginErrorDto = {
12
+ message: string;
13
+ };
11
14
  export interface LoginDto {
12
15
  Body: LoginUserDto;
13
- Reply: LoginSuccessDto;
16
+ Reply: LoginSuccessDto | LoginErrorDto;
14
17
  }
15
18
  //# sourceMappingURL=dtos.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"dtos.d.ts","sourceRoot":"","sources":["../../../../src/auth/providers/custom-function/dtos.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,YAAY,GAAG;IACzB,QAAQ,EAAE,MAAM,CAAA;IAChB,QAAQ,EAAE,MAAM,CAAA;CACjB,CAAA;AAED,MAAM,MAAM,eAAe,GAAG;IAC5B,YAAY,EAAE,MAAM,CAAA;IACpB,SAAS,EAAE,MAAM,CAAA;IACjB,aAAa,EAAE,MAAM,CAAA;IACrB,OAAO,EAAE,MAAM,CAAA;CAChB,CAAA;AAED,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,YAAY,CAAA;IAClB,KAAK,EAAE,eAAe,CAAA;CACvB"}
1
+ {"version":3,"file":"dtos.d.ts","sourceRoot":"","sources":["../../../../src/auth/providers/custom-function/dtos.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,YAAY,GAAG;IACzB,QAAQ,EAAE,MAAM,CAAA;IAChB,QAAQ,EAAE,MAAM,CAAA;CACjB,CAAA;AAED,MAAM,MAAM,eAAe,GAAG;IAC5B,YAAY,EAAE,MAAM,CAAA;IACpB,SAAS,EAAE,MAAM,CAAA;IACjB,aAAa,EAAE,MAAM,CAAA;IACrB,OAAO,EAAE,MAAM,CAAA;CAChB,CAAA;AAED,MAAM,MAAM,aAAa,GAAG;IAC1B,OAAO,EAAE,MAAM,CAAA;CAChB,CAAA;AAED,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,YAAY,CAAA;IAClB,KAAK,EAAE,eAAe,GAAG,aAAa,CAAA;CACvC"}
@@ -1 +1 @@
1
- {"version":3,"file":"controller.d.ts","sourceRoot":"","sources":["../../../../src/auth/providers/local-userpass/controller.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,SAAS,CAAA;AAmCzC;;;;GAIG;AACH,wBAAsB,uBAAuB,CAAC,GAAG,EAAE,eAAe,iBA2TjE"}
1
+ {"version":3,"file":"controller.d.ts","sourceRoot":"","sources":["../../../../src/auth/providers/local-userpass/controller.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,SAAS,CAAA;AAqCzC;;;;GAIG;AACH,wBAAsB,uBAAuB,CAAC,GAAG,EAAE,eAAe,iBAsUjE"}
@@ -14,7 +14,6 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
14
14
  Object.defineProperty(exports, "__esModule", { value: true });
15
15
  exports.localUserPassController = localUserPassController;
16
16
  const constants_1 = require("../../../constants");
17
- const services_1 = require("../../../services");
18
17
  const handleUserRegistration_1 = __importDefault(require("../../../shared/handleUserRegistration"));
19
18
  const handleUserRegistration_model_1 = require("../../../shared/models/handleUserRegistration.model");
20
19
  const state_1 = require("../../../state");
@@ -38,14 +37,14 @@ const isRateLimited = (key, maxAttempts, windowMs) => {
38
37
  */
39
38
  function localUserPassController(app) {
40
39
  return __awaiter(this, void 0, void 0, function* () {
41
- const functionsList = state_1.StateManager.select('functions');
42
- const { authCollection, userCollection, user_id_field, on_user_creation_function_name } = constants_1.AUTH_CONFIG;
40
+ const { authCollection, userCollection, user_id_field } = constants_1.AUTH_CONFIG;
43
41
  const { resetPasswordCollection } = constants_1.AUTH_CONFIG;
44
42
  const { refreshTokensCollection } = constants_1.AUTH_CONFIG;
45
43
  const db = app.mongo.client.db(constants_1.DB_NAME);
46
44
  const resetPasswordTtlSeconds = constants_1.DEFAULT_CONFIG.RESET_PASSWORD_TTL_SECONDS;
47
45
  const rateLimitWindowMs = constants_1.DEFAULT_CONFIG.AUTH_RATE_LIMIT_WINDOW_MS;
48
46
  const loginMaxAttempts = constants_1.DEFAULT_CONFIG.AUTH_LOGIN_MAX_ATTEMPTS;
47
+ const registerMaxAttempts = constants_1.DEFAULT_CONFIG.AUTH_REGISTER_MAX_ATTEMPTS;
49
48
  const resetMaxAttempts = constants_1.DEFAULT_CONFIG.AUTH_RESET_MAX_ATTEMPTS;
50
49
  const refreshTokenTtlMs = constants_1.DEFAULT_CONFIG.REFRESH_TOKEN_TTL_DAYS * 24 * 60 * 60 * 1000;
51
50
  try {
@@ -103,6 +102,11 @@ function localUserPassController(app) {
103
102
  app.post(utils_1.AUTH_ENDPOINTS.REGISTRATION, {
104
103
  schema: utils_1.REGISTRATION_SCHEMA
105
104
  }, (req, res) => __awaiter(this, void 0, void 0, function* () {
105
+ const key = `register:${req.ip}`;
106
+ if (isRateLimited(key, registerMaxAttempts, rateLimitWindowMs)) {
107
+ res.status(429).send({ message: 'Too many requests' });
108
+ return;
109
+ }
106
110
  const result = yield (0, handleUserRegistration_1.default)(app, { run_as_system: true, provider: handleUserRegistration_model_1.PROVIDER.LOCAL_USERPASS })({ email: req.body.email.toLowerCase(), password: req.body.password });
107
111
  if (!(result === null || result === void 0 ? void 0 : result.insertedId)) {
108
112
  res === null || res === void 0 ? void 0 : res.status(500);
@@ -111,6 +115,38 @@ function localUserPassController(app) {
111
115
  res === null || res === void 0 ? void 0 : res.status(201);
112
116
  return { userId: result.insertedId.toString() };
113
117
  }));
118
+ /**
119
+ * Endpoint for confirming a user registration.
120
+ *
121
+ * @route {POST} /confirm
122
+ * @param {ConfirmUserDto} req - The request object with confirmation data.
123
+ * @returns {Promise<Object>} A promise resolving with confirmation status.
124
+ */
125
+ app.post(utils_1.AUTH_ENDPOINTS.CONFIRM, {
126
+ schema: utils_1.CONFIRM_USER_SCHEMA
127
+ }, (req, res) => __awaiter(this, void 0, void 0, function* () {
128
+ const key = `confirm:${req.ip}`;
129
+ if (isRateLimited(key, resetMaxAttempts, rateLimitWindowMs)) {
130
+ res.status(429).send({ message: 'Too many requests' });
131
+ return;
132
+ }
133
+ const existing = yield db.collection(authCollection).findOne({
134
+ confirmationToken: req.body.token,
135
+ confirmationTokenId: req.body.tokenId
136
+ });
137
+ if (!existing) {
138
+ res.status(500);
139
+ throw new Error(utils_1.AUTH_ERRORS.INVALID_TOKEN);
140
+ }
141
+ if (existing.status !== 'confirmed') {
142
+ yield db.collection(authCollection).updateOne({ _id: existing._id }, {
143
+ $set: { status: 'confirmed' },
144
+ $unset: { confirmationToken: '', confirmationTokenId: '' }
145
+ });
146
+ }
147
+ res.status(200);
148
+ return { status: 'confirmed' };
149
+ }));
114
150
  /**
115
151
  * Endpoint for user login.
116
152
  *
@@ -144,36 +180,8 @@ function localUserPassController(app) {
144
180
  : {};
145
181
  authUser === null || authUser === void 0 ? true : delete authUser.password;
146
182
  const userWithCustomData = Object.assign(Object.assign({}, authUser), { user_data: Object.assign(Object.assign({}, (user || {})), { _id: authUser._id }), data: { email: authUser.email }, id: authUser._id.toString() });
147
- if (authUser && authUser.status === 'pending') {
148
- try {
149
- yield (db === null || db === void 0 ? void 0 : db.collection(authCollection).updateOne({ _id: authUser._id }, {
150
- $set: {
151
- status: 'confirmed'
152
- }
153
- }));
154
- }
155
- catch (error) {
156
- console.log('>>> 🚀 ~ localUserPassController ~ error:', error);
157
- }
158
- }
159
- if (authUser &&
160
- authUser.status === 'pending' &&
161
- on_user_creation_function_name &&
162
- functionsList[on_user_creation_function_name]) {
163
- try {
164
- yield (0, context_1.GenerateContext)({
165
- args: [userWithCustomData],
166
- app,
167
- rules: {},
168
- user: userWithCustomData,
169
- currentFunction: functionsList[on_user_creation_function_name],
170
- functionsList,
171
- services: services_1.services
172
- });
173
- }
174
- catch (error) {
175
- console.log('localUserPassController - /login - GenerateContext - CATCH:', error);
176
- }
183
+ if (authUser && authUser.status !== 'confirmed') {
184
+ throw new Error(utils_1.AUTH_ERRORS.USER_NOT_CONFIRMED);
177
185
  }
178
186
  const refreshToken = this.createRefreshToken(userWithCustomData);
179
187
  const refreshTokenHash = (0, crypto_1.hashToken)(refreshToken);
@@ -41,4 +41,10 @@ export interface ConfirmResetPasswordDto {
41
41
  password: string;
42
42
  };
43
43
  }
44
+ export interface ConfirmUserDto {
45
+ Body: {
46
+ token: string;
47
+ tokenId: string;
48
+ };
49
+ }
44
50
  //# sourceMappingURL=dtos.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"dtos.d.ts","sourceRoot":"","sources":["../../../../src/auth/providers/local-userpass/dtos.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,eAAe,GAAG;IAC5B,KAAK,EAAE,MAAM,CAAA;IACb,QAAQ,EAAE,MAAM,CAAA;CACjB,CAAA;AAED,MAAM,MAAM,YAAY,GAAG;IACzB,QAAQ,EAAE,MAAM,CAAA;IAChB,QAAQ,EAAE,MAAM,CAAA;CACjB,CAAA;AAED,MAAM,MAAM,eAAe,GAAG;IAC5B,YAAY,EAAE,MAAM,CAAA;IACpB,SAAS,EAAE,MAAM,CAAA;IACjB,aAAa,EAAE,MAAM,CAAA;IACrB,OAAO,EAAE,MAAM,CAAA;CAChB,CAAA;AAED,MAAM,MAAM,gBAAgB,GAAG;IAC7B,OAAO,EAAE,MAAM,CAAA;CAChB,CAAA;AAED,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,eAAe,CAAA;CACtB;AAED,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,YAAY,CAAA;IAClB,KAAK,EAAE,eAAe,GAAG,gBAAgB,CAAA;CAC1C;AAED,MAAM,WAAW,oBAAoB;IACnC,IAAI,EAAE;QACJ,KAAK,EAAE,MAAM,CAAA;KACd,CAAA;CACF;AAED,MAAM,WAAW,oBAAoB;IACnC,IAAI,EAAE;QACJ,KAAK,EAAE,MAAM,CAAA;QACb,QAAQ,EAAE,MAAM,CAAA;QAChB,SAAS,CAAC,EAAE,OAAO,EAAE,CAAA;KACtB,CAAA;CACF;AAED,MAAM,WAAW,uBAAuB;IACtC,IAAI,EAAE;QACJ,KAAK,EAAE,MAAM,CAAA;QACb,OAAO,EAAE,MAAM,CAAA;QACf,QAAQ,EAAE,MAAM,CAAA;KACjB,CAAA;CACF"}
1
+ {"version":3,"file":"dtos.d.ts","sourceRoot":"","sources":["../../../../src/auth/providers/local-userpass/dtos.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,eAAe,GAAG;IAC5B,KAAK,EAAE,MAAM,CAAA;IACb,QAAQ,EAAE,MAAM,CAAA;CACjB,CAAA;AAED,MAAM,MAAM,YAAY,GAAG;IACzB,QAAQ,EAAE,MAAM,CAAA;IAChB,QAAQ,EAAE,MAAM,CAAA;CACjB,CAAA;AAED,MAAM,MAAM,eAAe,GAAG;IAC5B,YAAY,EAAE,MAAM,CAAA;IACpB,SAAS,EAAE,MAAM,CAAA;IACjB,aAAa,EAAE,MAAM,CAAA;IACrB,OAAO,EAAE,MAAM,CAAA;CAChB,CAAA;AAED,MAAM,MAAM,gBAAgB,GAAG;IAC7B,OAAO,EAAE,MAAM,CAAA;CAChB,CAAA;AAED,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,eAAe,CAAA;CACtB;AAED,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,YAAY,CAAA;IAClB,KAAK,EAAE,eAAe,GAAG,gBAAgB,CAAA;CAC1C;AAED,MAAM,WAAW,oBAAoB;IACnC,IAAI,EAAE;QACJ,KAAK,EAAE,MAAM,CAAA;KACd,CAAA;CACF;AAED,MAAM,WAAW,oBAAoB;IACnC,IAAI,EAAE;QACJ,KAAK,EAAE,MAAM,CAAA;QACb,QAAQ,EAAE,MAAM,CAAA;QAChB,SAAS,CAAC,EAAE,OAAO,EAAE,CAAA;KACtB,CAAA;CACF;AAED,MAAM,WAAW,uBAAuB;IACtC,IAAI,EAAE;QACJ,KAAK,EAAE,MAAM,CAAA;QACb,OAAO,EAAE,MAAM,CAAA;QACf,QAAQ,EAAE,MAAM,CAAA;KACjB,CAAA;CACF;AAED,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE;QACJ,KAAK,EAAE,MAAM,CAAA;QACb,OAAO,EAAE,MAAM,CAAA;KAChB,CAAA;CACF"}
@@ -72,6 +72,20 @@ export declare const CONFIRM_RESET_SCHEMA: {
72
72
  required: string[];
73
73
  };
74
74
  };
75
+ export declare const CONFIRM_USER_SCHEMA: {
76
+ body: {
77
+ type: string;
78
+ properties: {
79
+ token: {
80
+ type: string;
81
+ };
82
+ tokenId: {
83
+ type: string;
84
+ };
85
+ };
86
+ required: string[];
87
+ };
88
+ };
75
89
  export declare const RESET_SCHEMA: {
76
90
  body: {
77
91
  type: string;
@@ -108,6 +122,7 @@ export declare const REGISTRATION_SCHEMA: {
108
122
  export declare enum AUTH_ENDPOINTS {
109
123
  LOGIN = "/login",
110
124
  REGISTRATION = "/register",
125
+ CONFIRM = "/confirm",
111
126
  PROFILE = "/profile",
112
127
  SESSION = "/session",
113
128
  RESET = "/reset/send",
@@ -119,13 +134,15 @@ export declare enum AUTH_ERRORS {
119
134
  INVALID_CREDENTIALS = "Invalid credentials",
120
135
  INVALID_TOKEN = "Invalid refresh token provided",
121
136
  INVALID_RESET_PARAMS = "Invalid token or tokenId provided",
122
- MISSING_RESET_FUNCTION = "Missing reset function"
137
+ MISSING_RESET_FUNCTION = "Missing reset function",
138
+ USER_NOT_CONFIRMED = "User not confirmed"
123
139
  }
124
140
  export interface AuthConfig {
125
141
  auth_collection?: string;
126
142
  'api-key': ApiKey;
127
143
  'local-userpass': LocalUserpass;
128
144
  'custom-function': CustomFunction;
145
+ 'anon-user'?: AnonUser;
129
146
  }
130
147
  interface ApiKey {
131
148
  name: string;
@@ -146,8 +163,14 @@ interface CustomFunction {
146
163
  "authFunctionName": string;
147
164
  };
148
165
  }
166
+ export interface AnonUser {
167
+ name: "anon-user";
168
+ type: "anon-user";
169
+ disabled: boolean;
170
+ }
149
171
  export interface Config {
150
172
  autoConfirm: boolean;
173
+ confirmationFunctionName?: string;
151
174
  resetFunctionName: string;
152
175
  resetPasswordUrl: string;
153
176
  runConfirmationFunction: boolean;
@@ -1 +1 @@
1
- {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/auth/utils.ts"],"names":[],"mappings":"AAMA,eAAO,MAAM,YAAY;;;;;;;;;;;;;;;;;;CAcxB,CAAA;AAED,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;CAa7B,CAAA;AAED,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;;;;;;;;CAe7B,CAAA;AAED,eAAO,MAAM,oBAAoB;;;;;;;;;;;;;;;;;;CAUhC,CAAA;AAED,eAAO,MAAM,YAAY;;;;;;;;;;;;;CAAoB,CAAA;AAE7C,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;;;;;;CAc/B,CAAA;AAED,oBAAY,cAAc;IACxB,KAAK,WAAW;IAChB,YAAY,cAAc;IAC1B,OAAO,aAAa;IACpB,OAAO,aAAa;IACpB,KAAK,gBAAgB;IACrB,UAAU,gBAAgB;IAC1B,aAAa,WAAW;IACxB,UAAU,sBAAsB;CACjC;AAED,oBAAY,WAAW;IACrB,mBAAmB,wBAAwB;IAC3C,aAAa,mCAAmC;IAChD,oBAAoB,sCAAsC;IAC1D,sBAAsB,2BAA2B;CAClD;AAED,MAAM,WAAW,UAAU;IACzB,eAAe,CAAC,EAAE,MAAM,CAAA;IACxB,SAAS,EAAE,MAAM,CAAA;IACjB,gBAAgB,EAAE,aAAa,CAAA;IAC/B,iBAAiB,EAAE,cAAc,CAAA;CAClC;AAED,UAAU,MAAM;IACd,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,MAAM,CAAA;IACZ,QAAQ,EAAE,OAAO,CAAA;CAClB;AACD,UAAU,aAAa;IACrB,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,MAAM,CAAA;IACZ,QAAQ,EAAE,OAAO,CAAA;IACjB,MAAM,EAAE,MAAM,CAAA;CACf;AAED,UAAU,cAAc;IACtB,IAAI,EAAE,iBAAiB,CAAC;IACxB,IAAI,EAAE,iBAAiB,CAAC;IACxB,QAAQ,EAAE,OAAO,CAAC;IAClB,MAAM,EAAE;QACN,kBAAkB,EAAE,MAAM,CAAA;KAC3B,CAAA;CACF;AAED,MAAM,WAAW,MAAM;IACrB,WAAW,EAAE,OAAO,CAAA;IACpB,iBAAiB,EAAE,MAAM,CAAA;IACzB,gBAAgB,EAAE,MAAM,CAAA;IACxB,uBAAuB,EAAE,OAAO,CAAA;IAChC,gBAAgB,EAAE,OAAO,CAAA;CAC1B;AAED,MAAM,WAAW,oBAAoB;IACnC,OAAO,EAAE,OAAO,CAAA;IAChB,kBAAkB,EAAE,MAAM,CAAA;IAC1B,aAAa,EAAE,MAAM,CAAA;IACrB,eAAe,EAAE,MAAM,CAAA;IACvB,aAAa,EAAE,MAAM,CAAA;IACrB,8BAA8B,EAAE,MAAM,CAAA;CACvC;AAMD;;;GAGG;AACH,eAAO,MAAM,cAAc,QAAO,UAGjC,CAAA;AAED;;;GAGG;AACH,eAAO,MAAM,kBAAkB,QAAO,oBAGrC,CAAA;AAED,eAAO,MAAM,gBAAgB,GAAI,eAAW,WAG3C,CAAA"}
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/auth/utils.ts"],"names":[],"mappings":"AAMA,eAAO,MAAM,YAAY;;;;;;;;;;;;;;;;;;CAcxB,CAAA;AAED,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;CAa7B,CAAA;AAED,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;;;;;;;;CAe7B,CAAA;AAED,eAAO,MAAM,oBAAoB;;;;;;;;;;;;;;;;;;CAUhC,CAAA;AAED,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;CAS/B,CAAA;AAED,eAAO,MAAM,YAAY;;;;;;;;;;;;;CAAoB,CAAA;AAE7C,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;;;;;;CAc/B,CAAA;AAED,oBAAY,cAAc;IACxB,KAAK,WAAW;IAChB,YAAY,cAAc;IAC1B,OAAO,aAAa;IACpB,OAAO,aAAa;IACpB,OAAO,aAAa;IACpB,KAAK,gBAAgB;IACrB,UAAU,gBAAgB;IAC1B,aAAa,WAAW;IACxB,UAAU,sBAAsB;CACjC;AAED,oBAAY,WAAW;IACrB,mBAAmB,wBAAwB;IAC3C,aAAa,mCAAmC;IAChD,oBAAoB,sCAAsC;IAC1D,sBAAsB,2BAA2B;IACjD,kBAAkB,uBAAuB;CAC1C;AAED,MAAM,WAAW,UAAU;IACzB,eAAe,CAAC,EAAE,MAAM,CAAA;IACxB,SAAS,EAAE,MAAM,CAAA;IACjB,gBAAgB,EAAE,aAAa,CAAA;IAC/B,iBAAiB,EAAE,cAAc,CAAA;IACjC,WAAW,CAAC,EAAE,QAAQ,CAAA;CACvB;AAED,UAAU,MAAM;IACd,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,MAAM,CAAA;IACZ,QAAQ,EAAE,OAAO,CAAA;CAClB;AACD,UAAU,aAAa;IACrB,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,MAAM,CAAA;IACZ,QAAQ,EAAE,OAAO,CAAA;IACjB,MAAM,EAAE,MAAM,CAAA;CACf;AAED,UAAU,cAAc;IACtB,IAAI,EAAE,iBAAiB,CAAC;IACxB,IAAI,EAAE,iBAAiB,CAAC;IACxB,QAAQ,EAAE,OAAO,CAAC;IAClB,MAAM,EAAE;QACN,kBAAkB,EAAE,MAAM,CAAA;KAC3B,CAAA;CACF;AAED,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,WAAW,CAAA;IACjB,IAAI,EAAE,WAAW,CAAA;IACjB,QAAQ,EAAE,OAAO,CAAA;CAClB;AAED,MAAM,WAAW,MAAM;IACrB,WAAW,EAAE,OAAO,CAAA;IACpB,wBAAwB,CAAC,EAAE,MAAM,CAAA;IACjC,iBAAiB,EAAE,MAAM,CAAA;IACzB,gBAAgB,EAAE,MAAM,CAAA;IACxB,uBAAuB,EAAE,OAAO,CAAA;IAChC,gBAAgB,EAAE,OAAO,CAAA;CAC1B;AAED,MAAM,WAAW,oBAAoB;IACnC,OAAO,EAAE,OAAO,CAAA;IAChB,kBAAkB,EAAE,MAAM,CAAA;IAC1B,aAAa,EAAE,MAAM,CAAA;IACrB,eAAe,EAAE,MAAM,CAAA;IACvB,aAAa,EAAE,MAAM,CAAA;IACrB,8BAA8B,EAAE,MAAM,CAAA;CACvC;AAMD;;;GAGG;AACH,eAAO,MAAM,cAAc,QAAO,UAGjC,CAAA;AAED;;;GAGG;AACH,eAAO,MAAM,kBAAkB,QAAO,oBAGrC,CAAA;AAED,eAAO,MAAM,gBAAgB,GAAI,eAAW,WAG3C,CAAA"}