@flusys/nestjs-auth 3.0.0-rc → 3.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 (40) hide show
  1. package/README.md +610 -95
  2. package/cjs/controllers/authentication.controller.js +2 -173
  3. package/cjs/controllers/email-verification.controller.js +220 -0
  4. package/cjs/controllers/index.js +1 -0
  5. package/cjs/dtos/authentication.dto.js +12 -2
  6. package/cjs/entities/index.js +16 -17
  7. package/cjs/entities/pending-registration.entity.js +9 -0
  8. package/cjs/modules/auth.module.js +33 -24
  9. package/cjs/services/auth-config.service.js +11 -7
  10. package/cjs/services/auth-datasource.provider.js +15 -27
  11. package/cjs/services/auth-email.service.js +8 -33
  12. package/cjs/services/authentication.service.js +123 -99
  13. package/cjs/services/user.service.js +28 -83
  14. package/controllers/authentication.controller.d.ts +2 -10
  15. package/controllers/email-verification.controller.d.ts +20 -0
  16. package/controllers/index.d.ts +1 -0
  17. package/dtos/authentication.dto.d.ts +1 -0
  18. package/entities/index.d.ts +5 -10
  19. package/entities/pending-registration.entity.d.ts +1 -0
  20. package/fesm/controllers/authentication.controller.js +3 -174
  21. package/fesm/controllers/email-verification.controller.js +210 -0
  22. package/fesm/controllers/index.js +1 -0
  23. package/fesm/dtos/authentication.dto.js +32 -25
  24. package/fesm/entities/index.js +17 -9
  25. package/fesm/entities/pending-registration.entity.js +9 -0
  26. package/fesm/interfaces/user-enricher.interface.js +2 -24
  27. package/fesm/modules/auth.module.js +35 -26
  28. package/fesm/services/auth-config.service.js +11 -7
  29. package/fesm/services/auth-datasource.provider.js +15 -27
  30. package/fesm/services/auth-email.service.js +8 -33
  31. package/fesm/services/authentication.service.js +124 -100
  32. package/fesm/services/user.service.js +28 -83
  33. package/interfaces/user-enricher.interface.d.ts +3 -2
  34. package/modules/auth.module.d.ts +3 -1
  35. package/package.json +3 -3
  36. package/services/auth-config.service.d.ts +1 -0
  37. package/services/auth-datasource.provider.d.ts +1 -0
  38. package/services/auth-email.service.d.ts +1 -0
  39. package/services/authentication.service.d.ts +4 -1
  40. package/services/user.service.d.ts +5 -0
@@ -30,7 +30,8 @@ import { ErrorHandler, generateUniqueSlug } from '@flusys/nestjs-shared/utils';
30
30
  import { BadRequestException, Inject, Injectable, Logger, NotFoundException, Optional, Scope, UnauthorizedException } from '@nestjs/common';
31
31
  import { JwtService } from '@nestjs/jwt';
32
32
  import * as bcrypt from 'bcrypt';
33
- import { BCRYPT_SALT_ROUNDS, TOKEN_REVOKED_PREFIX } from '../config';
33
+ import { BCRYPT_SALT_ROUNDS, TOKEN_REVOKED_PREFIX, USER_ENRICHER } from '../config';
34
+ import { IUserEnricher } from '../interfaces/user-enricher.interface';
34
35
  import { CompanyBranch } from '../entities/company-branch.entity';
35
36
  import { Company } from '../entities/company.entity';
36
37
  import { UserCompanyPermission } from '../entities/user-company-permission.entity';
@@ -41,11 +42,14 @@ import { AuthDataSourceProvider } from './auth-datasource.provider';
41
42
  import { AuthEmailService } from './auth-email.service';
42
43
  import { CompanySelectionSessionService } from './company-selection-session.service';
