@flusys/nestjs-auth 1.0.0-beta → 1.0.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 (106) hide show
  1. package/README.md +590 -473
  2. package/cjs/config/auth.constants.js +12 -0
  3. package/cjs/controllers/authentication.controller.js +365 -24
  4. package/cjs/controllers/branch.controller.js +44 -1
  5. package/cjs/controllers/company-selection.controller.js +27 -20
  6. package/cjs/controllers/company.controller.js +44 -1
  7. package/cjs/controllers/user-permission.controller.js +82 -154
  8. package/cjs/controllers/user.controller.js +211 -7
  9. package/cjs/docs/auth-swagger.config.js +14 -7
  10. package/cjs/dtos/authentication.dto.js +114 -38
  11. package/cjs/dtos/index.js +0 -1
  12. package/cjs/dtos/user-permission.dto.js +28 -0
  13. package/cjs/dtos/user.dto.js +19 -4
  14. package/cjs/entities/index.js +5 -1
  15. package/cjs/entities/pending-registration.entity.js +125 -0
  16. package/cjs/entities/user-company-permission.entity.js +3 -9
  17. package/cjs/entities/user-token.entity.js +129 -0
  18. package/cjs/interceptors/clear-token.interceptor.js +10 -23
  19. package/cjs/interceptors/set-token.interceptor.js +15 -55
  20. package/cjs/interfaces/auth-email-provider.interface.js +45 -0
  21. package/cjs/interfaces/index.js +2 -0
  22. package/cjs/interfaces/user-enricher.interface.js +4 -0
  23. package/cjs/modules/auth.module.js +65 -143
  24. package/cjs/services/auth-config.service.js +25 -27
  25. package/cjs/services/auth-datasource.provider.js +13 -23
  26. package/cjs/services/auth-email.service.js +456 -0
  27. package/cjs/services/authentication.service.js +297 -349
  28. package/cjs/services/branch.service.js +9 -4
  29. package/cjs/services/company-selection-session.service.js +1 -1
  30. package/cjs/services/index.js +1 -0
  31. package/cjs/services/user-permission.service.js +43 -73
  32. package/cjs/services/user.service.js +184 -34
  33. package/cjs/strategies/jwt.strategy.js +44 -44
  34. package/cjs/validators/password.validator.js +45 -0
  35. package/config/auth.constants.d.ts +3 -0
  36. package/controllers/authentication.controller.d.ts +16 -10
  37. package/controllers/company-selection.controller.d.ts +6 -2
  38. package/controllers/user-permission.controller.d.ts +5 -4
  39. package/controllers/user.controller.d.ts +33 -0
  40. package/dtos/authentication.dto.d.ts +20 -6
  41. package/dtos/company-branch.dto.d.ts +0 -1
  42. package/dtos/company.dto.d.ts +0 -1
  43. package/dtos/index.d.ts +0 -1
  44. package/dtos/user-permission.dto.d.ts +4 -0
  45. package/dtos/user.dto.d.ts +1 -2
  46. package/entities/index.d.ts +7 -3
  47. package/entities/pending-registration.entity.d.ts +17 -0
  48. package/entities/user-company-permission.entity.d.ts +1 -3
  49. package/entities/user-token.entity.d.ts +15 -0
  50. package/fesm/config/auth.constants.js +6 -2
  51. package/fesm/controllers/authentication.controller.js +368 -27
  52. package/fesm/controllers/branch.controller.js +45 -2
  53. package/fesm/controllers/company-selection.controller.js +28 -21
  54. package/fesm/controllers/company.controller.js +45 -2
  55. package/fesm/controllers/user-permission.controller.js +84 -156
  56. package/fesm/controllers/user.controller.js +214 -10
  57. package/fesm/docs/auth-swagger.config.js +14 -7
  58. package/fesm/dtos/authentication.dto.js +101 -39
  59. package/fesm/dtos/index.js +0 -1
  60. package/fesm/dtos/user-permission.dto.js +28 -0
  61. package/fesm/dtos/user.dto.js +20 -5
  62. package/fesm/entities/index.js +7 -1
  63. package/fesm/entities/pending-registration.entity.js +115 -0
  64. package/fesm/entities/user-company-permission.entity.js +3 -9
  65. package/fesm/entities/user-token.entity.js +113 -0
  66. package/fesm/interceptors/clear-token.interceptor.js +9 -22
  67. package/fesm/interceptors/set-token.interceptor.js +14 -54
  68. package/fesm/interfaces/auth-email-provider.interface.js +38 -0
  69. package/fesm/interfaces/authentication.interface.js +1 -1
  70. package/fesm/interfaces/index.js +2 -0
  71. package/fesm/interfaces/user-enricher.interface.js +26 -0
  72. package/fesm/modules/auth.module.js +67 -145
  73. package/fesm/services/auth-config.service.js +26 -28
  74. package/fesm/services/auth-datasource.provider.js +14 -24
  75. package/fesm/services/auth-email.service.js +405 -0
  76. package/fesm/services/authentication.service.js +297 -349
  77. package/fesm/services/branch.service.js +9 -4
  78. package/fesm/services/company-selection-session.service.js +1 -1
  79. package/fesm/services/index.js +1 -0
  80. package/fesm/services/user-permission.service.js +44 -74
  81. package/fesm/services/user.service.js +186 -36
  82. package/fesm/strategies/jwt.strategy.js +44 -44
  83. package/fesm/validators/password.validator.js +48 -0
  84. package/interceptors/clear-token.interceptor.d.ts +0 -1
  85. package/interceptors/set-token.interceptor.d.ts +1 -1
  86. package/interfaces/auth-email-provider.interface.d.ts +6 -0
  87. package/interfaces/auth-module-options.interface.d.ts +4 -1
  88. package/interfaces/authentication.interface.d.ts +13 -3
  89. package/interfaces/index.d.ts +2 -0
  90. package/interfaces/user-enricher.interface.d.ts +64 -0
  91. package/interfaces/user.interface.d.ts +1 -0
  92. package/modules/auth.module.d.ts +6 -3
  93. package/package.json +4 -4
  94. package/services/auth-config.service.d.ts +7 -8
  95. package/services/auth-datasource.provider.d.ts +2 -4
  96. package/services/auth-email.service.d.ts +54 -0
  97. package/services/authentication.service.d.ts +27 -16
  98. package/services/company-selection-session.service.d.ts +1 -1
  99. package/services/index.d.ts +1 -0
  100. package/services/user-permission.service.d.ts +6 -9
  101. package/services/user.service.d.ts +19 -3
  102. package/strategies/jwt.strategy.d.ts +4 -1
  103. package/validators/password.validator.d.ts +10 -0
  104. package/cjs/dtos/user-company-permission.dto.js +0 -110
  105. package/dtos/user-company-permission.dto.d.ts +0 -10
  106. package/fesm/dtos/user-company-permission.dto.js +0 -98
