@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
@@ -97,23 +97,17 @@ let UserService = class UserService extends _classes.RequestScopedApiService {
97
97
  }
98
98
  async ensureRepositoryInitialized() {
99
99
  await super.ensureRepositoryInitialized();
100
- // Initialize permission repository if company feature is enabled
101
100
  const isCompanyFeatureEnabled = this.authConfig.isCompanyFeatureEnabled();
102
101
  if (isCompanyFeatureEnabled && !this.permissionRepository) {
103
102
  [this.permissionRepository] = await this.initializeAdditionalRepositories([
104
103
  _usercompanypermissionentity.UserCompanyPermission
105
104
  ]);
106
105
  }
107
- // Initialize DataSource for transaction support
108
106
  if (!this.dataSource) {
109
107
  this.dataSource = await this.getDataSourceForService();
110
108
  }
111
109
  }
112
- // Custom Methods
113
- /**
114
- * Validate profile ownership, ensure repository initialized, and fetch user.
115
- * Throws ForbiddenException if not owner, NotFoundException if user not found.
116
- */ async getUserForProfile(userId, user) {
110
+ async getUserForProfile(userId, user) {
117
111
  if (userId !== user.id) {
118
112
  throw new _common.ForbiddenException('Cannot access another user\'s profile');
119
113
  }
@@ -128,38 +122,32 @@ let UserService = class UserService extends _classes.RequestScopedApiService {
128
122
  }
129
123
  return userEntity;
130
124
  }
131
- /** Verify email */ async verifyEmail(id) {
132
- // Ensure repository is initialized for custom method
125
+ async verifyEmail(id) {
133
126
  await this.ensureRepositoryInitialized();
134
127
  await this.repository.update(id, {
135
128
  emailVerified: true
136
129
  });
137
- // Clear cache for this user
138
130
  await this.clearCacheForId([
139
131
  {
140
132
  id
141
133
  }
142
134
  ]);
143
135
  }
144
- /** Verify phone */ async verifyPhone(id) {
145
- // Ensure repository is initialized for custom method
136
+ async verifyPhone(id) {
146
137
  await this.ensureRepositoryInitialized();
147
138
  await this.repository.update(id, {
148
139
  phoneVerified: true
149
140
  });
150
- // Clear cache for this user
151
141
  await this.clearCacheForId([
152
142
  {
153
143
  id
154
144
  }
155
145
  ]);
156
146
  }
157
- /** Update user status. When company feature enabled, updates permission isActive for logged user's company. */ async updateStatus(id, isActive, user) {
158
- // Ensure repository is initialized for custom method
147
+ async updateStatus(id, isActive, user) {
159
148
  await this.ensureRepositoryInitialized();
160
149
  const isCompanyFeatureEnabled = this.authConfig.isCompanyFeatureEnabled();
161
150
  if (isCompanyFeatureEnabled && user?.companyId && this.permissionRepository) {
162
- // Company feature enabled - update permission isActive
163
151
  const permission = await this.permissionRepository.findOne({
164
152
  where: {
165
153
  userId: id,
@@ -173,36 +161,30 @@ let UserService = class UserService extends _classes.RequestScopedApiService {
173
161
  permission.isActive = isActive;
174
162
  await this.permissionRepository.save(permission);
175
163
  } else {
176
- // Company feature disabled - update User.isActive directly
177
164
  await this.repository.update(id, {
178
165
  isActive
179
166
  });
180
167
  }
181
- // Clear cache for this user
182
168
  await this.clearCacheForId([
183
169
  {
184
170
  id
185
171
  }
186
172
  ]);
187
173
  }
188
- // ApiService Overrides
189
- /** Convert DTO to entity (hash password before saving) */ async convertSingleDtoToEntity(dto, user) {
190
- // Repository initialization is handled automatically by RequestScopedApiService
174
+ async convertSingleDtoToEntity(dto, user) {
191
175
  const entity = await super.convertSingleDtoToEntity(dto, user);
192
- // Hash password if provided (CreateUserDto has password field)
193
176
  if ('password' in dto && dto.password) {
194
177
  entity.password = await _bcrypt.hash(dto.password, _config.BCRYPT_SALT_ROUNDS);
195
178
  }
196
179
  return entity;
197
180
  }
198
- /** Convert entity to response DTO (removes password). In raw mode with company feature, isActive comes from permission table. */ convertEntityToResponseDto(entity, isRaw) {
181
+ convertEntityToResponseDto(entity, isRaw) {
199
182
  if (isRaw) {
200
183
  return this.convertRawToResponseDto(entity);
201
184
  }
202
185
  return this.convertEntityToDto(entity);
203
186
  }
204
- /** Convert raw query result to response DTO */ convertRawToResponseDto(raw) {
205
- // When raw mode is used with company feature, isActive comes from computed field
187
+ convertRawToResponseDto(raw) {
206
188
  const isActive = raw.user_companyIsActive !== undefined ? Boolean(raw.user_companyIsActive) : raw.user_is_active;
207
189
  return {
208
190
  id: raw.user_id,
@@ -223,7 +205,7 @@ let UserService = class UserService extends _classes.RequestScopedApiService {
223
205
  deletedById: raw.user_deleted_by_id
224
206
  };
225
207
  }
226
- /** Convert entity to response DTO */ convertEntityToDto(entity) {
208
+ convertEntityToDto(entity) {
227
209
  return {
228
210
  id: entity.id,
229
211
  name: entity.name,
@@ -243,10 +225,10 @@ let UserService = class UserService extends _classes.RequestScopedApiService {
243
225
  deletedById: entity.deletedById
244
226
  };
245
227
  }
246
- /** Convert entity list to response DTO list */ convertEntityListToResponseListDto(entities, isRaw) {
228
+ convertEntityListToResponseListDto(entities, isRaw) {
247
229
  return entities.map((entity)=>this.convertEntityToResponseDto(entity, isRaw));
248
230
  }
249
- /** Global search - search by name, email, or phone */ async getGlobalSearchQuery(query, search, _user) {
231
+ async getGlobalSearchQuery(query, search, _user) {
250
232
  query.andWhere('(user.name LIKE :search OR user.email LIKE :search OR user.phone LIKE :search)', {
251
233
  search: `%${search}%`
252
234
  });
@@ -255,26 +237,16 @@ let UserService = class UserService extends _classes.RequestScopedApiService {
255
237
  isRaw: false
256
238
  };
257
239
  }
258
- /** Add company permission-based isActive check when company feature enabled. Returns isRaw: true for computed fields. */ async getExtraManipulateQuery(query, filterAndPaginationDto, user) {
259
- // Repository initialization is handled automatically by RequestScopedApiService
240
+ async getExtraManipulateQuery(query, filterAndPaginationDto, user) {
260
241
  let result = await super.getExtraManipulateQuery(query, filterAndPaginationDto, user);
261
- // Apply user enricher query modifications if available
262
242
  if (this.userEnricher?.enrichListQuery) {
263
243
  await this.userEnricher.enrichListQuery(query, user);
264
244
  }
265
- // Only apply company filtering if:
266
- // 1. Company feature is enabled at bootstrap
267
- // 2. User has company context
268
- // 3. Permission repository is available
269
245
  const isCompanyFeatureEnabled = this.authConfig.isCompanyFeatureEnabled();
270
246
  if (!isCompanyFeatureEnabled) {
271
- // Company feature disabled - return without any company-related modifications
272
- // isActive will come from User entity directly
273
247
  return result;
274
248
  }
275
- // Company feature is enabled - apply company-based filtering
276
249
  if (user?.companyId && this.permissionRepository) {
277
- // Add computed isActive field from permission table
278
250
  query.addSelect(`(SELECT perm.is_active FROM user_company_permissions perm
279
251
  WHERE perm.user_id = user.id
280
252
  AND perm.permission_type = :permissionType
@@ -282,7 +254,6 @@ let UserService = class UserService extends _classes.RequestScopedApiService {
282
254
  LIMIT 1)`, 'user_companyIsActive');
283
255
  query.setParameter('permissionType', _enums.PermissionType.COMPANY);
284
256
  query.setParameter('companyId', user.companyId);
285
- // Add filter for isActive if provided (filters by permission isActive)
286
257
  if (filterAndPaginationDto.filter?.isActive !== undefined) {
287
258
  query.andWhere(`EXISTS (
288
259
  SELECT 1 FROM user_company_permissions perm
@@ -296,7 +267,6 @@ let UserService = class UserService extends _classes.RequestScopedApiService {
296
267
  isActiveValue: filterAndPaginationDto.filter.isActive
297
268
  });
298
269
  }
299
- // Filter users to only show those with company permission
300
270
  query.andWhere(`EXISTS (
301
271
  SELECT 1 FROM user_company_permissions perm
302
272
  WHERE perm.user_id = user.id
@@ -306,7 +276,6 @@ let UserService = class UserService extends _classes.RequestScopedApiService {
306
276
  permissionType: _enums.PermissionType.COMPANY,
307
277
  companyId: user.companyId
308
278
  });
309
- // Return with isRaw: true to get the computed field
310
279
  return {
311
280
  query,
312
281
  isRaw: true
@@ -314,11 +283,8 @@ let UserService = class UserService extends _classes.RequestScopedApiService {
314
283
  }
315
284
  return result;
316
285
  }
317
- /** Insert user. Creates company permission when company feature is enabled. */ async insert(dto, user) {
318
- // Repository initialization is handled automatically by RequestScopedApiService
319
- // Check if company feature is enabled
286
+ async insert(dto, user) {
320
287
  const isCompanyFeatureEnabled = this.authConfig.isCompanyFeatureEnabled();
321
- // If company feature is disabled OR missing dependencies, use parent implementation
322
288
  if (!isCompanyFeatureEnabled || !this.dataSource || !user?.companyId || !this.permissionRepository) {
323
289
  return super.insert(dto, user);
324
290
  }
@@ -326,11 +292,8 @@ let UserService = class UserService extends _classes.RequestScopedApiService {
326
292
  await queryRunner.connect();
327
293
  await queryRunner.startTransaction();
328
294
  try {
329
- // First, insert the user using parent method logic
330
295
  const userEntity = await this.convertSingleDtoToEntity(dto, user);
331
296
  const savedUser = await queryRunner.manager.save(this.repository.target, userEntity);
332
- // Create company permission (repository is guaranteed to exist due to check above)
333
- // Check if permission already exists
334
297
  const existingPermission = await queryRunner.manager.findOne(this.permissionRepository.target, {
335
298
  where: {
336
299
  userId: savedUser.id,
@@ -347,7 +310,6 @@ let UserService = class UserService extends _classes.RequestScopedApiService {
347
310
  });
348
311
  await queryRunner.manager.save(this.permissionRepository.target, permission);
349
312
  }
350
- // Also create branch permission if user has branch context
351
313
  if (user.branchId) {
352
314
  const existingBranchPermission = await queryRunner.manager.findOne(this.permissionRepository.target, {
353
315
  where: {
@@ -381,13 +343,9 @@ let UserService = class UserService extends _classes.RequestScopedApiService {
381
343
  await queryRunner.release();
382
344
  }
383
345
  }
384
- /**
385
- * Get user profile with extras from enricher
386
- * Returns base user data plus any extra data provided by enricher (roles, permissions, etc.)
387
- */ async getProfileWithExtras(userId, user) {
346
+ async getProfileWithExtras(userId, user) {
388
347
  const userEntity = await this.getUserForProfile(userId, user);
389
348
  const userData = this.convertEntityToResponseDto(userEntity, false);
390
- // Get extras from enricher if available
391
349
  let extras;
392
350
  if (this.userEnricher?.getProfileExtras) {
393
351
  extras = await this.userEnricher.getProfileExtras(userId, user);
@@ -397,38 +355,34 @@ let UserService = class UserService extends _classes.RequestScopedApiService {
397
355
  extras
398
356
  };
399
357
  }
400
- /**
401
- * Get enriched user list
402
- * Applies enricher transformations after query execution
403
- */ async getEnrichedList(users, user) {
358
+ async getAll(search, filterAndPaginationDto, user) {
359
+ const result = await super.getAll(search, filterAndPaginationDto, user);
360
+ const enrichedData = await this.getEnrichedList(result.data, user);
361
+ return {
362
+ data: enrichedData,
363
+ total: result.total
364
+ };
365
+ }
366
+ async getEnrichedList(users, user) {
404
367
  if (this.userEnricher?.enrichListItems) {
405
368
  return this.userEnricher.enrichListItems(users, user);
406
369
  }
407
370
  return users;
408
371
  }
409
- // ============================================
410
- // Multi-Step Profile Methods (via Enricher)
411
- // ============================================
412
- /**
413
- * Get profile section definitions from enricher
414
- */ async getProfileSections() {
372
+ async getProfileSections() {
415
373
  if (this.userEnricher?.getProfileSections) {
416
374
  return this.userEnricher.getProfileSections();
417
375
  }
418
376
  return [];
419
377
  }
420
- /**
421
- * Get specific profile section data
422
- */ async getProfileSectionData(userId, sectionId, user) {
378
+ async getProfileSectionData(userId, sectionId, user) {
423
379
  await this.getUserForProfile(userId, user);
424
380
  if (this.userEnricher?.getProfileSectionData) {
425
381
  return this.userEnricher.getProfileSectionData(userId, sectionId, user);
426
382
  }
427
383
  return null;
428
384
  }
429
- /**
430
- * Update specific profile section
431
- */ async updateProfileSection(userId, sectionId, data, user) {
385
+ async updateProfileSection(userId, sectionId, data, user) {
432
386
  const userEntity = await this.getUserForProfile(userId, user);
433
387
  if (!this.dataSource) {
434
388
  throw new _common.BadRequestException('DataSource not available');
@@ -456,23 +410,19 @@ let UserService = class UserService extends _classes.RequestScopedApiService {
456
410
  await queryRunner.release();
457
411
  }
458
412
  }
459
- /**
460
- * Get profile completion percentage
461
- */ async getProfileCompletion(userId, user) {
413
+ async getProfileCompletion(userId, user) {
462
414
  await this.getUserForProfile(userId, user);
463
415
  if (this.userEnricher?.calculateProfileCompletion) {
464
416
  return this.userEnricher.calculateProfileCompletion(userId, user);
465
417
  }
466
- return 100; // Default to 100% if no enricher
418
+ return 100;
467
419
  }
468
- /** Update user profile with password handling and extras */ async profile(dto, user) {
469
- // Ensure repository and dataSource are initialized
420
+ async profile(dto, user) {
470
421
  await this.ensureRepositoryInitialized();
471
422
  if (!this.dataSource) {
472
423
  throw new _common.BadRequestException('DataSource not available');
473
424
  }
474
425
  const userId = dto.id ?? user.id;
475
- // Validate extras if enricher provides validation
476
426
  if (dto.extras && this.userEnricher?.validateProfileExtras) {
477
427
  await this.userEnricher.validateProfileExtras(userId, dto.extras, user);
478
428
  }
@@ -488,9 +438,7 @@ let UserService = class UserService extends _classes.RequestScopedApiService {
488
438
  if (!findUser) {
489
439
  throw new _common.NotFoundException('User not found');
490
440
  }
491
- // Handle password update
492
441
  if (dto.password) {
493
- // If updating own profile, require old password verification
494
442
  const isOwnProfile = !dto.id || dto.id === user.id;
495
443
  if (isOwnProfile) {
496
444
  if (!dto.oldPassword) {
@@ -503,12 +451,9 @@ let UserService = class UserService extends _classes.RequestScopedApiService {
503
451
  }
504
452
  findUser.password = await _bcrypt.hash(dto.password, _config.BCRYPT_SALT_ROUNDS);
505
453
  }
506
- // Merge other fields (excluding password, oldPassword, extras, and sensitive flags)
507
- // Users cannot self-modify emailVerified, phoneVerified, or isActive via profile update
508
454
  const { password, oldPassword, extras, emailVerified, phoneVerified, isActive, ...restDto } = dto;
509
455
  Object.assign(findUser, restDto);
510
456
  await queryRunner.manager.save(this.repository.target, findUser);
511
- // Handle extras update via enricher
512
457
  if (extras && this.userEnricher?.updateProfileExtras) {
513
458
  await this.userEnricher.updateProfileExtras(userId, extras, queryRunner);
514
459
  }
@@ -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';
@@ -12,6 +12,7 @@ export declare class RegistrationDto {
12
12
  newCompanyName?: string;
13
13
  newCompanyPhone?: string;
14
14
  newCompanyAddress?: string;
15
+ additionalFields?: Record<string, any>;
15
16
  }
16
17
  export declare class RefreshTokenDto {
17
18
  refreshToken?: string;
@@ -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[];
@@ -13,5 +13,6 @@ export declare class PendingRegistration {
13
13
  newCompanyPhone?: string;
14
14
  newCompanyAddress?: string;
15
15
  } | null;
16
+ additionalFields: Record<string, any> | null;
16
17
  createdAt: Date;
17
18
  }
@@ -34,26 +34,16 @@ import { ApiBearerAuth, ApiBody, ApiExtraModels, ApiHeader, ApiOperation, ApiRes
34
34
  import { SkipThrottle, Throttle } from '@nestjs/throttler';
35
35
  import { Request } from 'express';
36
36
  import { DEFAULT_COOKIE_NAME } from '../config';
37
- import { ChangePasswordDto, CompanySelectionResponseDto, ForgotPasswordDto, LoginDto, LoginResponseDto, LoginResponseRequiresEmailVerificationDto, MeResponseDto, RefreshTokenDto, RegistrationDto, RegistrationResponseDto, ResendVerificationDto, ResetPasswordDto, VerifyEmailDto } from '../dtos/authentication.dto';
37
+ import { ChangePasswordDto, CompanySelectionResponseDto, LoginDto, LoginResponseDto, LoginResponseRequiresEmailVerificationDto, MeResponseDto, RefreshTokenDto, RegistrationDto, RegistrationResponseDto } from '../dtos/authentication.dto';
38
38
  import { ClearToken } from '../interceptors/clear-token.interceptor';
39
39
  import { SetToken } from '../interceptors/set-token.interceptor';
40
40
  import { AuthConfigService } from '../services/auth-config.service';
41
- import { AuthEmailService } from '../services/auth-email.service';
42
41
  import { AuthenticationService } from '../services/authentication.service';
43
42
  export class AuthenticationController {
44
43
  buildAuthUrl(req, path) {
45
44
  const frontendUrl = this.authConfig?.getFrontendUrl();
46
45
  return frontendUrl ? `${frontendUrl}${path}` : `${req.protocol}://${req.get('host')}${path}`;
47
46
  }
48
- get emailService() {
49
- if (!this.authEmailService) {
50
- throw new Error('Email service is not configured');
51
- }
52
- return this.authEmailService;
53
- }
54
- get isEmailEnabled() {
55
- return !!this.authEmailService;
56
- }
57
47
  async login(loginDto) {
58
48
  const result = await this.authService.login(loginDto.email, loginDto.password);
59
49
  if ('requiresEmailVerification' in result) {
@@ -99,56 +89,11 @@ export class AuthenticationController {
99
89
  message: 'Password changed successfully'
100
90
  };
101
91
  }
102
- async forgotPassword(req, dto) {
103
- if (!this.isEmailEnabled) {
104
- return {
105
- success: false,
106
- message: 'Email service is not configured'
107
- };
108
- }
109
- return this.emailService.forgotPassword(dto.email, this.buildAuthUrl(req, '/auth/reset-password'));
110
- }
111
- async resetPassword(dto) {
112
- if (!this.isEmailEnabled) {
113
- return {
114
- success: false,
115
- message: 'Email service is not configured'
116
- };
117
- }
118
- return this.emailService.resetPassword(dto.token, dto.newPassword);
119
- }
120
- async resendVerification(req, dto) {
121
- if (!this.isEmailEnabled) {
122
- return {
123
- success: false,
124
- message: 'Email service is not configured'
125
- };
126
- }
127
- return this.emailService.resendVerificationEmail(dto.email, this.buildAuthUrl(req, '/auth/verify-email'));
128
- }
129
- /** Verify email - Verify email using token. Handles both pending registration and existing user verification. */ async verifyEmail(dto) {
130
- if (!this.isEmailEnabled) {
131
- return {
132
- success: false,
133
- message: 'Email service is not configured'
134
- };
135
- }
136
- const result = await this.emailService.verifyEmail(dto.token);
137
- if (result.type === 'pending') {
138
- return this.authService.createUserFromPendingRegistration(result.pending);
139
- }
140
- return {
141
- success: true,
142
- message: result.message
143
- };
144
- }
145
- constructor(authService, authConfig, authEmailService){
92
+ constructor(authService, authConfig){
146
93
  _define_property(this, "authService", void 0);
147
94
  _define_property(this, "authConfig", void 0);
148
- _define_property(this, "authEmailService", void 0);
149
95
  this.authService = authService;
150
96
  this.authConfig = authConfig;
151
- this.authEmailService = authEmailService;
152
97
  }
153
98
  }
154
99
  _ts_decorate([
@@ -427,131 +372,15 @@ _ts_decorate([
427
372
  ]),
428
373
  _ts_metadata("design:returntype", Promise)
429
374
  ], AuthenticationController.prototype, "changePassword", null);
430
- _ts_decorate([
431
- Post('forgot-password'),
432
- HttpCode(HttpStatus.OK),
433
- Throttle({
434
- default: {
435
- limit: 3,
436
- ttl: 300000
437
- }
438
- }),
439
- ApiOperation({
440
- summary: 'Request password reset email'
441
- }),
442
- ApiBody({
443
- type: ForgotPasswordDto
444
- }),
445
- ApiResponse({
446
- status: 200,
447
- type: MessageResponseDto
448
- }),
449
- _ts_param(0, Req()),
450
- _ts_param(1, Body()),
451
- _ts_metadata("design:type", Function),
452
- _ts_metadata("design:paramtypes", [
453
- typeof Request === "undefined" ? Object : Request,
454
- typeof ForgotPasswordDto === "undefined" ? Object : ForgotPasswordDto
455
- ]),
456
- _ts_metadata("design:returntype", Promise)
457
- ], AuthenticationController.prototype, "forgotPassword", null);
458
- _ts_decorate([
459
- Post('reset-password'),
460
- HttpCode(HttpStatus.OK),
461
- Throttle({
462
- default: {
463
- limit: 5,
464
- ttl: 900000
465
- }
466
- }),
467
- ApiOperation({
468
- summary: 'Reset password using token'
469
- }),
470
- ApiBody({
471
- type: ResetPasswordDto
472
- }),
473
- ApiResponse({
474
- status: 200,
475
- type: MessageResponseDto
476
- }),
477
- _ts_param(0, Body()),
478
- _ts_metadata("design:type", Function),
479
- _ts_metadata("design:paramtypes", [
480
- typeof ResetPasswordDto === "undefined" ? Object : ResetPasswordDto
481
- ]),
482
- _ts_metadata("design:returntype", Promise)
483
- ], AuthenticationController.prototype, "resetPassword", null);
484
- _ts_decorate([
485
- Post('resend-verification'),
486
- HttpCode(HttpStatus.OK),
487
- Throttle({
488
- default: {
489
- limit: 3,
490
- ttl: 300000
491
- }
492
- }),
493
- ApiOperation({
494
- summary: 'Resend email verification link'
495
- }),
496
- ApiBody({
497
- type: ResendVerificationDto
498
- }),
499
- ApiResponse({
500
- status: 200,
501
- type: MessageResponseDto
502
- }),
503
- _ts_param(0, Req()),
504
- _ts_param(1, Body()),
505
- _ts_metadata("design:type", Function),
506
- _ts_metadata("design:paramtypes", [
507
- typeof Request === "undefined" ? Object : Request,
508
- typeof ResendVerificationDto === "undefined" ? Object : ResendVerificationDto
509
- ]),
510
- _ts_metadata("design:returntype", Promise)
511
- ], AuthenticationController.prototype, "resendVerification", null);
512
- _ts_decorate([
513
- Post('verify-email'),
514
- HttpCode(HttpStatus.OK),
515
- Throttle({
516
- default: {
517
- limit: 10,
518
- ttl: 60000
519
- }
520
- }),
521
- UseInterceptors(SetToken),
522
- ApiOperation({
523
- summary: 'Verify email using token'
524
- }),
525
- ApiBody({
526
- type: VerifyEmailDto
527
- }),
528
- ApiResponse({
529
- status: 200,
530
- type: MessageResponseDto
531
- }),
532
- ApiResponse({
533
- status: 200,
534
- type: RegistrationResponseDto
535
- }),
536
- _ts_param(0, Body()),
537
- _ts_metadata("design:type", Function),
538
- _ts_metadata("design:paramtypes", [
539
- typeof VerifyEmailDto === "undefined" ? Object : VerifyEmailDto
540
- ]),
541
- _ts_metadata("design:returntype", Promise)
542
- ], AuthenticationController.prototype, "verifyEmail", null);
543
375
  AuthenticationController = _ts_decorate([
544
376
  ApiTags('Authentication'),
545
377
  Controller('auth'),
546
378
  _ts_param(0, Inject(AuthenticationService)),
547
379
  _ts_param(1, Optional()),
548
380
  _ts_param(1, Inject(AuthConfigService)),
549
- _ts_param(2, Optional()),
550
- _ts_param(2, Inject(AuthEmailService)),
551
381
  _ts_metadata("design:type", Function),
552
382
  _ts_metadata("design:paramtypes", [
553
383
  typeof AuthenticationService === "undefined" ? Object : AuthenticationService,
554
- typeof AuthConfigService === "undefined" ? Object : AuthConfigService,
555
- typeof AuthEmailService === "undefined" ? Object : AuthEmailService
384
+ typeof AuthConfigService === "undefined" ? Object : AuthConfigService
556
385
  ])
557
386
  ], AuthenticationController);