@flusys/nestjs-auth 1.0.0-beta → 1.1.0-beta

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 (55) hide show
  1. package/cjs/config/auth.constants.js +4 -0
  2. package/cjs/controllers/authentication.controller.js +167 -5
  3. package/cjs/controllers/user.controller.js +151 -0
  4. package/cjs/dtos/authentication.dto.js +106 -3
  5. package/cjs/entities/index.js +5 -1
  6. package/cjs/entities/pending-registration.entity.js +125 -0
  7. package/cjs/entities/user-token.entity.js +129 -0
  8. package/cjs/interfaces/auth-email-provider.interface.js +45 -0
  9. package/cjs/interfaces/index.js +2 -0
  10. package/cjs/interfaces/user-enricher.interface.js +4 -0
  11. package/cjs/modules/auth.module.js +8 -2
  12. package/cjs/services/auth-config.service.js +4 -0
  13. package/cjs/services/auth-datasource.provider.js +4 -2
  14. package/cjs/services/auth-email.service.js +452 -0
  15. package/cjs/services/authentication.service.js +156 -37
  16. package/cjs/services/index.js +1 -0
  17. package/cjs/services/user.service.js +147 -11
  18. package/config/auth.constants.d.ts +1 -0
  19. package/controllers/authentication.controller.d.ts +13 -9
  20. package/controllers/user.controller.d.ts +27 -0
  21. package/dtos/authentication.dto.d.ts +21 -3
  22. package/dtos/user.dto.d.ts +1 -0
  23. package/entities/index.d.ts +7 -3
  24. package/entities/pending-registration.entity.d.ts +17 -0
  25. package/entities/user-token.entity.d.ts +15 -0
  26. package/fesm/config/auth.constants.js +11 -0
  27. package/fesm/controllers/authentication.controller.js +168 -6
  28. package/fesm/controllers/user.controller.js +151 -0
  29. package/fesm/dtos/authentication.dto.js +92 -3
  30. package/fesm/entities/index.js +7 -1
  31. package/fesm/entities/pending-registration.entity.js +115 -0
  32. package/fesm/entities/user-token.entity.js +113 -0
  33. package/fesm/interfaces/auth-email-provider.interface.js +38 -0
  34. package/fesm/interfaces/authentication.interface.js +1 -1
  35. package/fesm/interfaces/index.js +2 -0
  36. package/fesm/interfaces/user-enricher.interface.js +26 -0
  37. package/fesm/modules/auth.module.js +9 -3
  38. package/fesm/services/auth-config.service.js +4 -0
  39. package/fesm/services/auth-datasource.provider.js +4 -2
  40. package/fesm/services/auth-email.service.js +401 -0
  41. package/fesm/services/authentication.service.js +156 -37
  42. package/fesm/services/index.js +1 -0
  43. package/fesm/services/user.service.js +149 -13
  44. package/interfaces/auth-email-provider.interface.d.ts +6 -0
  45. package/interfaces/auth-module-options.interface.d.ts +4 -1
  46. package/interfaces/authentication.interface.d.ts +14 -0
  47. package/interfaces/index.d.ts +2 -0
  48. package/interfaces/user-enricher.interface.d.ts +67 -0
  49. package/interfaces/user.interface.d.ts +1 -0
  50. package/package.json +3 -3
  51. package/services/auth-config.service.d.ts +1 -0
  52. package/services/auth-email.service.d.ts +50 -0
  53. package/services/authentication.service.d.ts +16 -4
  54. package/services/index.d.ts +1 -0
  55. package/services/user.service.d.ts +16 -3
@@ -503,16 +503,17 @@ _ts_decorate([
503
503
  _define_property(this, "company", void 0);
504
504
  _define_property(this, "branch", void 0);
505
505
  _define_property(this, "companyFeatureEnabled", void 0);
506
+ _define_property(this, "requiresEmailVerification", void 0);
506
507
  }
507
508
  }