@@ -0,0 +1,129 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", {
3
+ value: true
4
+ });
5
+ function _export(target, all) {
6
+ for(var name in all)Object.defineProperty(target, name, {
7
+ enumerable: true,
8
+ get: Object.getOwnPropertyDescriptor(all, name).get
9
+ });
10
+ }
11
+ _export(exports, {
12
+ get TokenType () {
13
+ return TokenType;
14
+ },
15
+ get UserToken () {
16
+ return UserToken;
17
+ }
18
+ });
19
+ const _typeorm = require("typeorm");
20
+ function _define_property(obj, key, value) {
21
+ if (key in obj) {
22
+ Object.defineProperty(obj, key, {
23
+ value: value,
24
+ enumerable: true,
25
+ configurable: true,
26
+ writable: true
27
+ });
28
+ } else {
29
+ obj[key] = value;
30
+ }
31
+ return obj;
32
+ }
33
+ function _ts_decorate(decorators, target, key, desc) {
34
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
35
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
36
+ else for(var i = decorators.length - 1; i >= 0; i--)if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
37
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
38
+ }
39
+ function _ts_metadata(k, v) {
40
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
41
+ }
42
+ var TokenType = /*#__PURE__*/ function(TokenType) {
43
+ TokenType["PASSWORD_RESET"] = "password_reset";
44
+ TokenType["EMAIL_VERIFICATION"] = "email_verification";
45
+ TokenType["EMAIL_CHANGE"] = "email_change";
46
+ return TokenType;
47
+ }({});
48
+ let UserToken = class UserToken {
49
+ constructor(){
50
+ _define_property(this, "id", void 0);
51
+ _define_property(this, "userId", void 0);
52
+ _define_property(this, "type", void 0);
53
+ _define_property(this, "token", void 0);
54
+ _define_property(this, "expiresAt", void 0);
55
+ _define_property(this, "usedAt", void 0);
56
+ _define_property(this, "metadata", void 0);
57
+ _define_property(this, "createdAt", void 0);
58
+ }
59
+ };
60
+ _ts_decorate([
61
+ (0, _typeorm.PrimaryGeneratedColumn)('uuid'),
62
+ _ts_metadata("design:type", String)
63
+ ], UserToken.prototype, "id", void 0);
64
+ _ts_decorate([
65
+ (0, _typeorm.Column)({
66
+ type: 'uuid',
67
+ name: 'user_id'
68
+ }),
69
+ _ts_metadata("design:type", String)
70
+ ], UserToken.prototype, "userId", void 0);
71
+ _ts_decorate([
72
+ (0, _typeorm.Column)({
73
+ type: 'varchar',
74
+ length: 32
75
+ }),
76
+ _ts_metadata("design:type", String)
77
+ ], UserToken.prototype, "type", void 0);
78
+ _ts_decorate([
79
+ (0, _typeorm.Column)({
80
+ type: 'varchar',
81
+ length: 64
82
+ }),
83
+ _ts_metadata("design:type", String)
84
+ ], UserToken.prototype, "token", void 0);
85
+ _ts_decorate([
86
+ (0, _typeorm.Column)({
87
+ type: 'timestamp',
88
+ name: 'expires_at'
89
+ }),
90
+ _ts_metadata("design:type", typeof Date === "undefined" ? Object : Date)
91
+ ], UserToken.prototype, "expiresAt", void 0);
92
+ _ts_decorate([
93
+ (0, _typeorm.Column)({
94
+ type: 'timestamp',
95
+ name: 'used_at',
96
+ nullable: true
97
+ }),
98
+ _ts_metadata("design:type", Object)
99
+ ], UserToken.prototype, "usedAt", void 0);
100
+ _ts_decorate([
101
+ (0, _typeorm.Column)({
102
+ type: 'varchar',
103
+ length: 255,
104
+ nullable: true
105
+ }),
106
+ _ts_metadata("design:type", Object)
107
+ ], UserToken.prototype, "metadata", void 0);
108
+ _ts_decorate([
109
+ (0, _typeorm.CreateDateColumn)({
110
+ type: 'timestamp',
111
+ name: 'created_at'
112
+ }),
113
+ _ts_metadata("design:type", typeof Date === "undefined" ? Object : Date)
114
+ ], UserToken.prototype, "createdAt", void 0);
115
+ UserToken = _ts_decorate([
116
+ (0, _typeorm.Entity)('user_tokens'),
117
+ (0, _typeorm.Index)('IDX_user_token_token', [
118
+ 'token'
119
+ ], {
120
+ unique: true
121
+ }),
122
+ (0, _typeorm.Index)('IDX_user_token_user_type', [
123
+ 'userId',
124
+ 'type'
125
+ ]),
126
+ (0, _typeorm.Index)('IDX_user_token_expires', [
127
+ 'expiresAt'
128
+ ])
129
+ ], UserToken);
@@ -8,8 +8,10 @@ Object.defineProperty(exports, "ClearToken", {
8
8
  return ClearToken;
9
9
  }
10
10
  });
