@flowerforce/flowerbase 1.2.1-beta.16 → 1.2.1-beta.17

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 (33) hide show
  1. package/README.md +9 -3
  2. package/dist/auth/controller.d.ts.map +1 -1
  3. package/dist/auth/controller.js +2 -2
  4. package/dist/auth/plugins/jwt.js +3 -3
  5. package/dist/auth/providers/anon-user/controller.d.ts +8 -0
  6. package/dist/auth/providers/anon-user/controller.d.ts.map +1 -0
  7. package/dist/auth/providers/anon-user/controller.js +90 -0
  8. package/dist/auth/providers/anon-user/dtos.d.ts +10 -0
  9. package/dist/auth/providers/anon-user/dtos.d.ts.map +1 -0
  10. package/dist/auth/providers/anon-user/dtos.js +2 -0
  11. package/dist/auth/utils.d.ts +6 -0
  12. package/dist/auth/utils.d.ts.map +1 -1
  13. package/dist/constants.d.ts +2 -0
  14. package/dist/constants.d.ts.map +1 -1
  15. package/dist/constants.js +3 -1
  16. package/dist/shared/models/handleUserRegistration.model.d.ts +2 -1
  17. package/dist/shared/models/handleUserRegistration.model.d.ts.map +1 -1
  18. package/dist/shared/models/handleUserRegistration.model.js +1 -0
  19. package/dist/utils/context/index.d.ts.map +1 -1
  20. package/dist/utils/context/index.js +3 -10
  21. package/dist/utils/initializer/registerPlugins.d.ts.map +1 -1
  22. package/dist/utils/initializer/registerPlugins.js +12 -4
  23. package/package.json +1 -1
  24. package/src/auth/controller.ts +5 -2
  25. package/src/auth/plugins/jwt.ts +5 -5
  26. package/src/auth/providers/anon-user/controller.ts +91 -0
  27. package/src/auth/providers/anon-user/dtos.ts +10 -0
  28. package/src/auth/utils.ts +7 -0
  29. package/src/constants.ts +3 -1
  30. package/src/shared/models/handleUserRegistration.model.ts +2 -1
  31. package/src/utils/__tests__/registerPlugins.test.ts +5 -1
  32. package/src/utils/context/index.ts +5 -12
  33. package/src/utils/initializer/registerPlugins.ts +8 -0
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 });
@@ -142,6 +142,7 @@ export interface AuthConfig {
142
142
  'api-key': ApiKey;
143
143
  'local-userpass': LocalUserpass;
144
144
  'custom-function': CustomFunction;
145
+ 'anon-user'?: AnonUser;
145
146
  }
146
147
  interface ApiKey {
147
148
  name: string;
@@ -162,6 +163,11 @@ interface CustomFunction {
162
163
  "authFunctionName": string;
163
164
  };
164
165
  }