43
44
  export class AuthenticationService {
44
- // Feature Flags
45
- /** Check if company feature is enabled (tenant-aware with global fallback) */ isCompanyFeatureEnabled() {
45
+ isCompanyFeatureEnabled() {
46
46
  return this.dataSourceProvider?.isCompanyFeatureEnabled() ?? this.authConfig.isCompanyFeatureEnabled();
47
47
  }
48
- // Repository Getters
48
+ isEmailVerificationEnabled() {
49
+ const featureEnabled = this.dataSourceProvider?.isEmailVerificationEnabled() ?? this.authConfig.isEmailVerificationEnabled();
50
+ const providerAvailable = this.authEmailService?.isEmailEnabled() ?? false;
51
+ return featureEnabled && providerAvailable;
52
+ }
49
53
  async getUserRepository() {
50
54
  if (!this.dataSourceProvider) {
51
55
  throw new Error('User repository not available');
@@ -64,10 +68,8 @@ export class AuthenticationService {
64
68
  if (!this.isCompanyFeatureEnabled() || !this.dataSourceProvider) return null;
65
69
  return this.dataSourceProvider.getRepository(CompanyBranch);
66
70
  }
67
- // Login
68
71
  async login(email, password) {
69
- // Check for pending registration first (user registered but hasn't verified email yet)
70
- if (await this.authEmailService?.hasPendingRegistration(email)) {
72
+ if (this.isEmailVerificationEnabled() && await this.authEmailService.hasPendingRegistration(email)) {
71
73
  return {
72
74
  requiresEmailVerification: true,
73
75
  email,
@@ -78,7 +80,7 @@ export class AuthenticationService {
78
80
  if (!user.isActive) {
79
81
  throw new UnauthorizedException('User account is deactivated');
80
82
  }
81
- if (this.authEmailService?.isEmailEnabled() && !user.emailVerified) {
83
+ if (this.isEmailVerificationEnabled() && !user.emailVerified) {
82
84
  return {
83
85
  requiresEmailVerification: true,
84
86
  email: user.email,
@@ -90,20 +92,18 @@ export class AuthenticationService {
90
92
  }
91
93
  return this.handleCompanyBasedLogin(user);
92
94
  }
93
- /** Handle login when company feature is enabled */ async handleCompanyBasedLogin(user) {
95
+ async handleCompanyBasedLogin(user) {
94
96
  const permissionRepository = await this.getPermissionRepository();
95
97
  const branchRepository = await this.getBranchRepository();
96
98
  if (!permissionRepository || !branchRepository) {
97
99
  return this.generateLoginResponse(user);
98
100
  }
99
- // Get company permissions
100
101
  const companyPermissions = await permissionRepository.find({
101
102
  where: {
102
103
  userId: user.id,
103
104
  permissionType: PermissionType.COMPANY
104
105
  }
105
106
  });
106
- // Load companies
107
107
  const companyRepository = await this.getCompanyRepository();
108
108
  if (!companyRepository) {
109
109
  return this.generateLoginResponse(user);
@@ -114,12 +114,9 @@ export class AuthenticationService {
114
114
  }).andWhere('c.is_active = :active', {
115
115
  active: true
116
116
  }).getMany() : [];
117
- // If user has no company assignments yet, return simple login response
118
- // This allows users to login and be assigned to companies later
119
117
  if (companies.length === 0) {
120
118
  return this.generateLoginResponse(user);
121
119
  }
122
- // Get branch permissions
123
120
  const branchPermissions = await permissionRepository.find({
124
121
  where: {
125
122
  userId: user.id,
@@ -132,32 +129,25 @@ export class AuthenticationService {
132
129
  }).andWhere('b.is_active = :active', {
133
130
  active: true
134
131
  }).getMany() : [];
135
- // Case 1: Single company, single branch → Direct login
136
132
  if (companies.length === 1 && branches.length === 1) {
137
133
  return this.generateLoginResponseWithCompany(user, companies[0], branches[0]);
138
134
  }
139
- // Case 2: Multiple options → Selection required (frontend handles UI)
140
- // Returns all companies with their branches for frontend to display
141
135
  return await this.generateCompanySelectionResponse(user, companies, branches);
142
136
  }
143
- // Registration
144
- /** Register a new user. If email enabled, creates pending registration. Otherwise creates user directly. */ async register(dto, verifyUrlBase) {
137
+ async register(dto, verifyUrlBase) {
145
138
  const userRepository = await this.getUserRepository();
146
139
  const existingUser = await userRepository.findOne({
147
140
  where: {
148
141
  email: dto.email
149
142
  }
150
143
  });
151
- // When company feature is enabled and user exists, allow joining/creating company
152
144
  if (existingUser && this.isCompanyFeatureEnabled()) {
153
145
  return this.handleExistingUserCompanyRegistration(existingUser, dto);
154
146
  }
155
- // User exists but company feature is off - email must be unique
156
147
  if (existingUser) {
157
148
  throw new BadRequestException('Registration failed due to email exists. Please try again or contact support.');
158
149
  }
159
- // If email verification is enabled, create pending registration instead of user
160
- if (this.authEmailService?.isEmailEnabled() && verifyUrlBase) {
150
+ if (this.isEmailVerificationEnabled() && verifyUrlBase) {
161
151
  const companyData = this.isCompanyFeatureEnabled() ? {
162
152
  companySlug: dto.companySlug,
163
153
  branchSlug: dto.branchSlug,
@@ -171,6 +161,7 @@ export class AuthenticationService {
171
161
  phone: dto.phone,
172
162
  password: dto.password,
173
163
  companyData,
164
+ additionalFields: dto.additionalFields,
174
165
  verifyUrlBase
175
166
  });
176
167
  return {
@@ -178,10 +169,9 @@ export class AuthenticationService {
178
169
  message: result.message
179
170
  };
180
171
  }
181
- // No email verification - create user directly
182
172
  return this.createUserDirectly(dto);
183
173
  }
184
- /** Handle registration for existing user when company feature is enabled */ async handleExistingUserCompanyRegistration(existingUser, dto) {
174
+ async handleExistingUserCompanyRegistration(existingUser, dto) {
185
175
  if (!dto.companySlug && !dto.newCompanyName) {
186
176
  throw new BadRequestException('Email already registered. Please login or provide a company to join/create.');
187
177
  }
@@ -190,7 +180,6 @@ export class AuthenticationService {
190
180
  if (!permissionRepository || !companyRepository) {
191
181
  throw new BadRequestException('Company feature repositories not available');
192
182
  }
193
- // For existing users joining a company, check if already assigned
194
183
  if (dto.companySlug) {
195
184
  const company = await companyRepository.findOne({
196
185
  where: {
@@ -213,50 +202,92 @@ export class AuthenticationService {
213
202
  }
214
203
  return this.processCompanyRegistration(existingUser, dto, true);
215
204
  }
216
- /** Create user directly (no email verification) */ async createUserDirectly(dto) {
217
- const userRepository = await this.getUserRepository();
218
- const hashedPassword = await bcrypt.hash(dto.password, BCRYPT_SALT_ROUNDS);
219
- const user = userRepository.create({
220
- name: dto.name,
221
- email: dto.email,
222
- phone: dto.phone,
223
- password: hashedPassword,
224
- isActive: true,
225
- emailVerified: false,
226
- phoneVerified: false
227
- });
228
- await userRepository.save(user);
229
- if (!this.isCompanyFeatureEnabled()) {
230
- return this.generateRegistrationResponse(user);
205
+ async createUserDirectly(dto) {
206
+ if (!this.dataSourceProvider) {
207
+ throw new BadRequestException('Data source not available');
208
+ }
209
+ const dataSource = await this.dataSourceProvider.getDataSource();
210
+ const queryRunner = dataSource.createQueryRunner();
211
+ await queryRunner.connect();
212
+ await queryRunner.startTransaction();
213
+ try {
214
+ const hashedPassword = await bcrypt.hash(dto.password, BCRYPT_SALT_ROUNDS);
215
+ const user = queryRunner.manager.create(User, {
216
+ name: dto.name,
217
+ email: dto.email,
218
+ phone: dto.phone,
219
+ password: hashedPassword,
220
+ isActive: true,
221
+ emailVerified: false,
222
+ phoneVerified: false
223
+ });
224
+ await queryRunner.manager.save(User, user);
225
+ if (this.userEnricher?.onUserCreated) {
226
+ await this.userEnricher.onUserCreated(user.id, dto.additionalFields ?? null, queryRunner);
227
+ }
228
+ await queryRunner.commitTransaction();
229
+ if (!this.isCompanyFeatureEnabled()) {
230
+ return this.generateRegistrationResponse(user);
231
+ }
232
+ return this.processCompanyRegistration(user, dto);
233
+ } catch (error) {
234
+ await queryRunner.rollbackTransaction();
235
+ if (error instanceof BadRequestException) {
236
+ throw error;
237
+ }
238
+ ErrorHandler.logError(this.logger, error, 'createUserDirectly');
239
+ throw new BadRequestException('Registration failed. Please try again.');
240
+ } finally{
241
+ await queryRunner.release();
231
242
  }
232
- return this.processCompanyRegistration(user, dto);
233
243
  }
234
- /** Create user from pending registration (after email verification) */ async createUserFromPendingRegistration(pending) {
235
- const userRepository = await this.getUserRepository();
236
- const existingUser = await userRepository.findOne({
237
- where: {
238
- email: pending.email
244
+ async createUserFromPendingRegistration(pending) {
245
+ if (!this.dataSourceProvider) {
246
+ throw new BadRequestException('Data source not available');
247
+ }
248
+ const dataSource = await this.dataSourceProvider.getDataSource();
249
+ const queryRunner = dataSource.createQueryRunner();
250
+ await queryRunner.connect();
251
+ await queryRunner.startTransaction();
252
+ try {
253
+ const existingUser = await queryRunner.manager.findOne(User, {
254
+ where: {
255
+ email: pending.email
256
+ }
257
+ });
258
+ if (existingUser) {
259
+ throw new BadRequestException('This email has already been registered.');
239
260
  }
240
- });
241
- if (existingUser) {
242
- throw new BadRequestException('This email has already been registered.');
243
- }
244
- const user = userRepository.create({
245
- name: pending.name,
246
- email: pending.email,
247
- phone: pending.phone,
248
- password: pending.passwordHash,
249
- isActive: true,
250
- emailVerified: true,
251
- phoneVerified: false
252
- });
253
- await userRepository.save(user);
254
- if (this.isCompanyFeatureEnabled() && pending.companyData) {
255
- return this.processCompanyRegistration(user, pending.companyData);
261
+ const user = queryRunner.manager.create(User, {
262
+ name: pending.name,
263
+ email: pending.email,
264
+ phone: pending.phone,
265
+ password: pending.passwordHash,
266
+ isActive: true,
267
+ emailVerified: true,
268
+ phoneVerified: false
269
+ });
270
+ await queryRunner.manager.save(User, user);
271
+ if (this.userEnricher?.onUserCreated) {
272
+ await this.userEnricher.onUserCreated(user.id, pending.additionalFields ?? null, queryRunner);
273
+ }
274
+ await queryRunner.commitTransaction();
275
+ if (this.isCompanyFeatureEnabled() && pending.companyData) {
276
+ return this.processCompanyRegistration(user, pending.companyData);
277
+ }
278
+ return this.generateRegistrationResponse(user);
279
+ } catch (error) {
280
+ await queryRunner.rollbackTransaction();
281
+ if (error instanceof BadRequestException) {
282
+ throw error;
283
+ }
284
+ ErrorHandler.logError(this.logger, error, 'createUserFromPendingRegistration');
285
+ throw new BadRequestException('Registration failed. Please try again.');
286
+ } finally{
287
+ await queryRunner.release();
256
288
  }
257
- return this.generateRegistrationResponse(user);
258
289
  }
259
- /** Process company registration (join existing or create new) */ async processCompanyRegistration(user, data, throwOnUnavailable = false) {
290
+ async processCompanyRegistration(user, data, throwOnUnavailable = false) {
260
291
  const companyRepository = await this.getCompanyRepository();
261
292
  const branchRepository = await this.getBranchRepository();
262
293
  const permissionRepository = await this.getPermissionRepository();
@@ -271,7 +302,7 @@ export class AuthenticationService {
271
302
  }
272
303
  return this.generateRegistrationResponse(user);
273
304
  }
274
- /** Find existing company/branch or create new ones */ async findOrCreateCompanyAndBranch(data, companyRepo, branchRepo) {
305
+ async findOrCreateCompanyAndBranch(data, companyRepo, branchRepo) {
275
306
  if (data.companySlug) {
276
307
  const company = await companyRepo.findOne({
277
308
  where: {
@@ -335,7 +366,7 @@ export class AuthenticationService {
335
366
  branch: null
336
367
  };
337
368
  }
338
- /** Assign user to company and optionally branch */ async assignUserPermissions(userId, companyId, branchId, permissionRepo) {
369
+ async assignUserPermissions(userId, companyId, branchId, permissionRepo) {
339
370
  await permissionRepo.save(permissionRepo.create({
340
371
  userId,
341
372
  permissionType: PermissionType.COMPANY,
@@ -349,8 +380,7 @@ export class AuthenticationService {
349
380
  }));
350
381
  }
351
382
  }
352
- // Company/Branch Selection
353
- /** Select company and branch (step 2 of login). Frontend receives all options and user selects both. */ async select(sessionId, companyId, branchId) {
383
+ async select(sessionId, companyId, branchId) {
354
384
  this.ensureCompanyFeatureEnabled();
355
385
  if (!this.sessionService) {
356
386
  throw new BadRequestException('Session service not available');
@@ -361,11 +391,11 @@ export class AuthenticationService {
361
391
  }
362
392
  return this.validateAndLoginWithCompany(session.userId, companyId, branchId);
363
393
  }
364
- /** Switch company/branch after login */ async switchCompany(userId, companyId, branchId) {
394
+ async switchCompany(userId, companyId, branchId) {
365
395
  this.ensureCompanyFeatureEnabled();
366
396
  return this.validateAndLoginWithCompany(userId, companyId, branchId);
367
397
  }
368
- /** Shared: Validate user access to company/branch and generate login response */ async validateAndLoginWithCompany(userId, companyId, branchId) {
398
+ async validateAndLoginWithCompany(userId, companyId, branchId) {
369
399
  const userRepository = await this.getUserRepository();
370
400
  const user = await userRepository.findOne({
371
401
  where: {
@@ -381,7 +411,6 @@ export class AuthenticationService {
381
411
  if (!permissionRepository || !companyRepository || !branchRepository) {
382
412
  throw new BadRequestException('Repositories not available');
383
413
  }
384
- // Validate company access
385
414
  const hasCompanyAccess = await permissionRepository.findOne({
386
415
  where: {
387
416
  userId,
@@ -401,7 +430,6 @@ export class AuthenticationService {
401
430
  if (!company) {
402
431
  throw new UnauthorizedException('Company not found or inactive');
403
432
  }
404
- // Validate branch access
405
433
  const hasBranchAccess = await permissionRepository.findOne({
406
434
  where: {
407
435
  userId,
@@ -424,8 +452,7 @@ export class AuthenticationService {
424
452
  }
425
453
  return this.generateLoginResponseWithCompany(user, company, branch);
426
454
  }
427
- // Token Management
428
- /** Refresh access token (with token rotation). Returns new access token and new refresh token. */ async refreshToken(refreshToken) {
455
+ async refreshToken(refreshToken) {
429
456
  try {
430
457
  const payload = this.jwtService.verify(refreshToken, {
431
458
  secret: this.authConfig.getRefreshTokenSecret()
@@ -459,7 +486,7 @@ export class AuthenticationService {
459
486
  throw new UnauthorizedException('Invalid or expired refresh token');
460
487
  }
461
488
  }
462
- /** Change password */ async changePassword(userId, currentPassword, newPassword) {
489
+ async changePassword(userId, currentPassword, newPassword) {
463
490
  const userRepository = await this.getUserRepository();
464
491
  const user = await userRepository.findOne({
465
492
  where: {
@@ -473,21 +500,19 @@ export class AuthenticationService {
473
500
  user.password = await bcrypt.hash(newPassword, BCRYPT_SALT_ROUNDS);
474
501
  await userRepository.save(user);
475
502
  }
476
- /** Logout - Revokes all tokens. Stores revocation timestamp in cache. */ async logout(userId) {
503
+ async logout(userId) {
477
504
  if (!this.cacheManager) {
478
- // Cache is required for secure logout - tokens cannot be revoked without it
479
505
  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.');
480
506
  throw new BadRequestException('Logout service temporarily unavailable. Please try again later.');
481
507
  }
482
- const revokedAt = Math.floor(Date.now() / 1000); // Unix timestamp in seconds
508
+ const revokedAt = Math.floor(Date.now() / 1000);
483
509
  const cacheKey = `${TOKEN_REVOKED_PREFIX}:${userId}`;
484
- // TTL matches refresh token expiry (tokens older than this are already expired)
485
510
  const refreshTokenExpiry = this.authConfig.getRefreshTokenExpiration();
486
511
  const ttlMs = this.parseExpiryToMs(refreshTokenExpiry);
487
512
  await this.cacheManager.set(cacheKey, revokedAt, ttlMs);
488
513
  this.logger.log(`User ${userId} logged out - all tokens revoked`);
489
514
  }
490
- /** Check if a token is revoked (issued before user's revocation timestamp) */ async isTokenRevoked(userId, tokenIssuedAt) {
515
+ async isTokenRevoked(userId, tokenIssuedAt) {
491
516
  if (!this.cacheManager || !tokenIssuedAt) {
492
517
  return false;
493
518
  }
@@ -496,12 +521,11 @@ export class AuthenticationService {
496
521
  if (!revokedAt) {
497
522
  return false;
498
523
  }
499
- // Token is revoked if it was issued before the revocation timestamp
500
524
  return tokenIssuedAt < revokedAt;
501
525
  }
502
- /** Parse JWT expiry string to milliseconds */ parseExpiryToMs(expiry) {
526
+ parseExpiryToMs(expiry) {
503
527
  const match = expiry.match(/^(\d+)([smhd])$/);
504
- if (!match) return 7 * 24 * 60 * 60 * 1000; // Default 7 days
528
+ if (!match) return 7 * 24 * 60 * 60 * 1000;
505
529
  const value = parseInt(match[1], 10);
506
530
  const unit = match[2];
507
531
  switch(unit){
@@ -517,8 +541,7 @@ export class AuthenticationService {
517
541
  return 7 * 24 * 60 * 60 * 1000;
518
542
  }
519
543
  }
520
- // Query Methods
521
- /** Get user's companies */ async getUserCompanies(userId) {
544
+ async getUserCompanies(userId) {
522
545
  this.ensureCompanyFeatureEnabled();
523
546
  const permissionRepository = await this.getPermissionRepository();
524
547
  const companyRepository = await this.getCompanyRepository();
@@ -539,14 +562,13 @@ export class AuthenticationService {
539
562
  active: true
540
563
  }).orderBy('c.name', 'ASC').getMany();
541
564
  }
542
- /** Get branches for a company that user has access to */ async getUserBranches(userId, companyId) {
565
+ async getUserBranches(userId, companyId) {
543
566
  this.ensureCompanyFeatureEnabled();
544
567
  const permissionRepository = await this.getPermissionRepository();
545
568
  const branchRepository = await this.getBranchRepository();
546
569
  if (!permissionRepository || !branchRepository) {
547
570
  throw new BadRequestException('Repositories not available');
548
571
  }
549
- // Verify company access
550
572
  const companyPermission = await permissionRepository.findOne({
551
573
  where: {
552
574
  userId,
@@ -557,7 +579,6 @@ export class AuthenticationService {
557
579
  if (!companyPermission) {
558
580
  throw new UnauthorizedException('No access to this company');
559
581
  }
560
- // Get branch permissions
561
582
  const branchPermissions = await permissionRepository.find({
562
583
  where: {
563
584
  userId,
@@ -574,7 +595,7 @@ export class AuthenticationService {
574
595
  active: true
575
596
  }).orderBy('b.serial', 'ASC').addOrderBy('b.name', 'ASC').getMany();
576
597
  }
577
- /** Get company by ID */ async getCompanyById(companyId) {
598
+ async getCompanyById(companyId) {
578
599
  const companyRepository = await this.getCompanyRepository();
579
600
  if (!companyRepository) {
580
601
  return null;
@@ -585,7 +606,7 @@ export class AuthenticationService {
585
606
  }
586
607
  });
587
608
  }
588
- /** Get branch by ID */ async getBranchById(branchId) {
609
+ async getBranchById(branchId) {
589
610
  const branchRepository = await this.getBranchRepository();
590
611
  if (!branchRepository) {
591
612
  return null;
@@ -596,7 +617,7 @@ export class AuthenticationService {
596
617
  }
597
618
  });
598
619
  }
599
- /** Get user info for /auth/me endpoint. Returns user, company, and branch info (no tokens). */ async getUserInfo(userId, companyId, branchId) {
620
+ async getUserInfo(userId, companyId, branchId) {
600
621
  const userRepository = await this.getUserRepository();
601
622
  const user = await userRepository.findOne({
602
623
  where: {
@@ -622,7 +643,6 @@ export class AuthenticationService {
622
643
  }
623
644
  return response;
624
645
  }
625
- // Helper Methods
626
646
  ensureCompanyFeatureEnabled() {
627
647
  if (!this.isCompanyFeatureEnabled()) {
628
648
  throw new BadRequestException('Company feature is not enabled');
@@ -642,8 +662,7 @@ export class AuthenticationService {
642
662
  await userRepository.save(user);
643
663
  return user;
644
664
  }
645
- // Response Generators
646
- /** Create user info object */ toUserInfo(user) {
665
+ toUserInfo(user) {
647
666
  return {
648
667
  id: user.id,
649
668
  email: user.email,
@@ -652,7 +671,7 @@ export class AuthenticationService {
652
671
  profilePictureId: user.profilePictureId ?? null
653
672
  };
654
673
  }
655
- /** Create company info object */ toCompanyInfo(company) {
674
+ toCompanyInfo(company) {
656
675
  return {
657
676
  id: company.id,
658
677
  name: company.name,
@@ -660,7 +679,7 @@ export class AuthenticationService {
660
679
  logoId: company.logoId ?? null
661
680
  };
662
681
  }
663
- /** Create branch info object */ toBranchInfo(branch) {
682
+ toBranchInfo(branch) {
664
683
  return {
665
684
  id: branch.id,
666
685
  name: branch.name,
@@ -668,7 +687,7 @@ export class AuthenticationService {
668
687
  logoId: branch.logoId ?? null
669
688
  };
670
689
  }
671
- /** Generate JWT tokens */ generateTokens(payload) {
690
+ generateTokens(payload) {
672
691
  const accessToken = this.jwtService.sign({
673
692
  ...payload,
674
693
  type: 'access'
@@ -750,13 +769,14 @@ export class AuthenticationService {
750
769
  };
751
770
  }
752
771
  // NOTE: @Inject() required for bundled code - type metadata may be lost during esbuild
753
- constructor(jwtService, authConfig, cacheManager, dataSourceProvider, sessionService, authEmailService){
772
+ constructor(jwtService, authConfig, cacheManager, dataSourceProvider, sessionService, authEmailService, userEnricher){
754
773
  _define_property(this, "jwtService", void 0);
755
774
  _define_property(this, "authConfig", void 0);
756
775
  _define_property(this, "cacheManager", void 0);
757
776
  _define_property(this, "dataSourceProvider", void 0);
758
777
  _define_property(this, "sessionService", void 0);
759
778
  _define_property(this, "authEmailService", void 0);
779
+ _define_property(this, "userEnricher", void 0);
760
780
  _define_property(this, "logger", void 0);
761
781
  this.jwtService = jwtService;
762
782
  this.authConfig = authConfig;
@@ -764,6 +784,7 @@ export class AuthenticationService {
764
784
  this.dataSourceProvider = dataSourceProvider;
765
785
  this.sessionService = sessionService;
766
786
  this.authEmailService = authEmailService;
787
+ this.userEnricher = userEnricher;
767
788
  this.logger = new Logger(AuthenticationService.name);
768
789
  }
769
790
  }
@@ -781,6 +802,8 @@ AuthenticationService = _ts_decorate([
781
802
  _ts_param(4, Inject(CompanySelectionSessionService)),
782
803
  _ts_param(5, Optional()),
783
804
  _ts_param(5, Inject(AuthEmailService)),
805
+ _ts_param(6, Optional()),
806
+ _ts_param(6, Inject(USER_ENRICHER)),
784
807
  _ts_metadata("design:type", Function),
785
808
  _ts_metadata("design:paramtypes", [
786
809
  typeof JwtService === "undefined" ? Object : JwtService,
@@ -788,6 +811,7 @@ AuthenticationService = _ts_decorate([
788
811
  typeof HybridCache === "undefined" ? Object : HybridCache,
789
812
  typeof AuthDataSourceProvider === "undefined" ? Object : AuthDataSourceProvider,
790
813
  typeof CompanySelectionSessionService === "undefined" ? Object : CompanySelectionSessionService,
791
- typeof AuthEmailService === "undefined" ? Object : AuthEmailService
814
+ typeof AuthEmailService === "undefined" ? Object : AuthEmailService,
815
+ typeof IUserEnricher === "undefined" ? Object : IUserEnricher
792
816
  ])
793
817
  ], AuthenticationService);