11
+ const _utils = require("@flusys/nestjs-shared/utils");
11
12
  const _common = require("@nestjs/common");
12
13
  const _rxjs = require("rxjs");
14
+ const _config = require("../config");
13
15
  const _authconfigservice = require("../services/auth-config.service");
14
16
  function _define_property(obj, key, value) {
15
17
  if (key in obj) {
@@ -38,39 +40,24 @@ function _ts_param(paramIndex, decorator) {
38
40
  decorator(target, key, paramIndex);
39
41
  };
40
42
  }
41
- const DEFAULT_COOKIE_NAME = 'fsn_refresh_token';
42
43
  let ClearToken = class ClearToken {
43
44
  get cookieName() {
44
- return this.authConfig?.getRefreshTokenCookieName() ?? DEFAULT_COOKIE_NAME;
45
+ return this.authConfig?.getRefreshTokenCookieName() ?? _config.DEFAULT_COOKIE_NAME;
45
46
  }
46
47
  intercept(context, next) {
47
48
  const req = context.switchToHttp().getRequest();
48
49
  const res = context.switchToHttp().getResponse();
49
50
  return next.handle().pipe((0, _rxjs.map)((value)=>{
50
- // Clear the refresh token cookie
51
- this.clearRefreshTokenCookie(req, res);
51
+ if ((0, _utils.isBrowserRequest)(req)) {
52
+ res.clearCookie(this.cookieName, {
53
+ httpOnly: true,
54
+ path: '/',
55
+ ...(0, _utils.buildCookieOptions)(req)
56
+ });
57
+ }
52
58
  return value;
53
59
  }));
54
60
  }
55
- /**
56
- * Clear refresh token cookie
57
- */ clearRefreshTokenCookie(req, res) {
58
- const origin = req.headers.origin || '';
59
- const hostname = req.hostname || '';
60
- const isHttps = origin.startsWith('https://') || req.secure;
61
- let cookieDomain = hostname;
62
- const domainParts = hostname.split('.');
63
- if (domainParts.length > 2) {
64
- cookieDomain = '.' + domainParts.slice(-2).join('.');
65
- }
66
- res.clearCookie(this.cookieName, {
67
- httpOnly: true,
68
- secure: isHttps,
69
- sameSite: isHttps ? 'strict' : 'lax',
70
- domain: cookieDomain,
71
- path: '/'
72
- });
73
- }
74
61
  constructor(authConfig){
75
62
  _define_property(this, "authConfig", void 0);
76
63
  this.authConfig = authConfig;
@@ -8,9 +8,11 @@ Object.defineProperty(exports, "SetToken", {
8
8
  return SetToken;
9
9
  }
10
10
  });
11
+ const _utils = require("@flusys/nestjs-shared/utils");
11
12
  const _common = require("@nestjs/common");
12
13
  const _buffer = require("buffer");
13
14
  const _rxjs = require("rxjs");
15
+ const _config = require("../config");
14
16
  const _authconfigservice = require("../services/auth-config.service");
15
17
  function _define_property(obj, key, value) {
16
18
  if (key in obj) {
@@ -39,80 +41,37 @@ function _ts_param(paramIndex, decorator) {
39
41
  decorator(target, key, paramIndex);
40
42
  };
41
43
  }
42
- const DEFAULT_COOKIE_NAME = 'fsn_refresh_token';
43
- const MAX_COOKIE_BYTES = 3500;
44
44
  let SetToken = class SetToken {
45
45
  get cookieName() {
46
- return this.authConfig?.getRefreshTokenCookieName() ?? DEFAULT_COOKIE_NAME;
46
+ return this.authConfig?.getRefreshTokenCookieName() ?? _config.DEFAULT_COOKIE_NAME;
47
+ }
48
+ get maxAgeMs() {
49
+ return (0, _utils.parseDurationToMs)(this.authConfig?.getRefreshTokenExpiration() ?? '7d');
47
50
  }
48
51
  intercept(context, next) {
49
52
  const req = context.switchToHttp().getRequest();
50
53
  const res = context.switchToHttp().getResponse();
51
54
  return next.handle().pipe((0, _rxjs.map)((value)=>{
52
- // Skip if no refreshToken in response
53
- if (!value || !value.refreshToken) {
54
- return value;
55
- }
56
- const isBrowser = this.isBrowserRequest(req);
57
- const tokenValue = value.refreshToken;
58
- if (isBrowser) {
59
- // Browser: Set cookie and remove from response body
60
- this.setRefreshTokenCookie(req, res, tokenValue);
61
- // Return response without refreshToken for browsers
55
+ if (!value?.refreshToken) return value;
56
+ if ((0, _utils.isBrowserRequest)(req)) {
57
+ this.setRefreshTokenCookie(req, res, value.refreshToken);
62
58
  const { refreshToken, ...responseWithoutToken } = value;
63
59
  return responseWithoutToken;
64
60
  }
65
- // API/Mobile: Keep refreshToken in response body
66
61
  return value;
67
62
  }), (0, _rxjs.catchError)((err)=>(0, _rxjs.throwError)(()=>err)));
68
63
  }
69
- /**
70
- * Detect if request is from a browser
71
- * Checks Accept header and custom X-Client-Type header
72
- */ isBrowserRequest(req) {
73
- // Check custom header first (allows explicit client identification)
74
- const clientType = req.headers['x-client-type'];
75
- if (clientType) {
76
- return clientType.toLowerCase() === 'browser' || clientType.toLowerCase() === 'web';
77
- }
78
- // Check Accept header - browsers typically include text/html
79
- const accept = req.headers['accept'] || '';
80
- if (accept.includes('text/html')) {
81
- return true;
82
- }
83
- // Check User-Agent for common browsers
84
- const userAgent = req.headers['user-agent'] || '';
85
- const browserPatterns = /mozilla|chrome|safari|firefox|edge|opera|msie/i;
86
- if (browserPatterns.test(userAgent) && !userAgent.includes('Postman')) {
87
- return true;
88
- }
89
- return false;
90
- }
91
- /**
92
- * Set refresh token in HTTP-only cookie
93
- */ setRefreshTokenCookie(req, res, tokenValue) {
94
- const origin = req.headers.origin || '';
95
- const hostname = req.hostname || '';
96
- const isHttps = origin.startsWith('https://') || req.secure;
97
- let cookieDomain = hostname;
98
- const domainParts = hostname.split('.');
99
- if (domainParts.length > 2) {
100
- cookieDomain = '.' + domainParts.slice(-2).join('.');
101
- }
102
- // Check cookie size
103
- const rawCookieString = `${this.cookieName}=${tokenValue}; HttpOnly; Domain=${cookieDomain}`;
64
+ setRefreshTokenCookie(req, res, tokenValue) {
65
+ const rawCookieString = `${this.cookieName}=${tokenValue}; HttpOnly`;
104
66
  const estimatedBytes = _buffer.Buffer.byteLength(rawCookieString, 'utf8');
105
- if (estimatedBytes > MAX_COOKIE_BYTES) {
67
+ if (estimatedBytes > _config.MAX_COOKIE_BYTES) {
106
68
  throw new _common.PayloadTooLargeException(`Refresh token too large (≈${estimatedBytes} bytes)`);
107
69
  }
108
- // Set HTTP-only secure cookie
109
70
  res.cookie(this.cookieName, tokenValue, {
110
71
  httpOnly: true,
111
- secure: isHttps,
112
- sameSite: isHttps ? 'strict' : 'lax',
113
- domain: cookieDomain,
114
72
  path: '/',
115
- maxAge: 7 * 24 * 60 * 60 * 1000
73
+ maxAge: this.maxAgeMs,
74
+ ...(0, _utils.buildCookieOptions)(req)
116
75
  });
117
76
  }
118
77
  constructor(authConfig){
@@ -123,6 +82,7 @@ let SetToken = class SetToken {
123
82
  SetToken = _ts_decorate([
124
83
  (0, _common.Injectable)(),
125
84
  _ts_param(0, (0, _common.Optional)()),
85
+ _ts_param(0, (0, _common.Inject)(_authconfigservice.AuthConfigService)),
126
86
  _ts_metadata("design:type", Function),
127
87
  _ts_metadata("design:paramtypes", [
128
88
  typeof _authconfigservice.AuthConfigService === "undefined" ? Object : _authconfigservice.AuthConfigService
@@ -0,0 +1,45 @@
1
+ /**
2
+ * Auth Email Provider Interface
3
+ *
4
+ * This interface defines the contract for email sending in the auth module.
5
+ * It allows auth to work independently of the email module.
6
+ *
7
+ * To use email features in auth:
8
+ * 1. Provide AUTH_EMAIL_PROVIDER in your app module
9
+ * 2. Implement IAuthEmailProvider using EmailSendService from nestjs-email
10
+ *
11
+ * @example
12
+ * ```typescript
13
+ * // In app.module.ts or a provider file
14
+ * {
15
+ * provide: AUTH_EMAIL_PROVIDER,
16
+ * useFactory: (emailSendService: EmailSendService) => ({
17
+ * sendPasswordResetEmail: async (email, token, resetUrl) => {
18
+ * await emailSendService.sendTemplateEmail({
19
+ * templateSlug: 'password-reset',
20
+ * to: email,
21
+ * variables: { resetUrl, token },
22
+ * });
23
+ * },
24
+ * sendVerificationEmail: async (email, token, verifyUrl) => {
25
+ * await emailSendService.sendTemplateEmail({
26
+ * templateSlug: 'email-verification',
27
+ * to: email,
28
+ * variables: { verifyUrl, token },
29
+ * });
30
+ * },
31
+ * }),
32
+ * inject: [EmailSendService],
33
+ * }
34
+ * ```
35
+ */ "use strict";
36
+ Object.defineProperty(exports, "__esModule", {
37
+ value: true
38
+ });
39
+ Object.defineProperty(exports, "AUTH_EMAIL_PROVIDER", {
40
+ enumerable: true,
41
+ get: function() {
42
+ return AUTH_EMAIL_PROVIDER;
43
+ }
44
+ });
45
+ const AUTH_EMAIL_PROVIDER = 'AUTH_EMAIL_PROVIDER';
@@ -3,9 +3,11 @@ Object.defineProperty(exports, "__esModule", {
3
3
  value: true
4
4
  });
5
5
  _export_star(require("./authentication.interface"), exports);
6
+ _export_star(require("./auth-email-provider.interface"), exports);
6
7
  _export_star(require("./company-branch.interface"), exports);
7
8
  _export_star(require("./company.interface"), exports);
8
9
  _export_star(require("./user.interface"), exports);
10
+ _export_star(require("./user-enricher.interface"), exports);
9
11
  _export_star(require("./auth-module-options.interface"), exports);
10
12
  function _export_star(from, to) {
11
13
  Object.keys(from).forEach(function(k) {
@@ -0,0 +1,4 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", {
3
+ value: true
4
+ });
@@ -12,16 +12,15 @@ const _modules = require("@flusys/nestjs-shared/modules");
12
12
  const _common = require("@nestjs/common");
13
13
  const _jwt = require("@nestjs/jwt");
14
14
  const _passport = require("@nestjs/passport");
15
- const _typeorm = require("@nestjs/typeorm");
16
- const _authconfigservice = require("../services/auth-config.service");
17
- const _authdatasourceprovider = require("../services/auth-datasource.provider");
15
+ const _guards = require("@flusys/nestjs-shared/guards");
18
16
  const _authconstants = require("../config/auth.constants");
19
17
  const _controllers = require("../controllers");
20
18
  const _entities = require("../entities");
21
- const _guards = require("@flusys/nestjs-shared/guards");
22
19
  const _cleartokeninterceptor = require("../interceptors/clear-token.interceptor");
23
20
  const _settokeninterceptor = require("../interceptors/set-token.interceptor");
24
21
  const _services = require("../services");
22
+ const _authconfigservice = require("../services/auth-config.service");
23
+ const _authdatasourceprovider = require("../services/auth-datasource.provider");
25
24
  const _jwtstrategy = require("../strategies/jwt.strategy");
26
25
  function _ts_decorate(decorators, target, key, desc) {
27
26
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
@@ -31,79 +30,42 @@ function _ts_decorate(decorators, target, key, desc) {
31
30
  }
32
31
  let AuthModule = class AuthModule {
33
32
  static forRoot(options) {
34
- return this.buildDynamicModule(options);
33
+ const optionsProvider = {
34
+ provide: _authconstants.AUTH_MODULE_OPTIONS,
35
+ useValue: options
36
+ };
37
+ return this.buildModule(options, [
38
+ optionsProvider,
39
+ ...options.providers ?? []
40
+ ]);
35
41
  }
36
- static forRootAsync(asyncOptions) {
37
- const { global = false, includeController = true, bootstrapAppConfig: { enableCompanyFeature } = {}, imports: externalImports = [] } = asyncOptions;
38
- const asyncProviders = this.createAsyncProviders(asyncOptions);
39
- // Build imports
40
- const imports = [
41
- ...externalImports,
42
- _passport.PassportModule.register({
43
- defaultStrategy: 'jwt'
44
- }),
45
- _jwt.JwtModule.register({}),
46
- _modules.CacheModule,
47
- _modules.UtilsModule
48
- ];
49
- // Build controllers based on configuration
50
- const controllers = [];
51
- if (includeController) {
52
- // Core authentication controller (always included)
53
- controllers.push(_controllers.AuthenticationController);
54
- // User controller (always included)
55
- controllers.push(_controllers.UserController);
56
- // Company feature controllers (conditional)
57
- if (enableCompanyFeature) {
58
- controllers.push(_controllers.CompanySelectionController, _controllers.CompanyController, _controllers.BranchController, _controllers.UserPermissionController);
59
- }
60
- }
61
- // Build providers
62
- const providers = [
42
+ static forRootAsync(options) {
43
+ const asyncProviders = this.createAsyncProviders(options);
44
+ return this.buildModule(options, [
63
45
  ...asyncProviders,
64
- // Config & Infrastructure
65
- _authconfigservice.AuthConfigService,
66
- _authdatasourceprovider.AuthDataSourceProvider,
67
- // Auth core
68
- _jwtstrategy.JwtStrategy,
69
- _guards.JwtAuthGuard,
70
- _services.AuthenticationService,
71
- // Interceptors
72
- _settokeninterceptor.SetToken,
73
- _cleartokeninterceptor.ClearToken,
74
- // Core services (always included)
75
- _services.UserService
76
- ];
77
- // Company feature services (conditional)
78
- if (enableCompanyFeature) {
79
- providers.push(_services.CompanySelectionSessionService, _services.CompanyService, _services.BranchService, _services.UserPermissionService);
80
- }
81
- // Build exports
82
- const exports1 = [
83
- _passport.PassportModule,
84
- _authconstants.AUTH_MODULE_OPTIONS,
85
- _authconfigservice.AuthConfigService,
86
- _authdatasourceprovider.AuthDataSourceProvider,
87
- _jwtstrategy.JwtStrategy,
88
- _guards.JwtAuthGuard,
89
- _services.AuthenticationService,
90
- _services.UserService
91
- ];
92
- if (enableCompanyFeature) {
93
- exports1.push(_services.CompanySelectionSessionService, _services.CompanyService, _services.BranchService, _services.UserPermissionService);
94
- }
46
+ ...options.providers ?? []
47
+ ], options.imports);
48
+ }
49
+ /** Build the dynamic module with shared logic */ static buildModule(options, providers, externalImports = []) {
50
+ const { global = false, includeController = true, bootstrapAppConfig } = options;
51
+ const enableCompanyFeature = bootstrapAppConfig?.enableCompanyFeature ?? false;
95
52
  return {
96
53
  module: AuthModule,
97
54
  global,
98
- imports,
99
- controllers,
100
- providers,
101
- exports: exports1
55
+ imports: [
56
+ ...externalImports,
57
+ ...this.buildImports()
58
+ ],
59
+ controllers: this.buildControllers(includeController, enableCompanyFeature),
60
+ providers: [
61
+ ...providers,
62
+ ...this.buildProviders(enableCompanyFeature)
63
+ ],
64
+ exports: this.buildExports(enableCompanyFeature)
102
65
  };
103
66
  }
104
- static buildDynamicModule(options) {
105
- const { bootstrapAppConfig: { enableCompanyFeature } = {}, includeController = true, global = false } = options;
106
- const imports = [
67
+ /** Common module imports */ static buildImports() {
68
+ return [
107
69
  _passport.PassportModule.register({
108
70
  defaultStrategy: 'jwt'
109
71
  }),
@@ -111,40 +73,36 @@ let AuthModule = class AuthModule {
111
73
  _modules.CacheModule,
112
74
  _modules.UtilsModule
113
75
  ];
114
- // Build controllers based on configuration
115
- const controllers = [];
116
- if (includeController) {
117
- // Core authentication controller (always included)
118
- controllers.push(_controllers.AuthenticationController);
119
- // User controller (always included)
120
- controllers.push(_controllers.UserController);
121
- // Company feature controllers (conditional)
122
- if (enableCompanyFeature) {
123
- controllers.push(_controllers.CompanySelectionController, _controllers.CompanyController, _controllers.BranchController, _controllers.UserPermissionController);
124
- }
76
+ }
77
+ /** Build controllers based on feature flags */ static buildControllers(includeController, enableCompanyFeature) {
78
+ if (!includeController) return [];
79
+ const controllers = [
80
+ _controllers.AuthenticationController,
81
+ _controllers.UserController
82
+ ];
83
+ if (enableCompanyFeature) {
84
+ controllers.push(_controllers.CompanySelectionController, _controllers.CompanyController, _controllers.BranchController, _controllers.UserPermissionController);
125
85
  }
86
+ return controllers;
87
+ }
88
+ /** Core providers (without AUTH_MODULE_OPTIONS - that's added separately) */ static buildProviders(enableCompanyFeature) {
126
89
  const providers = [
127
- {
128
- provide: _authconstants.AUTH_MODULE_OPTIONS,
129
- useValue: options
130
- },
131
- // Config & Infrastructure
132
90
  _authconfigservice.AuthConfigService,
133
91
  _authdatasourceprovider.AuthDataSourceProvider,
134
- // Auth core
135
92
  _jwtstrategy.JwtStrategy,
136
93
  _guards.JwtAuthGuard,
137
94
  _services.AuthenticationService,
138
- // Interceptors
95
+ _services.AuthEmailService,
139
96
  _settokeninterceptor.SetToken,
140
97
  _cleartokeninterceptor.ClearToken,
141
- // Core services (always included)
142
98
  _services.UserService
143
99
  ];
144
- // Company feature services (conditional)
145
100
  if (enableCompanyFeature) {
146
101
  providers.push(_services.CompanySelectionSessionService, _services.CompanyService, _services.BranchService, _services.UserPermissionService);
147
102
  }
103
+ return providers;
104
+ }
105
+ /** Build module exports */ static buildExports(enableCompanyFeature) {
148
106
  const exports1 = [
149
107
  _passport.PassportModule,
150
108
  _authconstants.AUTH_MODULE_OPTIONS,
@@ -153,21 +111,15 @@ let AuthModule = class AuthModule {
153
111
  _jwtstrategy.JwtStrategy,
154
112
  _guards.JwtAuthGuard,
155
113
  _services.AuthenticationService,
114
+ _services.AuthEmailService,
156
115
  _services.UserService
157
116
  ];
158
117
  if (enableCompanyFeature) {
159
118
  exports1.push(_services.CompanySelectionSessionService, _services.CompanyService, _services.BranchService, _services.UserPermissionService);
160
119
  }
161
- return {
162
- module: AuthModule,
163
- global,
164
- imports,
165
- controllers,
166
- providers,
167
- exports: exports1
168
- };
120
+ return exports1;
169
121
  }
170
- static createAsyncProviders(options) {
122
+ /** Create async providers for forRootAsync */ static createAsyncProviders(options) {
171
123
  const staticOptions = {
172
124
  global: options.global,
173
125
  includeController: options.includeController,
@@ -177,13 +129,10 @@ let AuthModule = class AuthModule {
177
129
  return [
178
130
  {
179
131
  provide: _authconstants.AUTH_MODULE_OPTIONS,
180
- useFactory: async (...args)=>{
181
- const config = await options.useFactory(...args);
182
- return {
132
+ useFactory: async (...args)=>({
183
133
  ...staticOptions,
184
- config
185
- };
186
- },
134
+ config: await options.useFactory(...args)
135
+ }),
187
136
  inject: options.inject || []
188
137
  }
189
138
  ];
@@ -196,13 +145,10 @@ let AuthModule = class AuthModule {
196
145
  },
197
146
  {
198
147
  provide: _authconstants.AUTH_MODULE_OPTIONS,
199
- useFactory: async (factory)=>{
200
- const config = await factory.createAuthOptions();
201
- return {
148
+ useFactory: async (factory)=>({
202
149
  ...staticOptions,
203
- config
204
- };
205
- },
150
+ config: await factory.createAuthOptions()
151
+ }),
206
152
  inject: [
207
153
  options.useClass
208
154
  ]
@@ -213,13 +159,10 @@ let AuthModule = class AuthModule {
213
159
  return [
214
160
  {
215
161
  provide: _authconstants.AUTH_MODULE_OPTIONS,
216
- useFactory: async (factory)=>{
217
- const config = await factory.createAuthOptions();
218
- return {
162
+ useFactory: async (factory)=>({
219
163
  ...staticOptions,
220
- config
221
- };
222
- },
164
+ config: await factory.createAuthOptions()
165
+ }),
223
166
  inject: [
224
167
  options.useExisting
225
168
  ]
@@ -233,35 +176,14 @@ let AuthModule = class AuthModule {
233
176
  }
234
177
  ];
235
178
  }
236
- /**
237
- * Create repository providers that use AuthDataSourceProvider
238
- * This replaces TypeOrmModule.forFeature() functionality
239
- * Note: Must be REQUEST-scoped since AuthDataSourceProvider is REQUEST-scoped
240
- */ static getRepositoryProviders(enableCompanyFeature) {
241
- const entities = this.getEntities(enableCompanyFeature);
242
- return entities.map((entity)=>({
243
- provide: (0, _typeorm.getRepositoryToken)(entity),
244
- scope: _common.Scope.REQUEST,
245
- useFactory: async (dataSourceProvider)=>{
246
- return await dataSourceProvider.getRepository(entity);
247
- },
248
- inject: [
249
- _authdatasourceprovider.AuthDataSourceProvider
250
- ]
251
- }));
252
- }
253
- static getEntities(enableCompanyFeature = false) {
254
- const coreEntities = [
255
- _entities.User
256
- ];
257
- const companyEntities = enableCompanyFeature ? [
179
+ /** Get auth entities based on feature flags */ static getEntities(enableCompanyFeature = false) {
180
+ return enableCompanyFeature ? [
181
+ _entities.User,
258
182
  _entities.Company,
259
183
  _entities.CompanyBranch,
260
184
  _entities.UserCompanyPermission
261
- ] : [];
262
- return [
263
- ...coreEntities,
264
- ...companyEntities
185
+ ] : [
186
+ _entities.User
265
187
  ];
266
188
  }
267
189
  };