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

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 (95) hide show
  1. package/README.md +274 -291
  2. package/cjs/config/auth.constants.js +12 -0
  3. package/cjs/controllers/authentication.controller.js +219 -10
  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 +40 -25
  8. package/cjs/controllers/user.controller.js +211 -7
  9. package/cjs/dtos/authentication.dto.js +119 -13
  10. package/cjs/dtos/user-permission.dto.js +28 -0
  11. package/cjs/dtos/user.dto.js +19 -4
  12. package/cjs/entities/index.js +5 -1
  13. package/cjs/entities/pending-registration.entity.js +125 -0
  14. package/cjs/entities/user-company-permission.entity.js +0 -6
  15. package/cjs/entities/user-token.entity.js +129 -0
  16. package/cjs/guards/auth-throttler.guard.js +53 -0
  17. package/cjs/interceptors/clear-token.interceptor.js +3 -6
  18. package/cjs/interceptors/set-token.interceptor.js +38 -31
  19. package/cjs/interfaces/auth-email-provider.interface.js +45 -0
  20. package/cjs/interfaces/index.js +2 -0
  21. package/cjs/interfaces/user-enricher.interface.js +4 -0
  22. package/cjs/modules/auth.module.js +8 -20
  23. package/cjs/services/auth-config.service.js +23 -2
  24. package/cjs/services/auth-datasource.provider.js +5 -3
  25. package/cjs/services/auth-email.service.js +471 -0
  26. package/cjs/services/authentication.service.js +169 -77
  27. package/cjs/services/branch.service.js +6 -5
  28. package/cjs/services/company-selection-session.service.js +1 -1
  29. package/cjs/services/index.js +1 -0
  30. package/cjs/services/user-permission.service.js +0 -2
  31. package/cjs/services/user.service.js +213 -34
  32. package/cjs/validators/password.validator.js +45 -0
  33. package/config/auth.constants.d.ts +3 -0
  34. package/controllers/authentication.controller.d.ts +13 -9
  35. package/controllers/company-selection.controller.d.ts +6 -2
  36. package/controllers/user.controller.d.ts +33 -0
  37. package/dtos/authentication.dto.d.ts +21 -3
  38. package/dtos/company-branch.dto.d.ts +0 -1
  39. package/dtos/company.dto.d.ts +0 -1
  40. package/dtos/user-permission.dto.d.ts +4 -0
  41. package/dtos/user.dto.d.ts +1 -2
  42. package/entities/index.d.ts +7 -3
  43. package/entities/pending-registration.entity.d.ts +17 -0
  44. package/entities/user-company-permission.entity.d.ts +0 -2
  45. package/entities/user-token.entity.d.ts +15 -0
  46. package/fesm/config/auth.constants.js +6 -2
  47. package/fesm/controllers/authentication.controller.js +221 -12
  48. package/fesm/controllers/branch.controller.js +45 -2
  49. package/fesm/controllers/company-selection.controller.js +28 -21
  50. package/fesm/controllers/company.controller.js +45 -2
  51. package/fesm/controllers/user-permission.controller.js +41 -26
  52. package/fesm/controllers/user.controller.js +214 -10
  53. package/fesm/dtos/authentication.dto.js +106 -14
  54. package/fesm/dtos/user-permission.dto.js +28 -0
  55. package/fesm/dtos/user.dto.js +20 -5
  56. package/fesm/entities/index.js +7 -1
  57. package/fesm/entities/pending-registration.entity.js +115 -0
  58. package/fesm/entities/user-company-permission.entity.js +0 -6
  59. package/fesm/entities/user-token.entity.js +113 -0
  60. package/fesm/guards/auth-throttler.guard.js +43 -0
  61. package/fesm/interceptors/clear-token.interceptor.js +2 -5
  62. package/fesm/interceptors/set-token.interceptor.js +37 -30
  63. package/fesm/interfaces/auth-email-provider.interface.js +38 -0
  64. package/fesm/interfaces/authentication.interface.js +1 -1
  65. package/fesm/interfaces/index.js +2 -0
  66. package/fesm/interfaces/user-enricher.interface.js +26 -0
  67. package/fesm/modules/auth.module.js +10 -22
  68. package/fesm/services/auth-config.service.js +24 -3
  69. package/fesm/services/auth-datasource.provider.js +6 -4
  70. package/fesm/services/auth-email.service.js +420 -0
  71. package/fesm/services/authentication.service.js +169 -77
  72. package/fesm/services/branch.service.js +6 -5
  73. package/fesm/services/company-selection-session.service.js +1 -1
  74. package/fesm/services/index.js +1 -0
  75. package/fesm/services/user-permission.service.js +1 -3
  76. package/fesm/services/user.service.js +215 -36
  77. package/fesm/validators/password.validator.js +48 -0
  78. package/guards/auth-throttler.guard.d.ts +7 -0
  79. package/interceptors/set-token.interceptor.d.ts +1 -0
  80. package/interfaces/auth-email-provider.interface.d.ts +6 -0
  81. package/interfaces/auth-module-options.interface.d.ts +4 -1
  82. package/interfaces/authentication.interface.d.ts +14 -0
  83. package/interfaces/index.d.ts +2 -0
  84. package/interfaces/user-enricher.interface.d.ts +64 -0
  85. package/interfaces/user.interface.d.ts +1 -0
  86. package/modules/auth.module.d.ts +0 -1
  87. package/package.json +4 -4
  88. package/services/auth-config.service.d.ts +5 -1
  89. package/services/auth-email.service.d.ts +51 -0
  90. package/services/authentication.service.d.ts +16 -11
  91. package/services/company-selection-session.service.d.ts +1 -1
  92. package/services/index.d.ts +1 -0
  93. package/services/user-permission.service.d.ts +0 -1
  94. package/services/user.service.d.ts +19 -3
  95. package/validators/password.validator.d.ts +10 -0