166
+ export interface AnonUser {
167
+ name: "anon-user";
168
+ type: "anon-user";
169
+ disabled: boolean;
170
+ }
165
171
  export interface Config {
166
172
  autoConfirm: boolean;
167
173
  confirmationFunctionName?: string;
@@ -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,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;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,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"}
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"}
@@ -12,6 +12,7 @@ export declare const DEFAULT_CONFIG: {
12
12
  AUTH_LOGIN_MAX_ATTEMPTS: number;
13
13
  AUTH_RESET_MAX_ATTEMPTS: number;
14
14
  REFRESH_TOKEN_TTL_DAYS: number;
15
+ ANON_USER_TTL_SECONDS: number;
15
16
  SWAGGER_UI_USER: string;
16
17
  SWAGGER_UI_PASSWORD: string;
17
18
  CORS_OPTIONS: {
@@ -35,6 +36,7 @@ export declare const AUTH_CONFIG: {
35
36
  "custom-function": {
36
37
  authFunctionName: string;
37
38
  };
39
+ "anon-user": import("./auth/utils").AnonUser | undefined;
38
40
  };
39
41
  };
40
42
  export declare const S3_CONFIG: {
@@ -1 +1 @@
1
- {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,eAAe,EAAE,MAAM,IAAI,CAAA;AAUpC,eAAO,MAAM,cAAc;;;;;;;;;;;;;;;;;iBAiBsB,eAAe,EAAE;;CAEjE,CAAA;AACD,eAAO,MAAM,WAAW,QAA8C,CAAA;AACtE,eAAO,MAAM,YAAY,QAA8B,CAAA;AACvD,eAAO,MAAM,OAAO,QAAgB,CAAA;AAGpC,eAAO,MAAM,WAAW;;;;;;;;;;;;;;CAYvB,CAAA;AAID,eAAO,MAAM,SAAS;;;CAGrB,CAAA"}
1
+ {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,eAAe,EAAE,MAAM,IAAI,CAAA;AAUpC,eAAO,MAAM,cAAc;;;;;;;;;;;;;;;;;;iBAkBsB,eAAe,EAAE;;CAEjE,CAAA;AACD,eAAO,MAAM,WAAW,QAA8C,CAAA;AACtE,eAAO,MAAM,YAAY,QAA8B,CAAA;AACvD,eAAO,MAAM,OAAO,QAAgB,CAAA;AAGpC,eAAO,MAAM,WAAW;;;;;;;;;;;;;;;CAavB,CAAA;AAID,eAAO,MAAM,SAAS;;;CAGrB,CAAA"}
package/dist/constants.js CHANGED
@@ -29,6 +29,7 @@ exports.DEFAULT_CONFIG = {
29
29
  AUTH_LOGIN_MAX_ATTEMPTS: Number(process.env.AUTH_LOGIN_MAX_ATTEMPTS) || 10,
30
30
  AUTH_RESET_MAX_ATTEMPTS: Number(process.env.AUTH_RESET_MAX_ATTEMPTS) || 5,
31
31
  REFRESH_TOKEN_TTL_DAYS: Number(process.env.REFRESH_TOKEN_TTL_DAYS) || 60,
32
+ ANON_USER_TTL_SECONDS: Number(process.env.ANON_USER_TTL_SECONDS) || 3 * 60 * 60,
32
33
  SWAGGER_UI_USER: process.env.SWAGGER_UI_USER || '',
33
34
  SWAGGER_UI_PASSWORD: process.env.SWAGGER_UI_PASSWORD || '',
34
35
  CORS_OPTIONS: {
@@ -50,7 +51,8 @@ exports.AUTH_CONFIG = {
50
51
  user_id_field,
51
52
  on_user_creation_function_name,
52
53
  providers: {
53
- "custom-function": (_c = configuration['custom-function']) === null || _c === void 0 ? void 0 : _c.config
54
+ "custom-function": (_c = configuration['custom-function']) === null || _c === void 0 ? void 0 : _c.config,
55
+ "anon-user": configuration['anon-user']
54
56
  }
55
57
  };
56
58
  exports.S3_CONFIG = {
@@ -20,7 +20,8 @@ type RegistrationResult = {
20
20
  export type HandleUserRegistration = (app: FastifyInstance, opt: Options) => (params: RegistrationParams) => Promise<RegistrationResult>;
21
21
  export declare enum PROVIDER {
22
22
  LOCAL_USERPASS = "local-userpass",
23
- CUSTOM_FUNCTION = "custom-function"
23
+ CUSTOM_FUNCTION = "custom-function",
24
+ ANON_USER = "anon-user"
24
25
  }
25
26
  export {};
26
27
  //# sourceMappingURL=handleUserRegistration.model.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"handleUserRegistration.model.d.ts","sourceRoot":"","sources":["../../../src/shared/models/handleUserRegistration.model.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAA;AACxD,OAAO,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAA;AACtC,OAAO,EAAE,KAAK,EAAE,MAAM,gCAAgC,CAAA;AAEtD,KAAK,kBAAkB,GAAG;IACxB,KAAK,EAAE,MAAM,CAAA;IACb,QAAQ,EAAE,MAAM,CAAA;CACjB,CAAA;AAED,MAAM,MAAM,OAAO,GAAG;IACpB,IAAI,CAAC,EAAE,IAAI,CAAA;IACX,KAAK,CAAC,EAAE,KAAK,CAAA;IACb,aAAa,CAAC,EAAE,OAAO,CAAA;IACvB,QAAQ,CAAC,EAAE,QAAQ,CAAA;IACnB,aAAa,CAAC,EAAE,OAAO,CAAA;CACxB,CAAA;AAED,KAAK,kBAAkB,GAAG;IACxB,UAAU,CAAC,EAAE;QACX,QAAQ,EAAE,MAAM,MAAM,CAAA;KACvB,CAAA;CACF,CAAA;AAED,MAAM,MAAM,sBAAsB,GAAG,CACnC,GAAG,EAAE,eAAe,EACpB,GAAG,EAAE,OAAO,KACT,CAAC,MAAM,EAAE,kBAAkB,KAAK,OAAO,CAAC,kBAAkB,CAAC,CAAA;AAEhE,oBAAY,QAAQ;IAClB,cAAc,mBAAmB;IACjC,eAAe,oBAAoB;CACpC"}
1
+ {"version":3,"file":"handleUserRegistration.model.d.ts","sourceRoot":"","sources":["../../../src/shared/models/handleUserRegistration.model.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAA;AACxD,OAAO,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAA;AACtC,OAAO,EAAE,KAAK,EAAE,MAAM,gCAAgC,CAAA;AAEtD,KAAK,kBAAkB,GAAG;IACxB,KAAK,EAAE,MAAM,CAAA;IACb,QAAQ,EAAE,MAAM,CAAA;CACjB,CAAA;AAED,MAAM,MAAM,OAAO,GAAG;IACpB,IAAI,CAAC,EAAE,IAAI,CAAA;IACX,KAAK,CAAC,EAAE,KAAK,CAAA;IACb,aAAa,CAAC,EAAE,OAAO,CAAA;IACvB,QAAQ,CAAC,EAAE,QAAQ,CAAA;IACnB,aAAa,CAAC,EAAE,OAAO,CAAA;CACxB,CAAA;AAED,KAAK,kBAAkB,GAAG;IACxB,UAAU,CAAC,EAAE;QACX,QAAQ,EAAE,MAAM,MAAM,CAAA;KACvB,CAAA;CACF,CAAA;AAED,MAAM,MAAM,sBAAsB,GAAG,CACnC,GAAG,EAAE,eAAe,EACpB,GAAG,EAAE,OAAO,KACT,CAAC,MAAM,EAAE,kBAAkB,KAAK,OAAO,CAAC,kBAAkB,CAAC,CAAA;AAEhE,oBAAY,QAAQ;IAClB,cAAc,mBAAmB;IACjC,eAAe,oBAAoB;IACnC,SAAS,cAAc;CACxB"}
@@ -5,4 +5,5 @@ var PROVIDER;
5
5
  (function (PROVIDER) {
6
6
  PROVIDER["LOCAL_USERPASS"] = "local-userpass";
7
7
  PROVIDER["CUSTOM_FUNCTION"] = "custom-function";
8
+ PROVIDER["ANON_USER"] = "anon-user";
8
9
  })(PROVIDER || (exports.PROVIDER = PROVIDER = {}));
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/utils/context/index.ts"],"names":[],"mappings":"AAOA,OAAO,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAA;AA0GnD;;;;;;;;;;GAUG;AACH,wBAAsB,eAAe,CAAC,EACpC,IAAI,EACJ,GAAG,EACH,KAAK,EACL,IAAI,EACJ,eAAe,EACf,aAAa,EACb,QAAQ,EACR,WAAW,EACX,eAAsB,EACtB,OAAO,EACP,OAAO,EACR,EAAE,qBAAqB,GAAG,OAAO,CAAC,OAAO,CAAC,CAuK1C"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/utils/context/index.ts"],"names":[],"mappings":"AAOA,OAAO,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAA;AA0GnD;;;;;;;;;;GAUG;AACH,wBAAsB,eAAe,CAAC,EACpC,IAAI,EACJ,GAAG,EACH,KAAK,EACL,IAAI,EACJ,eAAe,EACf,aAAa,EACb,QAAQ,EACR,WAAW,EACX,eAAsB,EACtB,OAAO,EACP,OAAO,EACR,EAAE,qBAAqB,GAAG,OAAO,CAAC,OAAO,CAAC,CAgK1C"}
@@ -186,16 +186,9 @@ function GenerateContext(_a) {
186
186
  moduleCache.set(importTarget, syntheticModule);
187
187
  return syntheticModule;
188
188
  });
189
- const importModuleDynamically = ((specifier) => __awaiter(this, void 0, void 0, function* () {
190
- const module = yield loadModule(specifier);
191
- if (module.status === 'unlinked') {
192
- yield module.link(loadModule);
193
- }
194
- if (module.status === 'linked') {
195
- yield module.evaluate();
196
- }
197
- return module;
198
- }));
189
+ const importModuleDynamically = (specifier, _script, _importAssertions) => {
190
+ return loadModule(specifier);
191
+ };
199
192
  const sourceModule = new vmModules.SourceTextModule(wrapEsmModule(functionToRun.code), {
200
193
  context: vmContext,
201
194
  identifier: entryFile,
@@ -1 +1 @@
1
- {"version":3,"file":"registerPlugins.d.ts","sourceRoot":"","sources":["../../../src/utils/initializer/registerPlugins.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,eAAe,EAAE,MAAM,SAAS,CAAA;AAEzC,OAAO,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAA;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"}
1
+ {"version":3,"file":"registerPlugins.d.ts","sourceRoot":"","sources":["../../../src/utils/initializer/registerPlugins.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,eAAe,EAAE,MAAM,SAAS,CAAA;AAEzC,OAAO,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAA;AAOnC,OAAO,EAAE,SAAS,EAAE,MAAM,oCAAoC,CAAA;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"}
@@ -18,8 +18,9 @@ const mongodb_1 = __importDefault(require("@fastify/mongodb"));
18
18
  const fastify_raw_body_1 = __importDefault(require("fastify-raw-body"));
19
19
  const controller_1 = require("../../auth/controller");
20
20
  const jwt_1 = __importDefault(require("../../auth/plugins/jwt"));
21
- const controller_2 = require("../../auth/providers/custom-function/controller");
22
- const controller_3 = require("../../auth/providers/local-userpass/controller");
21
+ const controller_2 = require("../../auth/providers/anon-user/controller");
22
+ const controller_3 = require("../../auth/providers/custom-function/controller");
23
+ const controller_4 = require("../../auth/providers/local-userpass/controller");
23
24
  const constants_1 = require("../../constants");
24
25
  /**
25
26
  * > Used to register all plugins
@@ -104,17 +105,24 @@ const getRegisterConfig = (_a) => __awaiter(void 0, [_a], void 0, function* ({ m
104
105
  },
105
106
  {
106
107
  pluginName: 'localUserPassController',
107
- plugin: controller_3.localUserPassController,
108
+ plugin: controller_4.localUserPassController,
108
109
  options: {
109
110
  prefix: `${constants_1.API_VERSION}/app/:appId/auth/providers/local-userpass`
110
111
  }
111
112
  },
112
113
  {
113
114
  pluginName: 'customFunctionController',
114
- plugin: controller_2.customFunctionController,
115
+ plugin: controller_3.customFunctionController,
115
116
  options: {
116
117
  prefix: `${constants_1.API_VERSION}/app/:appId/auth/providers/custom-function`
117
118
  }
119
+ },
120
+ {
121
+ pluginName: 'anonUserController',
122
+ plugin: controller_2.anonUserController,
123
+ options: {
124
+ prefix: `${constants_1.API_VERSION}/app/:appId/auth/providers/anon-user`
125
+ }
118
126
  }
119
127
  ];
120
128
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@flowerforce/flowerbase",
3
- "version": "1.2.1-beta.16",
3
+ "version": "1.2.1-beta.17",
4
4
  "description": "",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -1,9 +1,9 @@
1
1
  import { ObjectId } from 'bson'
2
2
  import { FastifyInstance } from 'fastify'
3
3
  import { AUTH_CONFIG, DB_NAME, DEFAULT_CONFIG } from '../constants'
4
+ import { hashToken } from '../utils/crypto'
4
5
  import { SessionCreatedDto } from './dtos'
5
6
  import { AUTH_ENDPOINTS, AUTH_ERRORS } from './utils'
6
- import { hashToken } from '../utils/crypto'
7
7
 
8
8
  const HANDLER_TYPE = 'preHandler'
9
9
 
@@ -101,7 +101,10 @@ export async function authController(app: FastifyInstance) {
101
101
  return {
102
102
  access_token: this.createAccessToken({
103
103
  ...auth_user,
104
- user_data: user
104
+ user_data: {
105
+ ...user,
106
+ id: req.user.sub
107
+ }
105
108
  })
106
109
  }
107
110
  }
@@ -91,13 +91,13 @@ export default fp(async function (fastify, opts: Options) {
91
91
 
92
92
  fastify.decorate('createAccessToken', function (user: WithId<Document>) {
93
93
  const id = user._id.toString()
94
- const userDataId = user.user_data._id.toString()
94
+ // const userDataId = user.user_data._id.toString()
95
95
 
96
96
  const user_data = {
97
- _id: userDataId,
98
- id: userDataId,
97
+ ...user.user_data,
98
+ _id: id,
99
+ id: id,
99
100
  email: user.email,
100
- ...user.user_data
101
101
  }
102
102
 
103
103
  return this.jwt.sign(
@@ -111,7 +111,7 @@ export default fp(async function (fastify, opts: Options) {
111
111
  {
112
112
  iss: BAAS_ID,
113
113
  jti: BAAS_ID,
114
- sub: user._id.toJSON(),
114
+ sub: id,
115
115
  expiresIn: '300m'
116
116
  }
117
117
  )
@@ -0,0 +1,91 @@
1
+ import { FastifyInstance } from 'fastify'
2
+ import { AUTH_CONFIG, DB_NAME, DEFAULT_CONFIG } from '../../../constants'
3
+ import { hashToken } from '../../../utils/crypto'
4
+ import { PROVIDER } from '../../../shared/models/handleUserRegistration.model'
5
+ import { AUTH_ENDPOINTS } from '../../utils'
6
+ import { LoginDto } from './dtos'
7
+
8
+ /**
9
+ * Controller for handling anonymous user login.
10
+ * @testable
11
+ * @param {FastifyInstance} app - The Fastify instance.
12
+ */
13
+ export async function anonUserController(app: FastifyInstance) {
14
+ const db = app.mongo.client.db(DB_NAME)
15
+ const { authCollection, refreshTokensCollection, providers } = AUTH_CONFIG
16
+ const refreshTokenTtlMs = DEFAULT_CONFIG.REFRESH_TOKEN_TTL_DAYS * 24 * 60 * 60 * 1000
17
+ const anonUserTtlSeconds = DEFAULT_CONFIG.ANON_USER_TTL_SECONDS
18
+
19
+ try {
20
+ await db.collection(authCollection!).createIndex(
21
+ { createdAt: 1 },
22
+ {
23
+ expireAfterSeconds: anonUserTtlSeconds,
24
+ partialFilterExpression: { 'identities.provider_type': PROVIDER.ANON_USER }
25
+ }
26
+ )
27
+ } catch (error) {
28
+ console.error('Failed to ensure anonymous user TTL index', error)
29
+ }
30
+
31
+ app.post<LoginDto>(
32
+ AUTH_ENDPOINTS.LOGIN,
33
+ async function () {
34
+ const anonProvider = providers?.['anon-user']
35
+ if (anonProvider?.disabled) {
36
+ throw new Error('Anonymous authentication disabled')
37
+ }
38
+
39
+ const now = new Date()
40
+ const insertResult = await db.collection(authCollection!).insertOne({
41
+ status: 'confirmed',
42
+ createdAt: now,
43
+ custom_data: {},
44
+ identities: [
45
+ {
46
+ provider_type: PROVIDER.ANON_USER,
47
+ provider_data: {}
48
+ }
49
+ ]
50
+ })
51
+
52
+ const userId = insertResult.insertedId
53
+ await db.collection(authCollection!).updateOne(
54
+ { _id: userId },
55
+ {
56
+ $set: {
57
+ identities: [
58
+ {
59
+ id: userId.toString(),
60
+ provider_id: userId.toString(),
61
+ provider_type: PROVIDER.ANON_USER,
62
+ provider_data: {}
63
+ }
64
+ ]
65
+ }
66
+ }
67
+ )
68
+
69
+ const currentUserData = {
70
+ _id: userId,
71
+ user_data: {}
72
+ }
73
+ const refreshToken = this.createRefreshToken(currentUserData)
74
+ const refreshTokenHash = hashToken(refreshToken)
75
+ await db.collection(refreshTokensCollection).insertOne({
76
+ userId,
77
+ tokenHash: refreshTokenHash,
78
+ createdAt: now,
79
+ expiresAt: new Date(Date.now() + refreshTokenTtlMs),
80
+ revokedAt: null
81
+ })
82
+
83
+ return {
84
+ access_token: this.createAccessToken(currentUserData),
85
+ refresh_token: refreshToken,
86
+ device_id: '',
87
+ user_id: userId.toString()
88
+ }
89
+ }
90
+ )
91
+ }
@@ -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
+
8
+ export interface LoginDto {
9
+ Reply: LoginSuccessDto
10
+ }
package/src/auth/utils.ts CHANGED
@@ -118,6 +118,7 @@ export interface AuthConfig {
118
118
  'api-key': ApiKey
119
119
  'local-userpass': LocalUserpass
120
120
  'custom-function': CustomFunction
121
+ 'anon-user'?: AnonUser
121
122
  }
122
123
 
123
124
  interface ApiKey {
@@ -141,6 +142,12 @@ interface CustomFunction {
141
142
  }
142
143
  }
143
144
 
145
+ export interface AnonUser {
146
+ name: "anon-user"
147
+ type: "anon-user"
148
+ disabled: boolean
149
+ }
150
+
144
151
  export interface Config {
145
152
  autoConfirm: boolean
146
153
  confirmationFunctionName?: string
package/src/constants.ts CHANGED
@@ -22,6 +22,7 @@ export const DEFAULT_CONFIG = {
22
22
  AUTH_LOGIN_MAX_ATTEMPTS: Number(process.env.AUTH_LOGIN_MAX_ATTEMPTS) || 10,
23
23
  AUTH_RESET_MAX_ATTEMPTS: Number(process.env.AUTH_RESET_MAX_ATTEMPTS) || 5,
24
24
  REFRESH_TOKEN_TTL_DAYS: Number(process.env.REFRESH_TOKEN_TTL_DAYS) || 60,
25
+ ANON_USER_TTL_SECONDS: Number(process.env.ANON_USER_TTL_SECONDS) || 3 * 60 * 60,
25
26
  SWAGGER_UI_USER: process.env.SWAGGER_UI_USER || '',
26
27
  SWAGGER_UI_PASSWORD: process.env.SWAGGER_UI_PASSWORD || '',
27
28
  CORS_OPTIONS: {
@@ -44,7 +45,8 @@ export const AUTH_CONFIG = {
44
45
  user_id_field,
45
46
  on_user_creation_function_name,
46
47
  providers: {
47
- "custom-function": configuration['custom-function']?.config
48
+ "custom-function": configuration['custom-function']?.config,
49
+ "anon-user": configuration['anon-user']
48
50
  }
49
51
  }
50
52
 
@@ -28,5 +28,6 @@ export type HandleUserRegistration = (
28
28
 
29
29
  export enum PROVIDER {
30
30
  LOCAL_USERPASS = "local-userpass",
31
- CUSTOM_FUNCTION = "custom-function"
31
+ CUSTOM_FUNCTION = "custom-function",
32
+ ANON_USER = "anon-user"
32
33
  }
@@ -3,6 +3,7 @@ import fastifyMongodb from '@fastify/mongodb'
3
3
  import { authController } from '../../auth/controller'
4
4
  import jwtAuthPlugin from '../../auth/plugins/jwt'
5
5
  import fastifyRawBody from 'fastify-raw-body'
6
+ import { anonUserController } from '../../auth/providers/anon-user/controller'
6
7
  import { customFunctionController } from '../../auth/providers/custom-function/controller'
7
8
  import { localUserPassController } from '../../auth/providers/local-userpass/controller'
8
9
  import { Functions } from '../../features/functions/interface'
@@ -36,7 +37,7 @@ describe('registerPlugins', () => {
36
37
  })
37
38
 
38
39
  // Check Plugins Registration
39
- expect(registerMock).toHaveBeenCalledTimes(7)
40
+ expect(registerMock).toHaveBeenCalledTimes(8)
40
41
  expect(registerMock).toHaveBeenCalledWith(cors, {
41
42
  origin: '*',
42
43
  methods: ['POST', 'GET']
@@ -63,6 +64,9 @@ describe('registerPlugins', () => {
63
64
  expect(registerMock).toHaveBeenCalledWith(customFunctionController, {
64
65
  prefix: `${MOCKED_API_VERSION}/app/:appId/auth/providers/custom-function`
65
66
  })
67
+ expect(registerMock).toHaveBeenCalledWith(anonUserController, {
68
+ prefix: `${MOCKED_API_VERSION}/app/:appId/auth/providers/anon-user`
69
+ })
66
70
  })
67
71
 
68
72
  it('should handle errors in the catch block', async () => {
@@ -238,18 +238,11 @@ export async function GenerateContext({
238
238
  return syntheticModule
239
239
  }
240
240
 
241
- const importModuleDynamically = (async (
242
- specifier: string
243
- ): Promise<vm.Module> => {
244
- const module = await loadModule(specifier)
245
- if (module.status === 'unlinked') {
246
- await module.link(loadModule)
247
- }
248
- if (module.status === 'linked') {
249
- await module.evaluate()
250
- }
251
- return module
252
- }) as unknown as vm.ScriptOptions['importModuleDynamically']
241
+ const importModuleDynamically: NonNullable<
242
+ vm.ScriptOptions['importModuleDynamically']
243
+ > = (specifier, _script, _importAssertions) => {
244
+ return loadModule(specifier) as unknown as vm.Module
245
+ }
253
246
 
254
247
  const sourceModule = new vmModules.SourceTextModule(
255
248
  wrapEsmModule(functionToRun.code),
@@ -5,6 +5,7 @@ import fastifyRawBody from 'fastify-raw-body'
5
5
  import { CorsConfig } from '../../'
6
6
  import { authController } from '../../auth/controller'
7
7
  import jwtAuthPlugin from '../../auth/plugins/jwt'
8
+ import { anonUserController } from '../../auth/providers/anon-user/controller'
8
9
  import { customFunctionController } from '../../auth/providers/custom-function/controller'
9
10
  import { localUserPassController } from '../../auth/providers/local-userpass/controller'
10
11
  import { API_VERSION } from '../../constants'
@@ -133,6 +134,13 @@ const getRegisterConfig = async ({
133
134
  options: {
134
135
  prefix: `${API_VERSION}/app/:appId/auth/providers/custom-function`
135
136
  }
137
+ },
138
+ {
139
+ pluginName: 'anonUserController',
140
+ plugin: anonUserController,
141
+ options: {
142
+ prefix: `${API_VERSION}/app/:appId/auth/providers/anon-user`
143
+ }
136
144
  }
137
145
  ] as RegisterConfig[]
138
146
  }