@flusys/nestjs-auth 1.0.1 → 1.1.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.
@@ -46,9 +46,9 @@ let AuthModule = class AuthModule {
46
46
  ...options.providers ?? []
47
47
  ], options.imports);
48
48
  }
49
- /** Build the dynamic module with shared logic */ static buildModule(options, providers, externalImports = []) {
49
+ static buildModule(options, providers, externalImports = []) {
50
50
  const { global = false, includeController = true, bootstrapAppConfig } = options;
51
- const enableCompanyFeature = bootstrapAppConfig?.enableCompanyFeature ?? false;
51
+ const featureFlags = this.getFeatureFlags(bootstrapAppConfig);
52
52
  return {
53
53
  module: AuthModule,
54
54
  global,
@@ -56,15 +56,21 @@ let AuthModule = class AuthModule {
56
56
  ...externalImports,
57
57
  ...this.buildImports()
58
58
  ],
59
- controllers: this.buildControllers(includeController, enableCompanyFeature),
59
+ controllers: this.buildControllers(includeController, featureFlags),
60
60
  providers: [
61
61
  ...providers,
62
- ...this.buildProviders(enableCompanyFeature)
62
+ ...this.buildProviders(featureFlags)
63
63
  ],
64
- exports: this.buildExports(enableCompanyFeature)
64
+ exports: this.buildExports(featureFlags)
65
65
  };
66
66
  }
67
- /** Common module imports */ static buildImports() {
67
+ static getFeatureFlags(bootstrapAppConfig) {
68
+ return {
69
+ enableCompanyFeature: bootstrapAppConfig?.enableCompanyFeature ?? false,
70
+ enableEmailVerification: bootstrapAppConfig?.enableEmailVerification ?? true
71
+ };
72
+ }
73
+ static buildImports() {
68
74
  return [
69
75
  _passport.PassportModule.register({
70
76
  defaultStrategy: 'jwt'
@@ -74,35 +80,40 @@ let AuthModule = class AuthModule {
74
80
  _modules.UtilsModule
75
81
  ];
76
82
  }
77
- /** Build controllers based on feature flags */ static buildControllers(includeController, enableCompanyFeature) {
83
+ static buildControllers(includeController, flags) {
78
84
  if (!includeController) return [];
79
85
  const controllers = [
80
86
  _controllers.AuthenticationController,
81
87
  _controllers.UserController
82
88
  ];
83
- if (enableCompanyFeature) {
89
+ if (flags.enableEmailVerification) {
90
+ controllers.push(_controllers.EmailVerificationController);
91
+ }
92
+ if (flags.enableCompanyFeature) {
84
93
  controllers.push(_controllers.CompanySelectionController, _controllers.CompanyController, _controllers.BranchController, _controllers.UserPermissionController);
85
94
  }
86
95
  return controllers;
87
96
  }
88
- /** Core providers (without AUTH_MODULE_OPTIONS - that's added separately) */ static buildProviders(enableCompanyFeature) {
97
+ static buildProviders(flags) {
89
98
  const providers = [
90
99
  _authconfigservice.AuthConfigService,
91
100
  _authdatasourceprovider.AuthDataSourceProvider,
92
101
  _jwtstrategy.JwtStrategy,
93
102
  _guards.JwtAuthGuard,
94
103
  _services.AuthenticationService,
95
- _services.AuthEmailService,
96
104
  _settokeninterceptor.SetToken,
97
105
  _cleartokeninterceptor.ClearToken,
98
106
  _services.UserService
99
107
  ];
100
- if (enableCompanyFeature) {
108
+ if (flags.enableEmailVerification) {
109
+ providers.push(_services.AuthEmailService);
110
+ }
111
+ if (flags.enableCompanyFeature) {
101
112
  providers.push(_services.CompanySelectionSessionService, _services.CompanyService, _services.BranchService, _services.UserPermissionService);
102
113
  }
103
114
  return providers;
104
115
  }
105
- /** Build module exports */ static buildExports(enableCompanyFeature) {
116
+ static buildExports(flags) {
106
117
  const exports1 = [
107
118
  _passport.PassportModule,
108
119
  _authconstants.AUTH_MODULE_OPTIONS,
@@ -111,15 +122,17 @@ let AuthModule = class AuthModule {
111
122
  _jwtstrategy.JwtStrategy,
112
123
  _guards.JwtAuthGuard,
113
124
  _services.AuthenticationService,
114
- _services.AuthEmailService,
115
125
  _services.UserService
116
126
  ];
117
- if (enableCompanyFeature) {
127
+ if (flags.enableEmailVerification) {
128
+ exports1.push(_services.AuthEmailService);
129
+ }
130
+ if (flags.enableCompanyFeature) {
118
131
  exports1.push(_services.CompanySelectionSessionService, _services.CompanyService, _services.BranchService, _services.UserPermissionService);
119
132
  }
120
133
  return exports1;
121
134
  }
122
- /** Create async providers for forRootAsync */ static createAsyncProviders(options) {
135
+ static createAsyncProviders(options) {
123
136
  const staticOptions = {
124
137
  global: options.global,
125
138
  includeController: options.includeController,
@@ -176,15 +189,11 @@ let AuthModule = class AuthModule {
176
189
  }
177
190
  ];
178
191
  }
179
- /** Get auth entities based on feature flags */ static getEntities(enableCompanyFeature = false) {
180
- return enableCompanyFeature ? [
181
- _entities.User,
182
- _entities.Company,
183
- _entities.CompanyBranch,
184
- _entities.UserCompanyPermission
185
- ] : [
186
- _entities.User
187
- ];
192
+ static getEntities(config) {
193
+ return (0, _entities.getEntitiesByConfig)({
194
+ enableCompanyFeature: config.enableCompanyFeature ?? false,
195
+ enableEmailVerification: config.enableEmailVerification ?? true
196
+ });
188
197
  }
189
198
  };
190
199
  AuthModule = _ts_decorate([
@@ -8,6 +8,7 @@ Object.defineProperty(exports, "AuthConfigService", {
8
8
  return AuthConfigService;
9
9
  }
10
10
  });
11
+ const _config = require("@flusys/nestjs-core/config");
11
12
  const _common = require("@nestjs/common");
12
13
  const _authconstants = require("../config/auth.constants");
13
14
  const _authmoduleoptionsinterface = require("../interfaces/auth-module-options.interface");
@@ -50,21 +51,24 @@ let AuthConfigService = class AuthConfigService {
50
51
  isCompanyFeatureEnabled() {
51
52
  return this.options.bootstrapAppConfig?.enableCompanyFeature ?? false;
52
53
  }
54
+ isEmailVerificationEnabled() {
55
+ return this.options.bootstrapAppConfig?.enableEmailVerification ?? true;
56
+ }
53
57
  // JWT Configuration
54
- /** Get JWT secret key */ getJwtSecret() {
58
+ getJwtSecret() {
55
59
  if (!this.config.jwtSecret) {
56
60
  throw new _common.InternalServerErrorException('[AuthModule] JWT_SECRET is required - set via environment or module config');
57
61
  }
58
62
  return this.config.jwtSecret;
59
63
  }
60
- /** Get JWT expiration time */ getJwtExpiration() {
64
+ getJwtExpiration() {
61
65
  return this.config.jwtExpiration ?? '1h';
62
66
  }
63
- /** Get refresh token secret key */ getRefreshTokenSecret() {
67
+ getRefreshTokenSecret() {
64
68
  if (this.config.refreshTokenSecret) {
65
69
  return this.config.refreshTokenSecret;
66
70
  }
67
- if (process.env.NODE_ENV === 'production') {
71
+ if (_config.envConfig.isProduction()) {
68
72
  throw new _common.InternalServerErrorException('[AuthModule] REFRESH_TOKEN_SECRET is required in production - ' + 'using the same secret for access and refresh tokens is a security risk');
69
73
  }
70
74
  if (!this.refreshTokenSecretWarned) {
@@ -73,14 +77,14 @@ let AuthConfigService = class AuthConfigService {
73
77
  }
74
78
  return this.getJwtSecret();
75
79
  }
76
- /** Get refresh token expiration time */ getRefreshTokenExpiration() {
80
+ getRefreshTokenExpiration() {
77
81
  return this.config.refreshTokenExpiration ?? '7d';
78
82
  }
79
- /** Get refresh token cookie name */ getRefreshTokenCookieName() {
83
+ getRefreshTokenCookieName() {
80
84
  return this.config.refreshTokenCookieName ?? 'fsn_refresh_token';
81
85
  }
82
86
  // Frontend Configuration
83
- /** Get frontend URL for email links */ getFrontendUrl() {
87
+ getFrontendUrl() {
84
88
  return this.config.frontendUrl;
85
89
  }
86
90
  constructor(injectedOptions){
@@ -83,8 +83,7 @@ function _ts_param(paramIndex, decorator) {
83
83
  };
84
84
  }
85
85
  let AuthDataSourceProvider = class AuthDataSourceProvider extends _modules.MultiTenantDataSourceService {
86
- // Override Static Cache Access Methods
87
- /** Override to access Auth-specific static properties */ async getSingleDataSource() {
86
+ async getSingleDataSource() {
88
87
  if (!AuthDataSourceProvider.singleDataSource) {
89
88
  if (AuthDataSourceProvider.singleConnectionLock) {
90
89
  return AuthDataSourceProvider.singleConnectionLock;
@@ -108,18 +107,15 @@ let AuthDataSourceProvider = class AuthDataSourceProvider extends _modules.Multi
108
107
  }
109
108
  return AuthDataSourceProvider.singleDataSource;
110
109
  }
111
- /** Override to use Auth-specific static cache for tenant connections */ async getOrCreateTenantConnection(tenant) {
112
- // Return existing initialized connection from Auth-specific cache
110
+ async getOrCreateTenantConnection(tenant) {
113
111
  const existing = AuthDataSourceProvider.tenantConnections.get(tenant.id);
114
112
  if (existing?.isInitialized) {
115
113
  return existing;
116
114
  }
117
- // If another request is creating this tenant's connection, wait for it
118
115
  const pendingConnection = AuthDataSourceProvider.connectionLocks.get(tenant.id);
119
116
  if (pendingConnection) {
120
117
  return pendingConnection;
121
118
  }
122
- // Create connection with lock to prevent race conditions
123
119
  const config = this.buildTenantDatabaseConfig(tenant);
124
120
  const connectionPromise = this.createDataSourceFromConfig(config);
125
121
  AuthDataSourceProvider.connectionLocks.set(tenant.id, connectionPromise);
@@ -131,8 +127,7 @@ let AuthDataSourceProvider = class AuthDataSourceProvider extends _modules.Multi
131
127
  AuthDataSourceProvider.connectionLocks.delete(tenant.id);
132
128
  }
133
129
  }
134
- // Factory Methods
135
- /** Build parent options from AuthModuleOptions */ static buildParentOptions(options) {
130
+ static buildParentOptions(options) {
136
131
  return {
137
132
  bootstrapAppConfig: options.bootstrapAppConfig,
138
133
  defaultDatabaseConfig: options.config?.defaultDatabaseConfig,
@@ -140,35 +135,28 @@ let AuthDataSourceProvider = class AuthDataSourceProvider extends _modules.Multi
140
135
  tenants: options.config?.tenants
141
136
  };
142
137
  }
143
- // Feature Flags
144
- /** Check if company feature is enabled (tenant-specific or global fallback) */ isCompanyFeatureEnabled(tenant) {
138
+ isCompanyFeatureEnabled(tenant) {
145
139
  const effectiveTenant = tenant ?? this.getCurrentTenant();
146
140
  return effectiveTenant?.enableCompanyFeature ?? this.authOptions.bootstrapAppConfig?.enableCompanyFeature ?? false;
147
141
  }
148
- // Entity Management
149
- /** Get auth entities based on company feature flag */ async getAuthEntities() {
150
- const { Company, CompanyBranch, User, UserCompanyPermission, UserToken, PendingRegistration } = await Promise.resolve().then(()=>/*#__PURE__*/ _interop_require_wildcard(require("../entities")));
151
- const coreEntities = [
152
- User,
153
- UserToken,
154
- PendingRegistration
155
- ];
156
- return this.isCompanyFeatureEnabled() ? [
157
- ...coreEntities,
158
- Company,
159
- CompanyBranch,
160
- UserCompanyPermission
161
- ] : coreEntities;
142
+ isEmailVerificationEnabled(tenant) {
143
+ const effectiveTenant = tenant ?? this.getCurrentTenant();
144
+ return effectiveTenant?.enableEmailVerification ?? this.authOptions.bootstrapAppConfig?.enableEmailVerification ?? true;
145
+ }
146
+ async getAuthEntities() {
147
+ const { getEntitiesByConfig } = await Promise.resolve().then(()=>/*#__PURE__*/ _interop_require_wildcard(require("../entities")));
148
+ return getEntitiesByConfig({
149
+ enableCompanyFeature: this.isCompanyFeatureEnabled(),
150
+ enableEmailVerification: this.isEmailVerificationEnabled()
151
+ });
162
152
  }
163
- // Overrides
164
- /** Override to dynamically set entities based on tenant config */ async createDataSourceFromConfig(config) {
153
+ async createDataSourceFromConfig(config) {
165
154
  return super.createDataSourceFromConfig(config, await this.getAuthEntities());
166
155
  }
167
156
  constructor(authOptions, request){
168
157
  super(AuthDataSourceProvider.buildParentOptions(authOptions), request), _define_property(this, "authOptions", void 0), _define_property(this, "logger", void 0), this.authOptions = authOptions, this.logger = new _common.Logger(AuthDataSourceProvider.name);
169
158
  }
170
159
  };
171
- // Override parent's static properties to have Auth-specific cache (isolated from IAM/Storage)
172
160
  _define_property(AuthDataSourceProvider, "tenantConnections", new Map());
173
161
  _define_property(AuthDataSourceProvider, "singleDataSource", null);
174
162
  _define_property(AuthDataSourceProvider, "tenantsRegistry", new Map());
@@ -93,9 +93,14 @@ function _ts_param(paramIndex, decorator) {
93
93
  }
94
94
  let AuthenticationService = class AuthenticationService {
95
95
  // Feature Flags
96
- /** Check if company feature is enabled (tenant-aware with global fallback) */ isCompanyFeatureEnabled() {
96
+ isCompanyFeatureEnabled() {
97
97
  return this.dataSourceProvider?.isCompanyFeatureEnabled() ?? this.authConfig.isCompanyFeatureEnabled();
98
98
  }
99
+ isEmailVerificationEnabled() {
100
+ const featureEnabled = this.dataSourceProvider?.isEmailVerificationEnabled() ?? this.authConfig.isEmailVerificationEnabled();
101
+ const providerAvailable = this.authEmailService?.isEmailEnabled() ?? false;
102
+ return featureEnabled && providerAvailable;
103
+ }
99
104
  // Repository Getters
100
105
  async getUserRepository() {
101
106
  if (!this.dataSourceProvider) {
@@ -118,7 +123,7 @@ let AuthenticationService = class AuthenticationService {
118
123
  // Login
119
124
  async login(email, password) {
120
125
  // Check for pending registration first (user registered but hasn't verified email yet)
121
- if (await this.authEmailService?.hasPendingRegistration(email)) {
126
+ if (this.isEmailVerificationEnabled() && await this.authEmailService.hasPendingRegistration(email)) {
122
127
  return {
123
128
  requiresEmailVerification: true,
124
129
  email,
@@ -129,7 +134,7 @@ let AuthenticationService = class AuthenticationService {
129
134
  if (!user.isActive) {
130
135
  throw new _common.UnauthorizedException('User account is deactivated');
131
136
  }
132
- if (this.authEmailService?.isEmailEnabled() && !user.emailVerified) {
137
+ if (this.isEmailVerificationEnabled() && !user.emailVerified) {
133
138
  return {
134
139
  requiresEmailVerification: true,
135
140
  email: user.email,
@@ -141,7 +146,7 @@ let AuthenticationService = class AuthenticationService {
141
146
  }
142
147
  return this.handleCompanyBasedLogin(user);
143
148
  }
144
- /** Handle login when company feature is enabled */ async handleCompanyBasedLogin(user) {
149
+ async handleCompanyBasedLogin(user) {
145
150
  const permissionRepository = await this.getPermissionRepository();
146
151
  const branchRepository = await this.getBranchRepository();
147
152
  if (!permissionRepository || !branchRepository) {
@@ -192,7 +197,7 @@ let AuthenticationService = class AuthenticationService {
192
197
  return await this.generateCompanySelectionResponse(user, companies, branches);
193
198
  }
194
199
  // Registration
195
- /** Register a new user. If email enabled, creates pending registration. Otherwise creates user directly. */ async register(dto, verifyUrlBase) {
200
+ async register(dto, verifyUrlBase) {
196
201
  const userRepository = await this.getUserRepository();
197
202
  const existingUser = await userRepository.findOne({
198
203
  where: {
@@ -208,7 +213,7 @@ let AuthenticationService = class AuthenticationService {
208
213
  throw new _common.BadRequestException('Registration failed due to email exists. Please try again or contact support.');
209
214
  }
210
215
  // If email verification is enabled, create pending registration instead of user
211
- if (this.authEmailService?.isEmailEnabled() && verifyUrlBase) {
216
+ if (this.isEmailVerificationEnabled() && verifyUrlBase) {
212
217
  const companyData = this.isCompanyFeatureEnabled() ? {
213
218
  companySlug: dto.companySlug,
214
219
  branchSlug: dto.branchSlug,
@@ -232,7 +237,7 @@ let AuthenticationService = class AuthenticationService {
232
237
  // No email verification - create user directly
233
238
  return this.createUserDirectly(dto);
234
239
  }
235
- /** Handle registration for existing user when company feature is enabled */ async handleExistingUserCompanyRegistration(existingUser, dto) {
240
+ async handleExistingUserCompanyRegistration(existingUser, dto) {
236
241
  if (!dto.companySlug && !dto.newCompanyName) {
237
242
  throw new _common.BadRequestException('Email already registered. Please login or provide a company to join/create.');
238
243
  }
@@ -264,7 +269,7 @@ let AuthenticationService = class AuthenticationService {
264
269
  }
265
270
  return this.processCompanyRegistration(existingUser, dto, true);
266
271
  }
267
- /** Create user directly (no email verification) */ async createUserDirectly(dto) {
272
+ async createUserDirectly(dto) {
268
273
  const userRepository = await this.getUserRepository();
269
274
  const hashedPassword = await _bcrypt.hash(dto.password, _config.BCRYPT_SALT_ROUNDS);
270
275
  const user = userRepository.create({
@@ -282,7 +287,7 @@ let AuthenticationService = class AuthenticationService {
282
287
  }
283
288
  return this.processCompanyRegistration(user, dto);
284
289
  }
285
- /** Create user from pending registration (after email verification) */ async createUserFromPendingRegistration(pending) {
290
+ async createUserFromPendingRegistration(pending) {
286
291
  const userRepository = await this.getUserRepository();
287
292
  const existingUser = await userRepository.findOne({
288
293
  where: {
@@ -307,7 +312,7 @@ let AuthenticationService = class AuthenticationService {
307
312
  }
308
313
  return this.generateRegistrationResponse(user);
309
314
  }
310
- /** Process company registration (join existing or create new) */ async processCompanyRegistration(user, data, throwOnUnavailable = false) {
315
+ async processCompanyRegistration(user, data, throwOnUnavailable = false) {
311
316
  const companyRepository = await this.getCompanyRepository();
312
317
  const branchRepository = await this.getBranchRepository();
313
318
  const permissionRepository = await this.getPermissionRepository();
@@ -322,7 +327,7 @@ let AuthenticationService = class AuthenticationService {
322
327
  }
323
328
  return this.generateRegistrationResponse(user);
324
329
  }
325
- /** Find existing company/branch or create new ones */ async findOrCreateCompanyAndBranch(data, companyRepo, branchRepo) {
330
+ async findOrCreateCompanyAndBranch(data, companyRepo, branchRepo) {
326
331
  if (data.companySlug) {
327
332
  const company = await companyRepo.findOne({
328
333
  where: {
@@ -386,7 +391,7 @@ let AuthenticationService = class AuthenticationService {
386
391
  branch: null
387
392
  };
388
393
  }
389
- /** Assign user to company and optionally branch */ async assignUserPermissions(userId, companyId, branchId, permissionRepo) {
394
+ async assignUserPermissions(userId, companyId, branchId, permissionRepo) {
390
395
  await permissionRepo.save(permissionRepo.create({
391
396
  userId,
392
397
  permissionType: _enums.PermissionType.COMPANY,
@@ -401,7 +406,7 @@ let AuthenticationService = class AuthenticationService {
401
406
  }
402
407
  }
403
408
  // Company/Branch Selection
404
- /** Select company and branch (step 2 of login). Frontend receives all options and user selects both. */ async select(sessionId, companyId, branchId) {
409
+ async select(sessionId, companyId, branchId) {
405
410
  this.ensureCompanyFeatureEnabled();
406
411
  if (!this.sessionService) {
407
412
  throw new _common.BadRequestException('Session service not available');
@@ -412,11 +417,11 @@ let AuthenticationService = class AuthenticationService {
412
417
  }
413
418
  return this.validateAndLoginWithCompany(session.userId, companyId, branchId);
414
419
  }
415
- /** Switch company/branch after login */ async switchCompany(userId, companyId, branchId) {
420
+ async switchCompany(userId, companyId, branchId) {
416
421
  this.ensureCompanyFeatureEnabled();
417
422
  return this.validateAndLoginWithCompany(userId, companyId, branchId);
418
423
  }
419
- /** Shared: Validate user access to company/branch and generate login response */ async validateAndLoginWithCompany(userId, companyId, branchId) {
424
+ async validateAndLoginWithCompany(userId, companyId, branchId) {
420
425
  const userRepository = await this.getUserRepository();
421
426
  const user = await userRepository.findOne({
422
427
  where: {
@@ -476,7 +481,7 @@ let AuthenticationService = class AuthenticationService {
476
481
  return this.generateLoginResponseWithCompany(user, company, branch);
477
482
  }
478
483
  // Token Management
479
- /** Refresh access token (with token rotation). Returns new access token and new refresh token. */ async refreshToken(refreshToken) {
484
+ async refreshToken(refreshToken) {
480
485
  try {
481
486
  const payload = this.jwtService.verify(refreshToken, {
482
487
  secret: this.authConfig.getRefreshTokenSecret()
@@ -510,7 +515,7 @@ let AuthenticationService = class AuthenticationService {
510
515
  throw new _common.UnauthorizedException('Invalid or expired refresh token');
511
516
  }
512
517
  }
513
- /** Change password */ async changePassword(userId, currentPassword, newPassword) {
518
+ async changePassword(userId, currentPassword, newPassword) {
514
519
  const userRepository = await this.getUserRepository();
515
520
  const user = await userRepository.findOne({
516
521
  where: {
@@ -524,7 +529,7 @@ let AuthenticationService = class AuthenticationService {
524
529
  user.password = await _bcrypt.hash(newPassword, _config.BCRYPT_SALT_ROUNDS);
525
530
  await userRepository.save(user);
526
531
  }
527
- /** Logout - Revokes all tokens. Stores revocation timestamp in cache. */ async logout(userId) {
532
+ async logout(userId) {
528
533
  if (!this.cacheManager) {
529
534
  // Cache is required for secure logout - tokens cannot be revoked without it
530
535
  this.logger.error(`SECURITY: Cache not available for logout (userId: ${userId}). ` + 'Token revocation failed - tokens will remain valid until expiry. ' + 'Configure cache (Redis) to enable proper token revocation.');
@@ -538,7 +543,7 @@ let AuthenticationService = class AuthenticationService {
538
543
  await this.cacheManager.set(cacheKey, revokedAt, ttlMs);
539
544
  this.logger.log(`User ${userId} logged out - all tokens revoked`);
540
545
  }
541
- /** Check if a token is revoked (issued before user's revocation timestamp) */ async isTokenRevoked(userId, tokenIssuedAt) {
546
+ async isTokenRevoked(userId, tokenIssuedAt) {
542
547
  if (!this.cacheManager || !tokenIssuedAt) {
543
548
  return false;
544
549
  }
@@ -550,7 +555,7 @@ let AuthenticationService = class AuthenticationService {
550
555
  // Token is revoked if it was issued before the revocation timestamp
551
556
  return tokenIssuedAt < revokedAt;
552
557
  }
553
- /** Parse JWT expiry string to milliseconds */ parseExpiryToMs(expiry) {
558
+ parseExpiryToMs(expiry) {
554
559
  const match = expiry.match(/^(\d+)([smhd])$/);
555
560
  if (!match) return 7 * 24 * 60 * 60 * 1000; // Default 7 days
556
561
  const value = parseInt(match[1], 10);
@@ -569,7 +574,7 @@ let AuthenticationService = class AuthenticationService {
569
574
  }
570
575
  }
571
576
  // Query Methods
572
- /** Get user's companies */ async getUserCompanies(userId) {
577
+ async getUserCompanies(userId) {
573
578
  this.ensureCompanyFeatureEnabled();
574
579
  const permissionRepository = await this.getPermissionRepository();
575
580
  const companyRepository = await this.getCompanyRepository();
@@ -590,7 +595,7 @@ let AuthenticationService = class AuthenticationService {
590
595
  active: true
591
596
  }).orderBy('c.name', 'ASC').getMany();
592
597
  }
593
- /** Get branches for a company that user has access to */ async getUserBranches(userId, companyId) {
598
+ async getUserBranches(userId, companyId) {
594
599
  this.ensureCompanyFeatureEnabled();
595
600
  const permissionRepository = await this.getPermissionRepository();
596
601
  const branchRepository = await this.getBranchRepository();
@@ -625,7 +630,7 @@ let AuthenticationService = class AuthenticationService {
625
630
  active: true
626
631
  }).orderBy('b.serial', 'ASC').addOrderBy('b.name', 'ASC').getMany();
627
632
  }
628
- /** Get company by ID */ async getCompanyById(companyId) {
633
+ async getCompanyById(companyId) {
629
634
  const companyRepository = await this.getCompanyRepository();
630
635
  if (!companyRepository) {
631
636
  return null;
@@ -636,7 +641,7 @@ let AuthenticationService = class AuthenticationService {
636
641
  }
637
642
  });
638
643
  }
639
- /** Get branch by ID */ async getBranchById(branchId) {
644
+ async getBranchById(branchId) {
640
645
  const branchRepository = await this.getBranchRepository();
641
646
  if (!branchRepository) {
642
647
  return null;
@@ -647,7 +652,7 @@ let AuthenticationService = class AuthenticationService {
647
652
  }
648
653
  });
649
654
  }
650
- /** Get user info for /auth/me endpoint. Returns user, company, and branch info (no tokens). */ async getUserInfo(userId, companyId, branchId) {
655
+ async getUserInfo(userId, companyId, branchId) {
651
656
  const userRepository = await this.getUserRepository();
652
657
  const user = await userRepository.findOne({
653
658
  where: {
@@ -694,7 +699,7 @@ let AuthenticationService = class AuthenticationService {
694
699
  return user;
695
700
  }
696
701
  // Response Generators
697
- /** Create user info object */ toUserInfo(user) {
702
+ toUserInfo(user) {
698
703
  return {
699
704
  id: user.id,
700
705
  email: user.email,
@@ -703,7 +708,7 @@ let AuthenticationService = class AuthenticationService {
703
708
  profilePictureId: user.profilePictureId ?? null
704
709
  };
705
710
  }
706
- /** Create company info object */ toCompanyInfo(company) {
711
+ toCompanyInfo(company) {
707
712
  return {
708
713
  id: company.id,
709
714
  name: company.name,
@@ -711,7 +716,7 @@ let AuthenticationService = class AuthenticationService {
711
716
  logoId: company.logoId ?? null
712
717
  };
713
718
  }
714
- /** Create branch info object */ toBranchInfo(branch) {
719
+ toBranchInfo(branch) {
715
720
  return {
716
721
  id: branch.id,
717
722
  name: branch.name,
@@ -719,7 +724,7 @@ let AuthenticationService = class AuthenticationService {
719
724
  logoId: branch.logoId ?? null
720
725
  };
721
726
  }
722
- /** Generate JWT tokens */ generateTokens(payload) {
727
+ generateTokens(payload) {
723
728
  const accessToken = this.jwtService.sign({
724
729
  ...payload,
725
730
  type: 'access'
@@ -1,18 +1,14 @@
1
1
  import { MessageResponseDto } from '@flusys/nestjs-shared/dtos';
2
2
  import { ILoggedUserInfo } from '@flusys/nestjs-shared/interfaces';
3
3
  import { Request } from 'express';
4
- import { ChangePasswordDto, CompanySelectionResponseDto, ForgotPasswordDto, LoginDto, LoginResponseDto, LoginResponseRequiresEmailVerificationDto, MeResponseDto, RefreshTokenDto, RegistrationDto, RegistrationResponseDto, ResendVerificationDto, ResetPasswordDto, VerifyEmailDto } from '../dtos/authentication.dto';
4
+ import { ChangePasswordDto, CompanySelectionResponseDto, LoginDto, LoginResponseDto, LoginResponseRequiresEmailVerificationDto, MeResponseDto, RefreshTokenDto, RegistrationDto, RegistrationResponseDto } from '../dtos/authentication.dto';
5
5
  import { AuthConfigService } from '../services/auth-config.service';
6
- import { AuthEmailService } from '../services/auth-email.service';
7
6
  import { AuthenticationService } from '../services/authentication.service';
8
7
  export declare class AuthenticationController {
9
8
  private readonly authService;
10
9
  private readonly authConfig?;
11
- private readonly authEmailService?;
12
- constructor(authService: AuthenticationService, authConfig?: AuthConfigService, authEmailService?: AuthEmailService);
10
+ constructor(authService: AuthenticationService, authConfig?: AuthConfigService);
13
11
  private buildAuthUrl;
14
- private get emailService();
15
- private get isEmailEnabled();
16
12
  login(loginDto: LoginDto): Promise<LoginResponseDto | CompanySelectionResponseDto | LoginResponseRequiresEmailVerificationDto>;
17
13
  register(req: Request, registrationDto: RegistrationDto): Promise<RegistrationResponseDto>;
18
14
  refreshToken(req: Request, refreshTokenDto: RefreshTokenDto): Promise<{
@@ -21,8 +17,4 @@ export declare class AuthenticationController {
21
17
  getCurrentUser(user: ILoggedUserInfo): Promise<MeResponseDto>;
22
18
  logout(userId: string): Promise<MessageResponseDto>;
23
19
  changePassword(userId: string, dto: ChangePasswordDto): Promise<MessageResponseDto>;
24
- forgotPassword(req: Request, dto: ForgotPasswordDto): Promise<MessageResponseDto>;
25
- resetPassword(dto: ResetPasswordDto): Promise<MessageResponseDto>;
26
- resendVerification(req: Request, dto: ResendVerificationDto): Promise<MessageResponseDto>;
27
- verifyEmail(dto: VerifyEmailDto): Promise<MessageResponseDto | RegistrationResponseDto>;
28
20
  }
@@ -0,0 +1,20 @@
1
+ import { MessageResponseDto } from '@flusys/nestjs-shared/dtos';
2
+ import { Request } from 'express';
3
+ import { ForgotPasswordDto, RegistrationResponseDto, ResendVerificationDto, ResetPasswordDto, VerifyEmailDto } from '../dtos/authentication.dto';
4
+ import { AuthConfigService } from '../services/auth-config.service';
5
+ import { AuthDataSourceProvider } from '../services/auth-datasource.provider';
6
+ import { AuthEmailService } from '../services/auth-email.service';
7
+ import { AuthenticationService } from '../services/authentication.service';
8
+ export declare class EmailVerificationController {
9
+ private readonly authService;
10
+ private readonly authEmailService;
11
+ private readonly authConfig;
12
+ private readonly dataSourceProvider;
13
+ constructor(authService: AuthenticationService, authEmailService: AuthEmailService, authConfig: AuthConfigService, dataSourceProvider: AuthDataSourceProvider);
14
+ private ensureEmailVerificationEnabled;
15
+ private buildAuthUrl;
16
+ forgotPassword(req: Request, dto: ForgotPasswordDto): Promise<MessageResponseDto>;
17
+ resetPassword(dto: ResetPasswordDto): Promise<MessageResponseDto>;
18
+ resendVerification(req: Request, dto: ResendVerificationDto): Promise<MessageResponseDto>;
19
+ verifyEmail(dto: VerifyEmailDto): Promise<MessageResponseDto | RegistrationResponseDto>;
20
+ }
@@ -1,5 +1,6 @@
1
1
  export * from './authentication.controller';
2
2
  export * from './company-selection.controller';
3
+ export * from './email-verification.controller';
3
4
  export * from './user.controller';
4
5
  export * from './company.controller';
5
6
  export * from './branch.controller';
@@ -4,13 +4,8 @@ export * from './pending-registration.entity';
4
4
  export { PermissionType, UserCompanyPermission } from './user-company-permission.entity';
5
5
  export * from './user.entity';
6
6
  export * from './user-token.entity';
7
- import { CompanyBranch } from './company-branch.entity';
8
- import { Company } from './company.entity';
9
- import { PendingRegistration } from './pending-registration.entity';
10
- import { UserCompanyPermission } from './user-company-permission.entity';
11
- import { User } from './user.entity';
12
- import { UserToken } from './user-token.entity';
13
- export declare const CoreEntities: (typeof PendingRegistration | typeof UserToken | typeof User)[];
14
- export declare const CompanyEntities: (typeof Company | typeof CompanyBranch | typeof UserCompanyPermission)[];
15
- export declare const AllEntities: (typeof PendingRegistration | typeof UserToken | typeof User | typeof Company | typeof CompanyBranch | typeof UserCompanyPermission)[];
16
- export declare function getEntitiesByConfig(enableCompanyFeature: boolean): (typeof PendingRegistration | typeof UserToken | typeof User | typeof Company | typeof CompanyBranch | typeof UserCompanyPermission)[];
7
+ export interface IAuthEntitiesConfig {
8
+ enableCompanyFeature?: boolean;
9
+ enableEmailVerification?: boolean;
10
+ }
11
+ export declare function getEntitiesByConfig(config: IAuthEntitiesConfig): any[];