508
509
  _ts_decorate([
509
- ApiProperty({
510
+ ApiPropertyOptional({
510
511
  example: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...'
511
512
  }),
512
513
  _ts_metadata("design:type", String)
513
514
  ], RegistrationResponseDto.prototype, "accessToken", void 0);
514
515
  _ts_decorate([
515
- ApiProperty({
516
+ ApiPropertyOptional({
516
517
  example: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...'
517
518
  }),
518
519
  _ts_metadata("design:type", String)
@@ -539,12 +540,19 @@ _ts_decorate([
539
540
  _ts_metadata("design:type", typeof BranchInfoDto === "undefined" ? Object : BranchInfoDto)
540
541
  ], RegistrationResponseDto.prototype, "branch", void 0);
541
542
  _ts_decorate([
542
- ApiProperty({
543
+ ApiPropertyOptional({
543
544
  example: true,
544
545
  description: 'Whether company feature is enabled'
545
546
  }),
546
547
  _ts_metadata("design:type", Boolean)
547
548
  ], RegistrationResponseDto.prototype, "companyFeatureEnabled", void 0);
549
+ _ts_decorate([
550
+ ApiPropertyOptional({
551
+ example: true,
552
+ description: 'Whether email verification is required'
553
+ }),
554
+ _ts_metadata("design:type", Boolean)
555
+ ], RegistrationResponseDto.prototype, "requiresEmailVerification", void 0);
548
556
  /** Me Response DTO - Returned by GET /auth/me (user data only, no tokens) */ export class MeResponseDto {
549
557
  constructor(){
550
558
  _define_property(this, "user", void 0);
@@ -619,3 +627,84 @@ _ts_decorate([
619
627
  }),
620
628
  _ts_metadata("design:type", Array)
621
629
  ], CompanySelectionResponseDto.prototype, "companies", void 0);
630
+ /** Login Response when email verification required */ export class LoginResponseRequiresEmailVerificationDto {
631
+ constructor(){
632
+ _define_property(this, "requiresEmailVerification", void 0);
633
+ _define_property(this, "email", void 0);
634
+ _define_property(this, "message", void 0);
635
+ }
636
+ }
637
+ _ts_decorate([
638
+ ApiProperty({
639
+ example: true
640
+ }),
641
+ _ts_metadata("design:type", Boolean)
642
+ ], LoginResponseRequiresEmailVerificationDto.prototype, "requiresEmailVerification", void 0);
643
+ _ts_decorate([
644
+ ApiProperty({
645
+ example: 'john@example.com'
646
+ }),
647
+ _ts_metadata("design:type", String)
648
+ ], LoginResponseRequiresEmailVerificationDto.prototype, "email", void 0);
649
+ _ts_decorate([
650
+ ApiProperty({
651
+ example: 'Please verify your email address before logging in.'
652
+ }),
653
+ _ts_metadata("design:type", String)
654
+ ], LoginResponseRequiresEmailVerificationDto.prototype, "message", void 0);
655
+ // Email Auth DTOs
656
+ /** Forgot Password Request DTO - Initiates password reset flow */ export class ForgotPasswordDto {
657
+ constructor(){
658
+ _define_property(this, "email", void 0);
659
+ }
660
+ }
661
+ _ts_decorate([
662
+ ApiProperty({
663
+ example: 'john@example.com',
664
+ description: 'Email address to send reset link to'
665
+ }),
666
+ IsEmail(),
667
+ IsNotEmpty(),
668
+ _ts_metadata("design:type", String)
669
+ ], ForgotPasswordDto.prototype, "email", void 0);
670
+ /** Reset Password Request DTO - Resets password using token */ export class ResetPasswordDto {
671
+ constructor(){
672
+ _define_property(this, "token", void 0);
673
+ _define_property(this, "newPassword", void 0);
674
+ }
675
+ }
676
+ _ts_decorate([
677
+ ApiProperty({
678
+ example: 'a1b2c3d4e5f6...',
679
+ description: 'Password reset token from email'
680
+ }),
681
+ IsString(),
682
+ IsNotEmpty(),
683
+ _ts_metadata("design:type", String)
684
+ ], ResetPasswordDto.prototype, "token", void 0);
685
+ _ts_decorate([
686
+ ApiProperty({
687
+ example: 'newSecurePassword123',
688
+ description: 'New password (min 6 chars)'
689
+ }),
690
+ IsString(),
691
+ IsNotEmpty(),
692
+ MinLength(6),
693
+ _ts_metadata("design:type", String)
694
+ ], ResetPasswordDto.prototype, "newPassword", void 0);
695
+ /** Verify Email Request DTO - Verifies email using token */ export class VerifyEmailDto {
696
+ constructor(){
697
+ _define_property(this, "token", void 0);
698
+ }
699
+ }
700
+ _ts_decorate([
701
+ ApiProperty({
702
+ example: 'a1b2c3d4e5f6...',
703
+ description: 'Email verification token from email'
704
+ }),
705
+ IsString(),
706
+ IsNotEmpty(),
707
+ _ts_metadata("design:type", String)
708
+ ], VerifyEmailDto.prototype, "token", void 0);
709
+ /** Resend Verification Email Request DTO - Same structure as ForgotPasswordDto */ export class ResendVerificationDto extends ForgotPasswordDto {
710
+ }
@@ -1,13 +1,19 @@
1
1
  export * from './company-branch.entity';
2
2
  export * from './company.entity';
3
+ export * from './pending-registration.entity';
3
4
  export { PermissionType, UserCompanyPermission } from './user-company-permission.entity';
4
5
  export * from './user.entity';
6
+ export * from './user-token.entity';
5
7
  import { CompanyBranch } from './company-branch.entity';
6
8
  import { Company } from './company.entity';
9
+ import { PendingRegistration } from './pending-registration.entity';
7
10
  import { UserCompanyPermission } from './user-company-permission.entity';
8
11
  import { User } from './user.entity';
12
+ import { UserToken } from './user-token.entity';
9
13
  export const CoreEntities = [
10
- User
14
+ User,
15
+ UserToken,
16
+ PendingRegistration
11
17
  ];
12
18
  export const CompanyEntities = [
13
19
  Company,
@@ -0,0 +1,115 @@
1
+ function _define_property(obj, key, value) {
2
+ if (key in obj) {
3
+ Object.defineProperty(obj, key, {
4
+ value: value,
5
+ enumerable: true,
6
+ configurable: true,
7
+ writable: true
8
+ });
9
+ } else {
10
+ obj[key] = value;
11
+ }
12
+ return obj;
13
+ }
14
+ function _ts_decorate(decorators, target, key, desc) {
15
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
16
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
17
+ 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;
18
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
19
+ }
20
+ function _ts_metadata(k, v) {
21
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
22
+ }
23
+ import { Column, CreateDateColumn, Entity, Index, PrimaryGeneratedColumn } from 'typeorm';
24
+ export class PendingRegistration {
25
+ constructor(){
26
+ _define_property(this, "id", void 0);
27
+ _define_property(this, "email", void 0);
28
+ _define_property(this, "name", void 0);
29
+ _define_property(this, "phone", void 0);
30
+ _define_property(this, "passwordHash", void 0);
31
+ _define_property(this, "token", void 0);
32
+ _define_property(this, "expiresAt", void 0);
33
+ _define_property(this, "companyData", void 0);
34
+ _define_property(this, "createdAt", void 0);
35
+ }
36
+ }
37
+ _ts_decorate([
38
+ PrimaryGeneratedColumn('uuid'),
39
+ _ts_metadata("design:type", String)
40
+ ], PendingRegistration.prototype, "id", void 0);
41
+ _ts_decorate([
42
+ Column({
43
+ type: 'varchar',
44
+ length: 255
45
+ }),
46
+ _ts_metadata("design:type", String)
47
+ ], PendingRegistration.prototype, "email", void 0);
48
+ _ts_decorate([
49
+ Column({
50
+ type: 'varchar',
51
+ length: 255,
52
+ nullable: true
53
+ }),
54
+ _ts_metadata("design:type", Object)
55
+ ], PendingRegistration.prototype, "name", void 0);
56
+ _ts_decorate([
57
+ Column({
58
+ type: 'varchar',
59
+ length: 255,
60
+ nullable: true
61
+ }),
62
+ _ts_metadata("design:type", Object)
63
+ ], PendingRegistration.prototype, "phone", void 0);
64
+ _ts_decorate([
65
+ Column({
66
+ type: 'text',
67
+ name: 'passwordHash'
68
+ }),
69
+ _ts_metadata("design:type", String)
70
+ ], PendingRegistration.prototype, "passwordHash", void 0);
71
+ _ts_decorate([
72
+ Column({
73
+ type: 'varchar',
74
+ length: 64
75
+ }),
76
+ _ts_metadata("design:type", String)
77
+ ], PendingRegistration.prototype, "token", void 0);
78
+ _ts_decorate([
79
+ Column({
80
+ type: 'timestamp',
81
+ name: 'expires_at'
82
+ }),
83
+ _ts_metadata("design:type", typeof Date === "undefined" ? Object : Date)
84
+ ], PendingRegistration.prototype, "expiresAt", void 0);
85
+ _ts_decorate([
86
+ Column({
87
+ type: 'json',
88
+ nullable: true,
89
+ name: 'company_data'
90
+ }),
91
+ _ts_metadata("design:type", Object)
92
+ ], PendingRegistration.prototype, "companyData", void 0);
93
+ _ts_decorate([
94
+ CreateDateColumn({
95
+ type: 'timestamp',
96
+ name: 'created_at'
97
+ }),
98
+ _ts_metadata("design:type", typeof Date === "undefined" ? Object : Date)
99
+ ], PendingRegistration.prototype, "createdAt", void 0);
100
+ PendingRegistration = _ts_decorate([
101
+ Entity('pending_registrations'),
102
+ Index('IDX_pending_reg_email', [
103
+ 'email'
104
+ ], {
105
+ unique: true
106
+ }),
107
+ Index('IDX_pending_reg_token', [
108
+ 'token'
109
+ ], {
110
+ unique: true
111
+ }),
112
+ Index('IDX_pending_reg_expires', [
113
+ 'expiresAt'
114
+ ])
115
+ ], PendingRegistration);
@@ -0,0 +1,113 @@
1
+ function _define_property(obj, key, value) {
2
+ if (key in obj) {
3
+ Object.defineProperty(obj, key, {
4
+ value: value,
5
+ enumerable: true,
6
+ configurable: true,
7
+ writable: true
8
+ });
9
+ } else {
10
+ obj[key] = value;
11
+ }
12
+ return obj;
13
+ }
14
+ function _ts_decorate(decorators, target, key, desc) {
15
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
16
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
17
+ 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;
18
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
19
+ }
20
+ function _ts_metadata(k, v) {
21
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
22
+ }
23
+ import { Column, CreateDateColumn, Entity, Index, PrimaryGeneratedColumn } from 'typeorm';
24
+ /**
25
+ * Token types for various user actions
26
+ */ export var TokenType = /*#__PURE__*/ function(TokenType) {
27
+ TokenType["PASSWORD_RESET"] = "password_reset";
28
+ TokenType["EMAIL_VERIFICATION"] = "email_verification";
29
+ TokenType["EMAIL_CHANGE"] = "email_change";
30
+ return TokenType;
31
+ }({});
32
+ export class UserToken {
33
+ constructor(){
34
+ _define_property(this, "id", void 0);
35
+ _define_property(this, "userId", void 0);
36
+ _define_property(this, "type", void 0);
37
+ _define_property(this, "token", void 0);
38
+ _define_property(this, "expiresAt", void 0);
39
+ _define_property(this, "usedAt", void 0);
40
+ _define_property(this, "metadata", void 0);
41
+ _define_property(this, "createdAt", void 0);
42
+ }
43
+ }
44
+ _ts_decorate([
45
+ PrimaryGeneratedColumn('uuid'),
46
+ _ts_metadata("design:type", String)
47
+ ], UserToken.prototype, "id", void 0);
48
+ _ts_decorate([
49
+ Column({
50
+ type: 'uuid',
51
+ name: 'user_id'
52
+ }),
53
+ _ts_metadata("design:type", String)
54
+ ], UserToken.prototype, "userId", void 0);
55
+ _ts_decorate([
56
+ Column({
57
+ type: 'varchar',
58
+ length: 32
59
+ }),
60
+ _ts_metadata("design:type", String)
61
+ ], UserToken.prototype, "type", void 0);
62
+ _ts_decorate([
63
+ Column({
64
+ type: 'varchar',
65
+ length: 64
66
+ }),
67
+ _ts_metadata("design:type", String)
68
+ ], UserToken.prototype, "token", void 0);
69
+ _ts_decorate([
70
+ Column({
71
+ type: 'timestamp',
72
+ name: 'expires_at'
73
+ }),
74
+ _ts_metadata("design:type", typeof Date === "undefined" ? Object : Date)
75
+ ], UserToken.prototype, "expiresAt", void 0);
76
+ _ts_decorate([
77
+ Column({
78
+ type: 'timestamp',
79
+ name: 'used_at',
80
+ nullable: true
81
+ }),
82
+ _ts_metadata("design:type", Object)
83
+ ], UserToken.prototype, "usedAt", void 0);
84
+ _ts_decorate([
85
+ Column({
86
+ type: 'varchar',
87
+ length: 255,
88
+ nullable: true
89
+ }),
90
+ _ts_metadata("design:type", Object)
91
+ ], UserToken.prototype, "metadata", void 0);
92
+ _ts_decorate([
93
+ CreateDateColumn({
94
+ type: 'timestamp',
95
+ name: 'created_at'
96
+ }),
97
+ _ts_metadata("design:type", typeof Date === "undefined" ? Object : Date)
98
+ ], UserToken.prototype, "createdAt", void 0);
99
+ UserToken = _ts_decorate([
100
+ Entity('user_tokens'),
101
+ Index('IDX_user_token_token', [
102
+ 'token'
103
+ ], {
104
+ unique: true
105
+ }),
106
+ Index('IDX_user_token_user_type', [
107
+ 'userId',
108
+ 'type'
109
+ ]),
110
+ Index('IDX_user_token_expires', [
111
+ 'expiresAt'
112
+ ])
113
+ ], UserToken);
@@ -0,0 +1,38 @@
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
+ */ /**
36
+ * Injection token for auth email provider
37
+ * Use this to provide the email implementation
38
+ */ export const AUTH_EMAIL_PROVIDER = 'AUTH_EMAIL_PROVIDER';
@@ -1 +1 @@
1
- /** Login Response when company/branch selection is required */ export { };
1
+ /** Login Response when email verification is required */ export { };
@@ -1,5 +1,7 @@
1
1
  export * from './authentication.interface';
2
+ export * from './auth-email-provider.interface';
2
3
  export * from './company-branch.interface';
3
4
  export * from './company.interface';
4
5
  export * from './user.interface';
6
+ export * from './user-enricher.interface';
5
7
  export * from './auth-module-options.interface';
@@ -0,0 +1,26 @@
1
+ /**
2
+ * User Enricher Provider Interface
3
+ *
4
+ * Allows consuming applications to extend user list and profile
5
+ * without modifying the base nestjs-auth package.
6
+ *
7
+ * This follows the Provider Interface Pattern:
8
+ * - nestjs-auth defines the interface (this file)
9
+ * - Consuming apps implement the interface
10
+ * - nestjs-auth optionally injects the implementation
11
+ *
12
+ * @example
13
+ * // In your app module
14
+ * providers: [
15
+ * { provide: USER_ENRICHER, useClass: MyUserEnricher },
16
+ * ]
17
+ *
18
+ * // Your enricher implementation
19
+ * @Injectable()
20
+ * export class MyUserEnricher implements IUserEnricher {
21
+ * async enrichListQuery(query, user) {
22
+ * query.leftJoinAndSelect('user.department', 'department');
23
+ * return { extraFields: ['department.name'] };
24
+ * }
25
+ * }
26
+ */ export { };
@@ -17,14 +17,14 @@ import { Company, CompanyBranch, User, UserCompanyPermission } from '../entities
17
17
  import { JwtAuthGuard } from '@flusys/nestjs-shared/guards';
18
18
  import { ClearToken } from '../interceptors/clear-token.interceptor';
19
19
  import { SetToken } from '../interceptors/set-token.interceptor';
20
- import { AuthenticationService, BranchService, CompanySelectionSessionService, CompanyService, UserPermissionService, UserService } from '../services';
20
+ import { AuthEmailService, AuthenticationService, BranchService, CompanySelectionSessionService, CompanyService, UserPermissionService, UserService } from '../services';
21
21
  import { JwtStrategy } from '../strategies/jwt.strategy';
22
22
  export class AuthModule {
23
23
  static forRoot(options) {
24
24
  return this.buildDynamicModule(options);
25
25
  }
26
26
  static forRootAsync(asyncOptions) {
27
- const { global = false, includeController = true, bootstrapAppConfig: { enableCompanyFeature } = {}, imports: externalImports = [] } = asyncOptions;
27
+ const { global = false, includeController = true, bootstrapAppConfig: { enableCompanyFeature } = {}, imports: externalImports = [], providers: additionalProviders = [] } = asyncOptions;
28
28
  const asyncProviders = this.createAsyncProviders(asyncOptions);
29
29
  // Build imports
30
30
  const imports = [
@@ -51,6 +51,7 @@ export class AuthModule {
51
51
  // Build providers
52
52
  const providers = [
53
53
  ...asyncProviders,
54
+ ...additionalProviders,
54
55
  // Config & Infrastructure
55
56
  AuthConfigService,
56
57
  AuthDataSourceProvider,
@@ -58,6 +59,7 @@ export class AuthModule {
58
59
  JwtStrategy,
59
60
  JwtAuthGuard,
60
61
  AuthenticationService,
62
+ AuthEmailService,
61
63
  // Interceptors
62
64
  SetToken,
63
65
  ClearToken,
@@ -77,6 +79,7 @@ export class AuthModule {
77
79
  JwtStrategy,
78
80
  JwtAuthGuard,
79
81
  AuthenticationService,
82
+ AuthEmailService,
80
83
  UserService
81
84
  ];
82
85
  if (enableCompanyFeature) {
@@ -92,7 +95,7 @@ export class AuthModule {
92
95
  };
93
96
  }
94
97
  static buildDynamicModule(options) {
95
- const { bootstrapAppConfig: { enableCompanyFeature } = {}, includeController = true, global = false } = options;
98
+ const { bootstrapAppConfig: { enableCompanyFeature } = {}, includeController = true, global = false, providers: additionalProviders = [] } = options;
96
99
  const imports = [
97
100
  PassportModule.register({
98
101
  defaultStrategy: 'jwt'
@@ -118,6 +121,7 @@ export class AuthModule {
118
121
  provide: AUTH_MODULE_OPTIONS,
119
122
  useValue: options
120
123
  },
124
+ ...additionalProviders,
121
125
  // Config & Infrastructure
122
126
  AuthConfigService,
123
127
  AuthDataSourceProvider,
@@ -125,6 +129,7 @@ export class AuthModule {
125
129
  JwtStrategy,
126
130
  JwtAuthGuard,
127
131
  AuthenticationService,
132
+ AuthEmailService,
128
133
  // Interceptors
129
134
  SetToken,
130
135
  ClearToken,
@@ -143,6 +148,7 @@ export class AuthModule {
143
148
  JwtStrategy,
144
149
  JwtAuthGuard,
145
150
  AuthenticationService,
151
+ AuthEmailService,
146
152
  UserService
147
153
  ];
148
154
  if (enableCompanyFeature) {
@@ -56,6 +56,10 @@ export class AuthConfigService {
56
56
  /** Get refresh token cookie name */ getRefreshTokenCookieName() {
57
57
  return this.config.refreshTokenCookieName ?? 'fsn_refresh_token';
58
58
  }
59
+ // Frontend Configuration
60
+ /** Get frontend URL for email links */ getFrontendUrl() {
61
+ return this.config.frontendUrl;
62
+ }
59
63
  // Database Configuration
60
64
  /** Get default database config */ getDefaultDatabaseConfig() {
61
65
  return this.config.defaultDatabaseConfig ?? this.config.tenantDefaultDatabaseConfig;
@@ -102,9 +102,11 @@ export class AuthDataSourceProvider extends MultiTenantDataSourceService {
102
102
  // Entity Management
103
103
  /** Get auth entities based on company feature flag */ async getAuthEntities(enableCompanyFeature) {
104
104
  const enable = enableCompanyFeature ?? this.getEnableCompanyFeature();
105
- const { Company, CompanyBranch, User, UserCompanyPermission } = await import('../entities');
105
+ const { Company, CompanyBranch, User, UserCompanyPermission, UserToken, PendingRegistration } = await import('../entities');
106
106
  const coreEntities = [
107
- User
107
+ User,
108
+ UserToken,
109
+ PendingRegistration
108
110
  ];
109
111
  const companyEntities = enable ? [
110
112
  Company,