@@ -27,15 +27,14 @@ function _ts_param(paramIndex, decorator) {
27
27
  }
28
28
  import { BadRequestException, Inject, Injectable, Logger, NotFoundException, Optional, Scope, UnauthorizedException } from '@nestjs/common';
29
29
  import { JwtService } from '@nestjs/jwt';
30
- import { InjectRepository } from '@nestjs/typeorm';
31
30
  import * as bcrypt from 'bcrypt';
32
- import { Repository } from 'typeorm';
33
31
  import { ErrorHandler } from '@flusys/nestjs-shared/utils';
34
32
  import { AuthConfigService } from './auth-config.service';
35
33
  import { AuthDataSourceProvider } from './auth-datasource.provider';
36
34
  import { PermissionType } from '../enums';
37
35
  import { BCRYPT_SALT_ROUNDS, TOKEN_REVOKED_PREFIX } from '../config';
38
36
  import { HybridCache } from '@flusys/nestjs-shared/classes';
37
+ import { AuthEmailService } from './auth-email.service';
39
38
  import { CompanyBranch } from '../entities/company-branch.entity';
40
39
  import { Company } from '../entities/company.entity';
41
40
  import { UserCompanyPermission } from '../entities/user-company-permission.entity';
@@ -44,34 +43,22 @@ import { CompanySelectionSessionService } from './company-selection-session.serv
44
43
  export class AuthenticationService {
45
44
  // Repository Getters
46
45
  async getUserRepository() {
47
- if (this.dataSourceProvider) {
48
- return this.dataSourceProvider.getRepository(User);
46
+ if (!this.dataSourceProvider) {
47
+ throw new Error('User repository not available');
49
48
  }
50
- if (this.injectedUserRepository) {
51
- return this.injectedUserRepository;
52
- }
53
- throw new Error('User repository not available');
49
+ return this.dataSourceProvider.getRepository(User);
54
50
  }
55
51
  async getPermissionRepository() {
56
- if (!this.authConfig.isCompanyFeatureEnabled()) return null;
57
- if (this.dataSourceProvider) {
58
- return this.dataSourceProvider.getRepository(UserCompanyPermission);
59
- }
60
- return this.injectedPermissionRepository ?? null;
52
+ if (!this.authConfig.isCompanyFeatureEnabled() || !this.dataSourceProvider) return null;
53
+ return this.dataSourceProvider.getRepository(UserCompanyPermission);
61
54
  }
62
55
  async getCompanyRepository() {
63
- if (!this.authConfig.isCompanyFeatureEnabled()) return null;
64
- if (this.dataSourceProvider) {
65
- return this.dataSourceProvider.getRepository(Company);
66
- }
67
- return this.injectedCompanyRepository ?? null;
56
+ if (!this.authConfig.isCompanyFeatureEnabled() || !this.dataSourceProvider) return null;
57
+ return this.dataSourceProvider.getRepository(Company);
68
58
  }
69
59
  async getBranchRepository() {
70
- if (!this.authConfig.isCompanyFeatureEnabled()) return null;
71
- if (this.dataSourceProvider) {
72
- return this.dataSourceProvider.getRepository(CompanyBranch);
73
- }
74
- return this.injectedBranchRepository ?? null;
60
+ if (!this.authConfig.isCompanyFeatureEnabled() || !this.dataSourceProvider) return null;
61
+ return this.dataSourceProvider.getRepository(CompanyBranch);
75
62
  }
76
63
  // Login
77
64
  /** Login with email and password. Returns tokens or requires company/branch selection. */ async login(email, password) {
@@ -79,7 +66,14 @@ export class AuthenticationService {
79
66
  if (!user.isActive) {
80
67
  throw new UnauthorizedException('User account is deactivated');
81
68
  }
82
- // If company feature not enabled, return simple token
69
+ // Check email verification if email service is enabled
70
+ if (this.authEmailService?.isEmailEnabled() && !user.emailVerified) {
71
+ return {
72
+ requiresEmailVerification: true,
73
+ email: user.email,
74
+ message: 'Please verify your email address before logging in.'
75
+ };
76
+ }
83
77
  if (!this.authConfig.isCompanyFeatureEnabled()) {
84
78
  return this.generateLoginResponse(user);
85
79
  }
@@ -136,10 +130,8 @@ export class AuthenticationService {
136
130
  return await this.generateCompanySelectionResponse(user, companies, branches);
137
131
  }
138
132
  // Registration
139
- /** Register a new user. If company feature enabled, optionally join/create company. */ async register(dto) {
133
+ /** Register a new user. If email enabled, creates pending registration. Otherwise creates user directly. */ async register(dto, verifyUrlBase) {
140
134
  const userRepository = await this.getUserRepository();
141
- // Check if user exists
142
- // Note: Generic error message to prevent email enumeration attacks
143
135
  const existingUser = await userRepository.findOne({
144
136
  where: {
145
137
  email: dto.email
@@ -148,7 +140,33 @@ export class AuthenticationService {
148
140
  if (existingUser) {
149
141
  throw new BadRequestException('Registration failed. Please try again or contact support.');
150
142
  }
151
- // Create user
143
+ // If email verification is enabled, create pending registration instead of user
144
+ if (this.authEmailService?.isEmailEnabled() && verifyUrlBase) {
145
+ const companyData = this.authConfig.isCompanyFeatureEnabled() ? {
146
+ companySlug: dto.companySlug,
147
+ branchSlug: dto.branchSlug,
148
+ newCompanyName: dto.newCompanyName,
149
+ newCompanyPhone: dto.newCompanyPhone,
150
+ newCompanyAddress: dto.newCompanyAddress
151
+ } : undefined;
152
+ const result = await this.authEmailService.createPendingRegistration({
153
+ email: dto.email,
154
+ name: dto.name,
155
+ phone: dto.phone,
156
+ password: dto.password,
157
+ companyData,
158
+ verifyUrlBase
159
+ });
160
+ return {
161
+ requiresEmailVerification: true,
162
+ message: result.message
163
+ };
164
+ }
165
+ // No email verification - create user directly
166
+ return this.createUserDirectly(dto);
167
+ }
168
+ /** Create user directly (no email verification) */ async createUserDirectly(dto) {
169
+ const userRepository = await this.getUserRepository();
152
170
  const hashedPassword = await bcrypt.hash(dto.password, BCRYPT_SALT_ROUNDS);
153
171
  const user = userRepository.create({
154
172
  name: dto.name,
@@ -160,38 +178,68 @@ export class AuthenticationService {
160
178
  phoneVerified: false
161
179
  });
162
180
  await userRepository.save(user);
163
- // If company feature not enabled, return simple response
164
181
  if (!this.authConfig.isCompanyFeatureEnabled()) {
165
- return this.generateLoginResponse(user, false);
182
+ return this.generateRegistrationResponse(user, false, false);
166
183
  }
167
- // Handle company feature
168
- return this.handleCompanyRegistration(user, dto);
184
+ return this.handleCompanyRegistration(user, dto, false);
169
185
  }
170
- /** Handle company-related registration logic */ async handleCompanyRegistration(user, dto) {
186
+ /** Create user from pending registration (after email verification) */ async createUserFromPendingRegistration(pending) {
187
+ const userRepository = await this.getUserRepository();
188
+ // Check if user already exists (race condition protection)
189
+ const existingUser = await userRepository.findOne({
190
+ where: {
191
+ email: pending.email
192
+ }
193
+ });
194
+ if (existingUser) {
195
+ throw new BadRequestException('This email has already been registered.');
196
+ }
197
+ // Create user with verified email
198
+ const user = userRepository.create({
199
+ name: pending.name,
200
+ email: pending.email,
201
+ phone: pending.phone,
202
+ password: pending.passwordHash,
203
+ isActive: true,
204
+ emailVerified: true,
205
+ phoneVerified: false
206
+ });
207
+ await userRepository.save(user);
208
+ // Handle company feature if enabled
209
+ if (this.authConfig.isCompanyFeatureEnabled() && pending.companyData) {
210
+ return this.handleCompanyRegistrationFromPending(user, pending.companyData);
211
+ }
212
+ return this.generateRegistrationResponse(user, this.authConfig.isCompanyFeatureEnabled(), false);
213
+ }
214
+ /** Handle company registration from pending registration data */ async handleCompanyRegistrationFromPending(user, companyData) {
215
+ return this.processCompanyRegistration(user, companyData, false);
216
+ }
217
+ /** Handle company-related registration logic */ async handleCompanyRegistration(user, dto, requiresEmailVerification) {
218
+ return this.processCompanyRegistration(user, dto, requiresEmailVerification);
219
+ }
220
+ /** Shared logic for company registration (join existing or create new) */ async processCompanyRegistration(user, data, requiresEmailVerification) {
171
221
  const companyRepository = await this.getCompanyRepository();
172
222
  const branchRepository = await this.getBranchRepository();
173
223
  const permissionRepository = await this.getPermissionRepository();
174
224
  if (!companyRepository || !branchRepository || !permissionRepository) {
175
- return this.generateLoginResponse(user, true);
225
+ return this.generateRegistrationResponse(user, true, requiresEmailVerification);
176
226
  }
177
227
  let company = null;
178
228
  let branch = null;
179
- // Case 1: Join existing company by slug
180
- if (dto.companySlug) {
229
+ if (data.companySlug) {
181
230
  company = await companyRepository.findOne({
182
231
  where: {
183
- slug: dto.companySlug,
232
+ slug: data.companySlug,
184
233
  isActive: true
185
234
  }
186
235
  });
187
236
  if (!company) {
188
237
  throw new BadRequestException('Company not found or inactive');
189
238
  }
190
- // Find branch by slug or get default
191
- if (dto.branchSlug) {
239
+ if (data.branchSlug) {
192
240
  branch = await branchRepository.findOne({
193
241
  where: {
194
- slug: dto.branchSlug,
242
+ slug: data.branchSlug,
195
243
  companyId: company.id,
196
244
  isActive: true
197
245
  }
@@ -200,7 +248,6 @@ export class AuthenticationService {
200
248
  throw new BadRequestException('Branch not found or inactive');
201
249
  }
202
250
  } else {
203
- // Get first active branch
204
251
  branch = await branchRepository.findOne({
205
252
  where: {
206
253
  companyId: company.id,
@@ -212,9 +259,8 @@ export class AuthenticationService {
212
259
  }
213
260
  });
214
261
  }
215
- } else if (dto.newCompanyName) {
216
- const slug = this.generateSlug(dto.newCompanyName);
217
- // Check if slug exists
262
+ } else if (data.newCompanyName) {
263
+ const slug = this.generateSlug(data.newCompanyName);
218
264
  const existingCompany = await companyRepository.findOne({
219
265
  where: {
220
266
  slug
@@ -223,16 +269,14 @@ export class AuthenticationService {
223
269
  if (existingCompany) {
224
270
  throw new BadRequestException('Company creation failed. Please try a different name.');
225
271
  }
226
- // Create company
227
272
  company = companyRepository.create({
228
- name: dto.newCompanyName,
273
+ name: data.newCompanyName,
229
274
  slug,
230
- phone: dto.newCompanyPhone,
231
- address: dto.newCompanyAddress,
275
+ phone: data.newCompanyPhone,
276
+ address: data.newCompanyAddress,
232
277
  isActive: true
233
278
  });
234
279
  await companyRepository.save(company);
235
- // Create default branch
236
280
  branch = branchRepository.create({
237
281
  name: 'Main Branch',
238
282
  slug: 'main-branch',
@@ -241,16 +285,13 @@ export class AuthenticationService {
241
285
  });
242
286
  await branchRepository.save(branch);
243
287
  }
244
- // Create permissions if company exists
245
288
  if (company) {
246
- // Create company permission
247
289
  const companyPermission = permissionRepository.create({
248
290
  userId: user.id,
249
291
  permissionType: PermissionType.COMPANY,
250
292
  targetId: company.id
251
293
  });
252
294
  await permissionRepository.save(companyPermission);
253
- // Create branch permission if branch exists
254
295
  if (branch) {
255
296
  const branchPermission = permissionRepository.create({
256
297
  userId: user.id,
@@ -259,10 +300,9 @@ export class AuthenticationService {
259
300
  });
260
301
  await permissionRepository.save(branchPermission);
261
302
  }
262
- return this.generateLoginResponseWithCompany(user, company, branch ?? undefined);
303
+ return this.generateRegistrationResponseWithCompany(user, company, branch ?? undefined, requiresEmailVerification);
263
304
  }
264
- // No company assigned
265
- return this.generateLoginResponse(user, true);
305
+ return this.generateRegistrationResponse(user, true, requiresEmailVerification);
266
306
  }
267
307
  /** Generate URL-friendly slug from name */ generateSlug(name) {
268
308
  return name.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-+|-+$/g, '').substring(0, 100);
@@ -400,6 +440,11 @@ export class AuthenticationService {
400
440
  const payload = this.jwtService.verify(refreshToken, {
401
441
  secret: this.authConfig.getRefreshTokenSecret()
402
442
  });
443
+ // Check if token has been revoked (user logged out after token was issued)
444
+ const isRevoked = await this.isTokenRevoked(payload.id, payload.iat);
445
+ if (isRevoked) {
446
+ throw new UnauthorizedException('Token has been revoked');
447
+ }
403
448
  const userRepository = await this.getUserRepository();
404
449
  const user = await userRepository.findOne({
405
450
  where: {
@@ -480,8 +525,9 @@ export class AuthenticationService {
480
525
  }
481
526
  /** Logout - Revokes all tokens. Stores revocation timestamp in cache. */ async logout(userId) {
482
527
  if (!this.cacheManager) {
483
- // Cache not available - graceful degradation (client-side logout only)
484
- return;
528
+ // Cache is required for secure logout - tokens cannot be revoked without it
529
+ 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.');
530
+ throw new BadRequestException('Logout service temporarily unavailable. Please try again later.');
485
531
  }
486
532
  const revokedAt = Math.floor(Date.now() / 1000); // Unix timestamp in seconds
487
533
  const cacheKey = `${TOKEN_REVOKED_PREFIX}:${userId}`;
@@ -489,6 +535,7 @@ export class AuthenticationService {
489
535
  const refreshTokenExpiry = this.authConfig.getRefreshTokenExpiration();
490
536
  const ttlMs = this.parseExpiryToMs(refreshTokenExpiry);
491
537
  await this.cacheManager.set(cacheKey, revokedAt, ttlMs);
538
+ this.logger.log(`User ${userId} logged out - all tokens revoked`);
492
539
  }
493
540
  /** Check if a token is revoked (issued before user's revocation timestamp) */ async isTokenRevoked(userId, tokenIssuedAt) {
494
541
  if (!this.cacheManager || !tokenIssuedAt) {
@@ -615,6 +662,7 @@ export class AuthenticationService {
615
662
  id: user.id,
616
663
  email: user.email,
617
664
  name: user.name ?? undefined,
665
+ phone: user.phone ?? undefined,
618
666
  profilePictureId: user.profilePictureId ?? undefined
619
667
  }
620
668
  };
@@ -701,6 +749,7 @@ export class AuthenticationService {
701
749
  id: user.id,
702
750
  email: user.email,
703
751
  name: user.name ?? undefined,
752
+ phone: user.phone ?? null,
704
753
  profilePictureId: user.profilePictureId ?? null
705
754
  },
706
755
  companyFeatureEnabled
@@ -736,6 +785,7 @@ export class AuthenticationService {
736
785
  id: user.id,
737
786
  email: user.email,
738
787
  name: user.name ?? undefined,
788
+ phone: user.phone ?? null,
739
789
  profilePictureId: user.profilePictureId ?? null
740
790
  },
741
791
  company: {
@@ -781,32 +831,83 @@ export class AuthenticationService {
781
831
  id: user.id,
782
832
  email: user.email,
783
833
  name: user.name ?? undefined,
834
+ phone: user.phone ?? null,
784
835
  profilePictureId: user.profilePictureId ?? null
785
836
  },
786
837
  companies: companiesWithBranches
787
838
  };
788
839
  }
840
+ /** Generate registration response - tokens included only if email verification not required */ generateRegistrationResponse(user, companyFeatureEnabled, requiresEmailVerification) {
841
+ const userInfo = {
842
+ id: user.id,
843
+ email: user.email,
844
+ name: user.name ?? undefined,
845
+ phone: user.phone ?? null,
846
+ profilePictureId: user.profilePictureId ?? null
847
+ };
848
+ if (requiresEmailVerification) {
849
+ return {
850
+ user: userInfo,
851
+ companyFeatureEnabled,
852
+ requiresEmailVerification: true
853
+ };
854
+ }
855
+ const loginResponse = this.generateLoginResponse(user, companyFeatureEnabled);
856
+ return {
857
+ ...loginResponse,
858
+ requiresEmailVerification: false
859
+ };
860
+ }
861
+ /** Generate registration response with company - tokens included only if email verification not required */ generateRegistrationResponseWithCompany(user, company, branch, requiresEmailVerification = false) {
862
+ const userInfo = {
863
+ id: user.id,
864
+ email: user.email,
865
+ name: user.name ?? undefined,
866
+ phone: user.phone ?? null,
867
+ profilePictureId: user.profilePictureId ?? null
868
+ };
869
+ const companyInfo = {
870
+ id: company.id,
871
+ name: company.name,
872
+ slug: company.slug,
873
+ logoId: company.logoId ?? null
874
+ };
875
+ const branchInfo = branch ? {
876
+ id: branch.id,
877
+ name: branch.name,
878
+ slug: branch.slug,
879
+ logoId: branch.logoId ?? null
880
+ } : undefined;
881
+ if (requiresEmailVerification) {
882
+ return {
883
+ user: userInfo,
884
+ company: companyInfo,
885
+ branch: branchInfo,
886
+ companyFeatureEnabled: true,
887
+ requiresEmailVerification: true
888
+ };
889
+ }
890
+ const loginResponse = this.generateLoginResponseWithCompany(user, company, branch);
891
+ return {
892
+ ...loginResponse,
893
+ requiresEmailVerification: false
894
+ };
895
+ }
789
896
  // NOTE: @Inject() required for bundled code - type metadata may be lost during esbuild
790
- constructor(jwtService, authConfig, cacheManager, dataSourceProvider, sessionService, injectedUserRepository, injectedPermissionRepository, injectedCompanyRepository, injectedBranchRepository){
897
+ constructor(jwtService, authConfig, cacheManager, dataSourceProvider, sessionService, authEmailService){
791
898
  _define_property(this, "jwtService", void 0);
792
899
  _define_property(this, "authConfig", void 0);
793
900
  _define_property(this, "cacheManager", void 0);
794
901
  _define_property(this, "dataSourceProvider", void 0);
795
902
  _define_property(this, "sessionService", void 0);
796
- _define_property(this, "injectedUserRepository", void 0);
797
- _define_property(this, "injectedPermissionRepository", void 0);
798
- _define_property(this, "injectedCompanyRepository", void 0);
799
- _define_property(this, "injectedBranchRepository", void 0);
903
+ _define_property(this, "authEmailService", void 0);
800
904
  _define_property(this, "logger", void 0);
801
905
  this.jwtService = jwtService;
802
906
  this.authConfig = authConfig;
803
907
  this.cacheManager = cacheManager;
804
908
  this.dataSourceProvider = dataSourceProvider;
805
909
  this.sessionService = sessionService;
806
- this.injectedUserRepository = injectedUserRepository;
807
- this.injectedPermissionRepository = injectedPermissionRepository;
808
- this.injectedCompanyRepository = injectedCompanyRepository;
809
- this.injectedBranchRepository = injectedBranchRepository;
910
+ this.authEmailService = authEmailService;
810
911
  this.logger = new Logger(AuthenticationService.name);
811
912
  }
812
913
  }
@@ -823,13 +924,7 @@ AuthenticationService = _ts_decorate([
823
924
  _ts_param(4, Optional()),
824
925
  _ts_param(4, Inject(CompanySelectionSessionService)),
825
926
  _ts_param(5, Optional()),
826
- _ts_param(5, InjectRepository(User)),
827
- _ts_param(6, Optional()),
828
- _ts_param(6, InjectRepository(UserCompanyPermission)),
829
- _ts_param(7, Optional()),
830
- _ts_param(7, InjectRepository(Company)),
831
- _ts_param(8, Optional()),
832
- _ts_param(8, InjectRepository(CompanyBranch)),
927
+ _ts_param(5, Inject(AuthEmailService)),
833
928
  _ts_metadata("design:type", Function),
834
929
  _ts_metadata("design:paramtypes", [
835
930
  typeof JwtService === "undefined" ? Object : JwtService,
@@ -837,9 +932,6 @@ AuthenticationService = _ts_decorate([
837
932
  typeof HybridCache === "undefined" ? Object : HybridCache,
838
933
  typeof AuthDataSourceProvider === "undefined" ? Object : AuthDataSourceProvider,
839
934
  typeof CompanySelectionSessionService === "undefined" ? Object : CompanySelectionSessionService,
840
- typeof Repository === "undefined" ? Object : Repository,
841
- typeof Repository === "undefined" ? Object : Repository,
842
- typeof Repository === "undefined" ? Object : Repository,
843
- typeof Repository === "undefined" ? Object : Repository
935
+ typeof AuthEmailService === "undefined" ? Object : AuthEmailService
844
936
  ])
845
937
  ], AuthenticationService);
@@ -27,6 +27,7 @@ function _ts_param(paramIndex, decorator) {
27
27
  }
28
28
  import { RequestScopedApiService, HybridCache } from '@flusys/nestjs-shared/classes';
29
29
  import { UtilsService } from '@flusys/nestjs-shared/modules';
30
+ import { applyCompanyFilter } from '@flusys/nestjs-shared/utils';
30
31
  import { Inject, Injectable, Scope } from '@nestjs/common';
31
32
  import { CompanyBranch } from '../entities/company-branch.entity';
32
33
  import { AuthConfigService } from './auth-config.service';
@@ -66,11 +67,11 @@ export class BranchService extends RequestScopedApiService {
66
67
  }
67
68
  async getExtraManipulateQuery(query, filterDto, user) {
68
69
  const result = await super.getExtraManipulateQuery(query, filterDto, user);
69
- if (this.authConfig.isCompanyFeatureEnabled() && user?.companyId) {
70
- query.andWhere('company_branch.company_id = :companyId', {
71
- companyId: user.companyId
72
- });
73
- }
70
+ applyCompanyFilter(query, {
71
+ isCompanyFeatureEnabled: this.authConfig.isCompanyFeatureEnabled(),
72
+ entityAlias: 'company_branch',
73
+ columnName: 'company_id'
74
+ }, user);
74
75
  return result;
75
76
  }
76
77
  constructor(cacheManager, utilsService, dataSourceProvider, authConfig){
@@ -33,7 +33,7 @@ const SESSION_TTL_MS = 5 * 60 * 1000; // 5 minutes
33
33
  export class CompanySelectionSessionService {
34
34
  /**
35
35
  * Create a new session for company/branch selection
36
- */ async createSession(userId, companyId) {
36
+ */ async createSession(userId) {
37
37
  const sessionId = randomUUID();
38
38
  const now = new Date();
39
39
  const expiresAt = new Date(now.getTime() + SESSION_TTL_MS);
@@ -1,4 +1,5 @@
1
1
  export * from './authentication.service';
2
+ export * from './auth-email.service';
2
3
  export * from './company-selection-session.service';
3
4
  export * from './user.service';
4
5
  export * from './company.service';
@@ -25,7 +25,7 @@ function _ts_param(paramIndex, decorator) {
25
25
  decorator(target, key, paramIndex);
26
26
  };
27
27
  }
28
- import { BadRequestException, Inject, Injectable, Logger, NotFoundException, Scope } from '@nestjs/common';
28
+ import { BadRequestException, Inject, Injectable, NotFoundException, Scope } from '@nestjs/common';
29
29
  import { PermissionType, UserCompanyPermission } from '../entities/user-company-permission.entity';
30
30
  import { AuthDataSourceProvider } from './auth-datasource.provider';
31
31
  export class UserPermissionService {
@@ -140,10 +140,8 @@ export class UserPermissionService {
140
140
  // NOTE: @Inject() required for bundled code - type metadata may be lost during esbuild
141
141
  constructor(dataSourceProvider){
142
142
  _define_property(this, "dataSourceProvider", void 0);
143
- _define_property(this, "logger", void 0);
144
143
  _define_property(this, "_repository", void 0);
145
144
  this.dataSourceProvider = dataSourceProvider;
146
- this.logger = new Logger(UserPermissionService.name);
147
145
  this._repository = null;
148
146
  }
149
147
  }