@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.
- package/README.md +610 -95
- package/cjs/controllers/authentication.controller.js +2 -173
- package/cjs/controllers/email-verification.controller.js +220 -0
- package/cjs/controllers/index.js +1 -0
- package/cjs/dtos/authentication.dto.js +12 -2
- package/cjs/entities/index.js +16 -17
- package/cjs/entities/pending-registration.entity.js +9 -0
- package/cjs/modules/auth.module.js +33 -24
- package/cjs/services/auth-config.service.js +11 -7
- package/cjs/services/auth-datasource.provider.js +15 -27
- package/cjs/services/auth-email.service.js +8 -33
- package/cjs/services/authentication.service.js +123 -99
- package/cjs/services/user.service.js +28 -83
- package/controllers/authentication.controller.d.ts +2 -10
- package/controllers/email-verification.controller.d.ts +20 -0
- package/controllers/index.d.ts +1 -0
- package/dtos/authentication.dto.d.ts +1 -0
- package/entities/index.d.ts +5 -10
- package/entities/pending-registration.entity.d.ts +1 -0
- package/fesm/controllers/authentication.controller.js +3 -174
- package/fesm/controllers/email-verification.controller.js +210 -0
- package/fesm/controllers/index.js +1 -0
- package/fesm/dtos/authentication.dto.js +32 -25
- package/fesm/entities/index.js +17 -9
- package/fesm/entities/pending-registration.entity.js +9 -0
- package/fesm/interfaces/user-enricher.interface.js +2 -24
- package/fesm/modules/auth.module.js +35 -26
- package/fesm/services/auth-config.service.js +11 -7
- package/fesm/services/auth-datasource.provider.js +15 -27
- package/fesm/services/auth-email.service.js +8 -33
- package/fesm/services/authentication.service.js +124 -100
- package/fesm/services/user.service.js +28 -83
- package/interfaces/user-enricher.interface.d.ts +3 -2
- package/modules/auth.module.d.ts +3 -1
- package/package.json +3 -3
- package/services/auth-config.service.d.ts +1 -0
- package/services/auth-datasource.provider.d.ts +1 -0
- package/services/auth-email.service.d.ts +1 -0
- package/services/authentication.service.d.ts +4 -1
- package/services/user.service.d.ts +5 -0
package/README.md
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
# Authentication Package Guide
|
|
2
2
|
|
|
3
3
|
> **Package:** `@flusys/nestjs-auth`
|
|
4
|
+
> **Version:** 3.0.0
|
|
4
5
|
> **Type:** Authentication system with JWT, email verification, multi-tenant, and company/branch support
|
|
5
6
|
|
|
6
7
|
## Table of Contents
|
|
@@ -17,6 +18,9 @@
|
|
|
17
18
|
- [Email Verification Flow](#email-verification-flow)
|
|
18
19
|
- [User Management](#user-management)
|
|
19
20
|
- [No-IAM Mode](#no-iam-mode)
|
|
21
|
+
- [JWT Strategy](#jwt-strategy)
|
|
22
|
+
- [Interceptors](#interceptors)
|
|
23
|
+
- [Validators](#validators)
|
|
20
24
|
- [API Reference](#api-reference)
|
|
21
25
|
|
|
22
26
|
---
|
|
@@ -153,6 +157,7 @@ interface AuthModuleOptions {
|
|
|
153
157
|
bootstrapAppConfig?: {
|
|
154
158
|
databaseMode: 'single' | 'multi-tenant';
|
|
155
159
|
enableCompanyFeature: boolean;
|
|
160
|
+
enableEmailVerification?: boolean; // Default: true
|
|
156
161
|
};
|
|
157
162
|
config?: {
|
|
158
163
|
defaultDatabaseConfig?: IDatabaseConfig;
|
|
@@ -169,6 +174,13 @@ interface AuthModuleOptions {
|
|
|
169
174
|
}
|
|
170
175
|
```
|
|
171
176
|
|
|
177
|
+
**Bootstrap Configuration Flags:**
|
|
178
|
+
|
|
179
|
+
| Flag | Type | Default | Effect |
|
|
180
|
+
|------|------|---------|--------|
|
|
181
|
+
| `enableCompanyFeature` | `boolean` | `false` | Enables company/branch entities and APIs |
|
|
182
|
+
| `enableEmailVerification` | `boolean` | `true` | When `false`: excludes `AuthEmailService`, hides email-related APIs (forgot-password, reset-password, verify-email, resend-verification), and excludes `PendingRegistration` entity from migrations |
|
|
183
|
+
|
|
172
184
|
## Constants
|
|
173
185
|
|
|
174
186
|
```typescript
|
|
@@ -192,22 +204,53 @@ export const TOKEN_REVOKED_PREFIX = 'auth:revoked';
|
|
|
192
204
|
|
|
193
205
|
### Entity Groups
|
|
194
206
|
|
|
195
|
-
|
|
196
|
-
// Core entities (always loaded)
|
|
197
|
-
export const CoreEntities = [User, UserToken, PendingRegistration];
|
|
207
|
+
The auth module organizes entities into groups based on feature flags:
|
|
198
208
|
|
|
199
|
-
|
|
200
|
-
|
|
209
|
+
```typescript
|
|
210
|
+
// Internal entity groups (not exported directly)
|
|
211
|
+
// Base entities: User, UserToken
|
|
212
|
+
// Email entities: PendingRegistration
|
|
213
|
+
// Company entities: Company, CompanyBranch, UserCompanyPermission
|
|
214
|
+
|
|
215
|
+
// Exported interface for configuration
|
|
216
|
+
export interface IAuthEntitiesConfig {
|
|
217
|
+
enableCompanyFeature?: boolean;
|
|
218
|
+
enableEmailVerification?: boolean; // Default: true
|
|
219
|
+
}
|
|
201
220
|
|
|
202
|
-
//
|
|
203
|
-
export
|
|
221
|
+
// Get entities based on feature flags (exported)
|
|
222
|
+
export function getEntitiesByConfig(config: IAuthEntitiesConfig): any[] {
|
|
223
|
+
const { enableCompanyFeature = false, enableEmailVerification = true } = config;
|
|
204
224
|
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
225
|
+
const entities = [User, UserToken];
|
|
226
|
+
if (enableEmailVerification) entities.push(PendingRegistration);
|
|
227
|
+
if (enableCompanyFeature) entities.push(Company, CompanyBranch, UserCompanyPermission);
|
|
228
|
+
return entities;
|
|
208
229
|
}
|
|
209
230
|
```
|
|
210
231
|
|
|
232
|
+
**Usage:**
|
|
233
|
+
```typescript
|
|
234
|
+
import { getEntitiesByConfig } from '@flusys/nestjs-auth/entities';
|
|
235
|
+
|
|
236
|
+
// Get entities for single database without company feature
|
|
237
|
+
const entities = getEntitiesByConfig({ enableCompanyFeature: false });
|
|
238
|
+
// Returns: [User, UserToken, PendingRegistration]
|
|
239
|
+
|
|
240
|
+
// Get entities with company feature, no email verification
|
|
241
|
+
const entities = getEntitiesByConfig({ enableCompanyFeature: true, enableEmailVerification: false });
|
|
242
|
+
// Returns: [User, UserToken, Company, CompanyBranch, UserCompanyPermission]
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
**Entity Selection by Feature Flags:**
|
|
246
|
+
|
|
247
|
+
| enableEmailVerification | enableCompanyFeature | Entities |
|
|
248
|
+
|------------------------|---------------------|----------|
|
|
249
|
+
| `true` (default) | `false` | User, UserToken, PendingRegistration |
|
|
250
|
+
| `true` | `true` | All entities |
|
|
251
|
+
| `false` | `false` | User, UserToken only |
|
|
252
|
+
| `false` | `true` | User, UserToken, Company, CompanyBranch, UserCompanyPermission |
|
|
253
|
+
|
|
211
254
|
### User Entity
|
|
212
255
|
|
|
213
256
|
Extends `UserRoot` from `@flusys/nestjs-shared`:
|
|
@@ -271,6 +314,7 @@ Stores registration data until email verification (prevents garbage accounts):
|
|
|
271
314
|
| `token` | `varchar(64)` | SHA-256 hashed verification token |
|
|
272
315
|
| `expiresAt` | `timestamp` | Expiration (24 hours) |
|
|
273
316
|
| `companyData` | `json` | Company registration data |
|
|
317
|
+
| `additionalFields` | `json` | Extension fields for USER_ENRICHER |
|
|
274
318
|
| `createdAt` | `timestamp` | Auto-generated |
|
|
275
319
|
|
|
276
320
|
**Indexes:**
|
|
@@ -283,25 +327,48 @@ Stores registration data until email verification (prevents garbage accounts):
|
|
|
283
327
|
| Field | Type | Description |
|
|
284
328
|
|-------|------|-------------|
|
|
285
329
|
| `id` | `uuid` | Primary key |
|
|
286
|
-
| `
|
|
287
|
-
| `
|
|
288
|
-
| `
|
|
289
|
-
| `
|
|
290
|
-
| `
|
|
291
|
-
| `
|
|
330
|
+
| `readOnly` | `boolean` | Read-only flag (default: false) |
|
|
331
|
+
| `name` | `varchar(255)` | Company name (unique) |
|
|
332
|
+
| `slug` | `varchar(255)` | URL-friendly identifier (unique) |
|
|
333
|
+
| `logoId` | `char(36)` | Reference to storage file |
|
|
334
|
+
| `address` | `text` | Company address |
|
|
335
|
+
| `phone` | `varchar(50)` | Contact phone |
|
|
336
|
+
| `email` | `varchar(255)` | Contact email |
|
|
337
|
+
| `website` | `varchar(100)` | Company website URL |
|
|
338
|
+
| `serial` | `int` | Display order |
|
|
339
|
+
| `isActive` | `boolean` | Company status (default: true) |
|
|
340
|
+
| `settings` | `json` | Company-specific settings |
|
|
341
|
+
| `additionalFields` | `json` | Extension fields |
|
|
342
|
+
| `createdAt` | `timestamp` | Auto-generated |
|
|
343
|
+
| `updatedAt` | `timestamp` | Auto-updated |
|
|
344
|
+
|
|
345
|
+
**Relations:**
|
|
346
|
+
- `branches` - One-to-Many relation to CompanyBranch
|
|
292
347
|
|
|
293
348
|
### CompanyBranch Entity
|
|
294
349
|
|
|
295
350
|
| Field | Type | Description |
|
|
296
351
|
|-------|------|-------------|
|
|
297
352
|
| `id` | `uuid` | Primary key |
|
|
353
|
+
| `readOnly` | `boolean` | Read-only flag (default: false) |
|
|
298
354
|
| `name` | `varchar(255)` | Branch name |
|
|
299
|
-
| `slug` | `varchar(255)` | URL-friendly identifier |
|
|
300
|
-
| `
|
|
301
|
-
| `
|
|
355
|
+
| `slug` | `varchar(255)` | URL-friendly identifier (unique per company) |
|
|
356
|
+
| `logoId` | `char(36)` | Reference to storage file |
|
|
357
|
+
| `address` | `text` | Branch address |
|
|
358
|
+
| `phone` | `varchar(50)` | Branch phone |
|
|
359
|
+
| `email` | `varchar(255)` | Branch email |
|
|
302
360
|
| `serial` | `int` | Display order |
|
|
303
|
-
| `
|
|
304
|
-
| `
|
|
361
|
+
| `isActive` | `boolean` | Branch status (default: true) |
|
|
362
|
+
| `additionalFields` | `json` | Extension fields |
|
|
363
|
+
| `parentId` | `uuid` | Parent branch (for hierarchical branches) |
|
|
364
|
+
| `companyId` | `uuid` | Parent company ID |
|
|
365
|
+
| `createdAt` | `timestamp` | Auto-generated |
|
|
366
|
+
| `updatedAt` | `timestamp` | Auto-updated |
|
|
367
|
+
|
|
368
|
+
**Relations:**
|
|
369
|
+
- `company` - Many-to-One relation to Company (CASCADE delete)
|
|
370
|
+
- `parent` - Many-to-One relation to self (hierarchical, CASCADE delete)
|
|
371
|
+
- `children` - One-to-Many relation to self
|
|
305
372
|
|
|
306
373
|
### UserCompanyPermission Entity (Polymorphic)
|
|
307
374
|
|
|
@@ -316,9 +383,22 @@ enum PermissionType {
|
|
|
316
383
|
|-------|------|-------------|
|
|
317
384
|
| `id` | `uuid` | Primary key |
|
|
318
385
|
| `userId` | `uuid` | Reference to user |
|
|
319
|
-
| `permissionType` | `
|
|
386
|
+
| `permissionType` | `varchar(50)` | company or branch |
|
|
320
387
|
| `targetId` | `uuid` | Company ID or Branch ID |
|
|
321
|
-
| `
|
|
388
|
+
| `metadata` | `json` | Optional metadata for the permission |
|
|
389
|
+
| `isActive` | `boolean` | Permission status (default: true) |
|
|
390
|
+
| `createdAt` | `timestamp` | Auto-generated |
|
|
391
|
+
| `updatedAt` | `timestamp` | Auto-updated |
|
|
392
|
+
|
|
393
|
+
**Indexes:**
|
|
394
|
+
- Unique index on `(userId, permissionType, targetId)`
|
|
395
|
+
- Index on `(userId, permissionType)`
|
|
396
|
+
- Index on `(permissionType, targetId)`
|
|
397
|
+
|
|
398
|
+
**Relations:**
|
|
399
|
+
- `user` - Many-to-One relation to User (CASCADE delete)
|
|
400
|
+
- `company` - Many-to-One relation to Company (no FK constraint - polymorphic)
|
|
401
|
+
- `branch` - Many-to-One relation to CompanyBranch (no FK constraint - polymorphic)
|
|
322
402
|
|
|
323
403
|
## Provider Interfaces
|
|
324
404
|
|
|
@@ -370,6 +450,8 @@ Extends user list and profile without modifying base package:
|
|
|
370
450
|
|
|
371
451
|
```typescript
|
|
372
452
|
interface IUserEnricher {
|
|
453
|
+
// ===== List Enrichment =====
|
|
454
|
+
|
|
373
455
|
/** Enrich user list query with extra joins/selects */
|
|
374
456
|
enrichListQuery?(
|
|
375
457
|
query: SelectQueryBuilder<User>,
|
|
@@ -382,13 +464,15 @@ interface IUserEnricher {
|
|
|
382
464
|
user: ILoggedUserInfo | null,
|
|
383
465
|
): Promise<IEnrichedUser[]>;
|
|
384
466
|
|
|
467
|
+
// ===== Profile Enrichment =====
|
|
468
|
+
|
|
385
469
|
/** Get extra profile data (roles, permissions, sections) */
|
|
386
470
|
getProfileExtras?(
|
|
387
471
|
userId: string,
|
|
388
472
|
user: ILoggedUserInfo,
|
|
389
473
|
): Promise<IProfileExtras>;
|
|
390
474
|
|
|
391
|
-
/** Handle profile update with extra fields */
|
|
475
|
+
/** Handle profile update with extra fields (within transaction) */
|
|
392
476
|
updateProfileExtras?(
|
|
393
477
|
userId: string,
|
|
394
478
|
extras: Record<string, any>,
|
|
@@ -402,27 +486,92 @@ interface IUserEnricher {
|
|
|
402
486
|
user: ILoggedUserInfo,
|
|
403
487
|
): Promise<void>;
|
|
404
488
|
|
|
405
|
-
// Multi-Step Profile Methods
|
|
489
|
+
// ===== Multi-Step Profile Methods =====
|
|
490
|
+
|
|
491
|
+
/** Get profile section definitions for multi-step profiles */
|
|
406
492
|
getProfileSections?(): IProfileSection[];
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
493
|
+
|
|
494
|
+
/** Get specific section data for a user */
|
|
495
|
+
getProfileSectionData?(
|
|
496
|
+
userId: string,
|
|
497
|
+
sectionId: string,
|
|
498
|
+
user: ILoggedUserInfo,
|
|
499
|
+
): Promise<IProfileSectionData>;
|
|
500
|
+
|
|
501
|
+
/** Update specific profile section (within transaction) */
|
|
502
|
+
updateProfileSection?(
|
|
503
|
+
userId: string,
|
|
504
|
+
sectionId: string,
|
|
505
|
+
data: Record<string, any>,
|
|
506
|
+
queryRunner: QueryRunner,
|
|
507
|
+
): Promise<void>;
|
|
508
|
+
|
|
509
|
+
/** Handle file upload for profile section */
|
|
510
|
+
handleSectionFileUpload?(
|
|
511
|
+
userId: string,
|
|
512
|
+
sectionId: string,
|
|
513
|
+
field: string,
|
|
514
|
+
fileInfo: { name: string; url: string; size: number; type: string },
|
|
515
|
+
queryRunner: QueryRunner,
|
|
516
|
+
): Promise<IProfileFile>;
|
|
517
|
+
|
|
518
|
+
/** Handle file deletion for profile section */
|
|
519
|
+
handleSectionFileDelete?(
|
|
520
|
+
userId: string,
|
|
521
|
+
sectionId: string,
|
|
522
|
+
field: string,
|
|
523
|
+
fileId: string,
|
|
524
|
+
queryRunner: QueryRunner,
|
|
525
|
+
): Promise<void>;
|
|
526
|
+
|
|
527
|
+
/** Calculate profile completion percentage (0-100) */
|
|
528
|
+
calculateProfileCompletion?(
|
|
529
|
+
userId: string,
|
|
530
|
+
user: ILoggedUserInfo,
|
|
531
|
+
): Promise<number>;
|
|
532
|
+
|
|
533
|
+
// ===== Registration Hook =====
|
|
534
|
+
|
|
535
|
+
/**
|
|
536
|
+
* Hook called after user is created during registration
|
|
537
|
+
* Runs within the same database transaction as user creation
|
|
538
|
+
* Use this to create related entities (e.g., UserProfileInfo)
|
|
539
|
+
* Throw error to rollback the entire registration
|
|
540
|
+
*/
|
|
541
|
+
onUserCreated?(
|
|
542
|
+
userId: string,
|
|
543
|
+
additionalFields: Record<string, any> | null,
|
|
544
|
+
queryRunner: QueryRunner,
|
|
545
|
+
): Promise<void>;
|
|
412
546
|
}
|
|
413
547
|
```
|
|
414
548
|
|
|
415
|
-
**Profile
|
|
549
|
+
**Profile Related Interfaces:**
|
|
416
550
|
|
|
417
551
|
```typescript
|
|
418
552
|
interface IProfileSection {
|
|
419
|
-
id: string;
|
|
420
|
-
name: string;
|
|
421
|
-
order: number;
|
|
422
|
-
icon?: string;
|
|
423
|
-
required?: boolean;
|
|
424
|
-
hasFileUpload?: boolean;
|
|
425
|
-
editPermission?:
|
|
553
|
+
id: string; // Unique identifier
|
|
554
|
+
name: string; // Display name
|
|
555
|
+
order: number; // Stepper order
|
|
556
|
+
icon?: string; // PrimeNG icon class
|
|
557
|
+
required?: boolean; // Required for completion
|
|
558
|
+
hasFileUpload?: boolean; // Has file fields
|
|
559
|
+
editPermission?: IPermissionLogic; // Required permission
|
|
560
|
+
}
|
|
561
|
+
|
|
562
|
+
interface IProfileSectionData {
|
|
563
|
+
sectionId: string;
|
|
564
|
+
data: Record<string, any>;
|
|
565
|
+
isComplete: boolean;
|
|
566
|
+
files?: IProfileFile[];
|
|
567
|
+
}
|
|
568
|
+
|
|
569
|
+
interface IProfileFile {
|
|
570
|
+
field: string;
|
|
571
|
+
id: string;
|
|
572
|
+
name: string;
|
|
573
|
+
url?: string;
|
|
574
|
+
type?: string;
|
|
426
575
|
}
|
|
427
576
|
|
|
428
577
|
interface IProfileExtras {
|
|
@@ -431,6 +580,73 @@ interface IProfileExtras {
|
|
|
431
580
|
sections?: IProfileSectionData[];
|
|
432
581
|
completionPercentage?: number;
|
|
433
582
|
}
|
|
583
|
+
|
|
584
|
+
interface IProfileRole {
|
|
585
|
+
id: string;
|
|
586
|
+
name: string;
|
|
587
|
+
description?: string | null;
|
|
588
|
+
}
|
|
589
|
+
|
|
590
|
+
interface IProfileAction {
|
|
591
|
+
id: string;
|
|
592
|
+
name: string;
|
|
593
|
+
code: string;
|
|
594
|
+
description?: string | null;
|
|
595
|
+
}
|
|
596
|
+
|
|
597
|
+
type IEnrichedUser = IUser & IProfileExtras;
|
|
598
|
+
```
|
|
599
|
+
|
|
600
|
+
**Registration Hook Example (UserProfileInfo):**
|
|
601
|
+
|
|
602
|
+
```typescript
|
|
603
|
+
// In your consuming app (e.g., FLUSYS-TEMPLATE)
|
|
604
|
+
import { USER_ENRICHER, IUserEnricher } from '@flusys/nestjs-auth';
|
|
605
|
+
import { QueryRunner } from 'typeorm';
|
|
606
|
+
|
|
607
|
+
@Injectable({ scope: Scope.REQUEST })
|
|
608
|
+
export class MyUserEnricher implements IUserEnricher {
|
|
609
|
+
/**
|
|
610
|
+
* Called after user creation, within the same transaction
|
|
611
|
+
* If this throws, the entire registration rolls back
|
|
612
|
+
*/
|
|
613
|
+
async onUserCreated(
|
|
614
|
+
userId: string,
|
|
615
|
+
additionalFields: Record<string, any> | null,
|
|
616
|
+
queryRunner: QueryRunner,
|
|
617
|
+
): Promise<void> {
|
|
618
|
+
if (!additionalFields) return;
|
|
619
|
+
|
|
620
|
+
// Create related entity (e.g., UserProfileInfo)
|
|
621
|
+
const profileInfo = queryRunner.manager.create(UserProfileInfo, {
|
|
622
|
+
userId,
|
|
623
|
+
prevCompanyName: additionalFields.prevCompanyName ?? null,
|
|
624
|
+
prevCompanyLocation: additionalFields.prevCompanyLocation ?? null,
|
|
625
|
+
});
|
|
626
|
+
|
|
627
|
+
await queryRunner.manager.save(UserProfileInfo, profileInfo);
|
|
628
|
+
}
|
|
629
|
+
}
|
|
630
|
+
|
|
631
|
+
// Register the provider
|
|
632
|
+
{
|
|
633
|
+
provide: USER_ENRICHER,
|
|
634
|
+
useClass: MyUserEnricher,
|
|
635
|
+
}
|
|
636
|
+
```
|
|
637
|
+
|
|
638
|
+
**Registration with additionalFields:**
|
|
639
|
+
|
|
640
|
+
```json
|
|
641
|
+
{
|
|
642
|
+
"name": "John Doe",
|
|
643
|
+
"email": "john@example.com",
|
|
644
|
+
"password": "password123",
|
|
645
|
+
"additionalFields": {
|
|
646
|
+
"prevCompanyName": "Acme Corp",
|
|
647
|
+
"prevCompanyLocation": "New York"
|
|
648
|
+
}
|
|
649
|
+
}
|
|
434
650
|
```
|
|
435
651
|
|
|
436
652
|
## Services
|
|
@@ -458,7 +674,7 @@ Token Security: All tokens are stored as SHA-256 hashes. Raw tokens are sent to
|
|
|
458
674
|
| `createPendingRegistration(data)` | Create pending registration with verification email |
|
|
459
675
|
| `forgotPassword(email, resetUrlBase)` | Send password reset email |
|
|
460
676
|
| `resetPassword(token, newPassword)` | Reset password using token |
|
|
461
|
-
| `verifyEmail(token)` | Verify email (pending
|
|
677
|
+
| `verifyEmail(token)` | Verify email (returns `{ type: 'pending', pending }` or `{ type: 'verified', message }`) |
|
|
462
678
|
| `resendVerificationEmail(email, verifyUrlBase)` | Resend verification email |
|
|
463
679
|
| `cleanupExpired()` | Clean up expired tokens and pending registrations |
|
|
464
680
|
|
|
@@ -466,70 +682,204 @@ Token Security: All tokens are stored as SHA-256 hashes. Raw tokens are sent to
|
|
|
466
682
|
- Password Reset: 1 hour
|
|
467
683
|
- Email Verification: 24 hours
|
|
468
684
|
|
|
685
|
+
### AuthenticationService
|
|
686
|
+
|
|
687
|
+
| Method | Description |
|
|
688
|
+
|--------|-------------|
|
|
689
|
+
| `login(email, password)` | Validate credentials and return tokens |
|
|
690
|
+
| `register(dto, verifyUrlBase?)` | Register new user (creates pending registration if email enabled) |
|
|
691
|
+
| `createUserFromPendingRegistration(pending)` | Create user from verified pending registration |
|
|
692
|
+
| `select(sessionId, companyId, branchId)` | Complete company selection after login |
|
|
693
|
+
| `switchCompany(userId, companyId, branchId)` | Switch to different company/branch |
|
|
694
|
+
| `refreshToken(refreshToken)` | Refresh access token |
|
|
695
|
+
| `changePassword(userId, currentPassword, newPassword)` | Change user password |
|
|
696
|
+
| `logout(userId)` | Revoke all tokens for user |
|
|
697
|
+
| `isTokenRevoked(userId, tokenIssuedAt)` | Check if token is revoked |
|
|
698
|
+
| `getUserCompanies(userId)` | Get user's available companies |
|
|
699
|
+
| `getUserBranches(userId, companyId)` | Get user's branches for a company |
|
|
700
|
+
| `getUserInfo(userId, companyId?, branchId?)` | Get current user info |
|
|
701
|
+
|
|
702
|
+
### UserService
|
|
703
|
+
|
|
704
|
+
Extends `RequestScopedApiService` for full CRUD support.
|
|
705
|
+
|
|
706
|
+
| Method | Description |
|
|
707
|
+
|--------|-------------|
|
|
708
|
+
| `insert(dto, user)` | Create user (auto-assigns company permissions) |
|
|
709
|
+
| `verifyEmail(id)` | Mark user email as verified |
|
|
710
|
+
| `verifyPhone(id)` | Mark user phone as verified |
|
|
711
|
+
| `updateStatus(id, isActive, user)` | Update user status (company-aware) |
|
|
712
|
+
| `profile(dto, user)` | Update own profile with optional extras |
|
|
713
|
+
| `getProfileWithExtras(userId, user)` | Get profile with enricher data |
|
|
714
|
+
| `getProfileSections()` | Get profile section definitions |
|
|
715
|
+
| `getProfileSectionData(userId, sectionId, user)` | Get specific section data |
|
|
716
|
+
| `updateProfileSection(userId, sectionId, data, user)` | Update specific section |
|
|
717
|
+
| `getProfileCompletion(userId, user)` | Calculate profile completion % |
|
|
718
|
+
| `getEnrichedList(users, user)` | Enrich user list with extra data |
|
|
719
|
+
|
|
720
|
+
### CompanyService
|
|
721
|
+
|
|
722
|
+
Extends `RequestScopedApiService` for full CRUD support on Company entity.
|
|
723
|
+
|
|
724
|
+
### BranchService
|
|
725
|
+
|
|
726
|
+
Extends `RequestScopedApiService` for full CRUD support on CompanyBranch entity.
|
|
727
|
+
Automatically applies company filter based on logged user context.
|
|
728
|
+
|
|
729
|
+
### UserPermissionService
|
|
730
|
+
|
|
731
|
+
| Method | Description |
|
|
732
|
+
|--------|-------------|
|
|
733
|
+
| `findUserPermissions(userId, type)` | Get all permissions of type for user |
|
|
734
|
+
| `assignPermission(userId, targetId, type, metadata?)` | Assign permission to user |
|
|
735
|
+
| `revokePermission(userId, targetId, type)` | Revoke permission from user |
|
|
736
|
+
| `findUserCompanies(userId)` | Get user's company permissions |
|
|
737
|
+
| `findUserBranches(userId, companyId?)` | Get user's branch permissions |
|
|
738
|
+
|
|
739
|
+
### CompanySelectionSessionService
|
|
740
|
+
|
|
741
|
+
Manages temporary sessions during company/branch selection flow.
|
|
742
|
+
|
|
743
|
+
| Method | Description |
|
|
744
|
+
|--------|-------------|
|
|
745
|
+
| `createSession(userId)` | Create session (returns sessionId, TTL: 5 minutes) |
|
|
746
|
+
| `getSession(sessionId)` | Get session without consuming |
|
|
747
|
+
| `consumeSession(sessionId)` | Get and delete session (one-time use) |
|
|
748
|
+
| `deleteSession(sessionId)` | Delete session |
|
|
749
|
+
|
|
750
|
+
### AuthConfigService
|
|
751
|
+
|
|
752
|
+
Provides configuration access.
|
|
753
|
+
|
|
754
|
+
| Method | Description |
|
|
755
|
+
|--------|-------------|
|
|
756
|
+
| `getDatabaseMode()` | Returns 'single' or 'multi-tenant' |
|
|
757
|
+
| `isMultiTenant()` | Check if multi-tenant mode |
|
|
758
|
+
| `isCompanyFeatureEnabled()` | Check if company feature enabled |
|
|
759
|
+
| `isEmailVerificationEnabled()` | Check if email verification enabled |
|
|
760
|
+
| `getJwtSecret()` | Get JWT secret (throws if not configured) |
|
|
761
|
+
| `getJwtExpiration()` | Get JWT expiration (default: '1h') |
|
|
762
|
+
| `getRefreshTokenSecret()` | Get refresh token secret |
|
|
763
|
+
| `getRefreshTokenExpiration()` | Get refresh expiration (default: '7d') |
|
|
764
|
+
| `getRefreshTokenCookieName()` | Get cookie name (default: 'fsn_refresh_token') |
|
|
765
|
+
| `getFrontendUrl()` | Get frontend URL for email links |
|
|
766
|
+
|
|
767
|
+
### AuthDataSourceProvider
|
|
768
|
+
|
|
769
|
+
Extends `MultiTenantDataSourceService` for dynamic datasource handling.
|
|
770
|
+
|
|
771
|
+
| Method | Description |
|
|
772
|
+
|--------|-------------|
|
|
773
|
+
| `getDataSource()` | Get current tenant's DataSource |
|
|
774
|
+
| `getRepository(entity)` | Get repository for entity |
|
|
775
|
+
| `isCompanyFeatureEnabled(tenant?)` | Check company feature for tenant |
|
|
776
|
+
| `isEmailVerificationEnabled(tenant?)` | Check email verification for tenant |
|
|
777
|
+
| `getAuthEntities()` | Get entities based on feature flags |
|
|
778
|
+
|
|
469
779
|
## API Endpoints
|
|
470
780
|
|
|
781
|
+
> **Note:** All endpoints use POST method following POST-only RPC pattern.
|
|
782
|
+
|
|
471
783
|
### Authentication Endpoints
|
|
472
784
|
|
|
473
|
-
| Endpoint | Method | Description |
|
|
474
|
-
|
|
475
|
-
| `/auth/login` | POST | Login with email/password |
|
|
476
|
-
| `/auth/register` | POST | Register new user |
|
|
477
|
-
| `/auth/refresh` | POST | Refresh access token |
|
|
478
|
-
| `/auth/logout` | POST | Logout (revokes all tokens) |
|
|
479
|
-
| `/auth/change-password` | POST | Change user password |
|
|
480
|
-
| `/auth/me` |
|
|
785
|
+
| Endpoint | Method | Auth | Description |
|
|
786
|
+
|----------|--------|------|-------------|
|
|
787
|
+
| `/auth/login` | POST | No | Login with email/password |
|
|
788
|
+
| `/auth/register` | POST | No | Register new user |
|
|
789
|
+
| `/auth/refresh` | POST | No | Refresh access token |
|
|
790
|
+
| `/auth/logout` | POST | JWT | Logout (revokes all tokens) |
|
|
791
|
+
| `/auth/change-password` | POST | JWT | Change user password |
|
|
792
|
+
| `/auth/me` | POST | JWT | Get current user info |
|
|
793
|
+
|
|
794
|
+
**Rate Limits:**
|
|
795
|
+
- `/auth/login` - 5 attempts per minute
|
|
796
|
+
- `/auth/register` - 3 attempts per minute
|
|
797
|
+
- `/auth/refresh` - 30 attempts per minute
|
|
481
798
|
|
|
482
799
|
### Email Authentication Endpoints
|
|
483
800
|
|
|
484
|
-
| Endpoint | Method | Description |
|
|
485
|
-
|
|
486
|
-
| `/auth/forgot-password` | POST | Request password reset email |
|
|
487
|
-
| `/auth/reset-password` | POST | Reset password using token |
|
|
488
|
-
| `/auth/verify-email` | POST | Verify email using token |
|
|
489
|
-
| `/auth/resend-verification` | POST | Resend email verification link |
|
|
801
|
+
| Endpoint | Method | Auth | Description |
|
|
802
|
+
|----------|--------|------|-------------|
|
|
803
|
+
| `/auth/forgot-password` | POST | No | Request password reset email |
|
|
804
|
+
| `/auth/reset-password` | POST | No | Reset password using token |
|
|
805
|
+
| `/auth/verify-email` | POST | No | Verify email using token |
|
|
806
|
+
| `/auth/resend-verification` | POST | No | Resend email verification link |
|
|
807
|
+
|
|
808
|
+
**Rate Limits:**
|
|
809
|
+
- `/auth/forgot-password` - 3 requests per 5 minutes
|
|
810
|
+
- `/auth/reset-password` - 5 attempts per 15 minutes
|
|
811
|
+
- `/auth/verify-email` - 10 attempts per minute
|
|
812
|
+
- `/auth/resend-verification` - 3 requests per 5 minutes
|
|
490
813
|
|
|
491
|
-
> **Note:** Email endpoints require `AUTH_EMAIL_PROVIDER` to be configured
|
|
814
|
+
> **Note:** Email endpoints require `AUTH_EMAIL_PROVIDER` to be configured and `enableEmailVerification: true`.
|
|
492
815
|
|
|
493
816
|
### Company Selection Endpoints (when company feature enabled)
|
|
494
817
|
|
|
495
|
-
| Endpoint | Method | Description |
|
|
496
|
-
|
|
497
|
-
| `/auth/select` | POST | Select company and branch after login |
|
|
498
|
-
| `/auth/switch-company` | POST | Switch to different company/branch |
|
|
499
|
-
| `/auth/companies` |
|
|
500
|
-
| `/auth/
|
|
818
|
+
| Endpoint | Method | Auth | Description |
|
|
819
|
+
|----------|--------|------|-------------|
|
|
820
|
+
| `/auth/select` | POST | No | Select company and branch after login |
|
|
821
|
+
| `/auth/switch-company` | POST | JWT | Switch to different company/branch |
|
|
822
|
+
| `/auth/get-companies` | POST | JWT | Get user's available companies |
|
|
823
|
+
| `/auth/get-company-branches` | POST | JWT | Get branches for a company |
|
|
501
824
|
|
|
502
825
|
### User Management Endpoints
|
|
503
826
|
|
|
504
|
-
| Endpoint | Method | Description |
|
|
505
|
-
|
|
506
|
-
| `/administration/users/insert` | POST | Create user |
|
|
507
|
-
| `/administration/users/insert-many` | POST | Bulk create users |
|
|
508
|
-
| `/administration/users/get/:id` | POST | Get user by ID |
|
|
509
|
-
| `/administration/users/get-all` | POST | Get paginated user list |
|
|
510
|
-
| `/administration/users/update` | POST | Update user |
|
|
511
|
-
| `/administration/users/update-many` | POST | Bulk update users |
|
|
512
|
-
| `/administration/users/delete` | POST | Delete/restore/permanent delete |
|
|
513
|
-
| `/administration/users/profile` | POST | Update own profile |
|
|
514
|
-
| `/administration/users/:id/verify-email` | POST | Mark email as verified |
|
|
515
|
-
| `/administration/users/:id/verify-phone` | POST | Mark phone as verified |
|
|
516
|
-
| `/administration/users/:id/status` |
|
|
827
|
+
| Endpoint | Method | Auth | Permission | Description |
|
|
828
|
+
|----------|--------|------|------------|-------------|
|
|
829
|
+
| `/administration/users/insert` | POST | JWT | `user.create` | Create user |
|
|
830
|
+
| `/administration/users/insert-many` | POST | JWT | `user.create` | Bulk create users |
|
|
831
|
+
| `/administration/users/get/:id` | POST | JWT | `user.read` | Get user by ID |
|
|
832
|
+
| `/administration/users/get-all` | POST | JWT | `user.read` | Get paginated user list |
|
|
833
|
+
| `/administration/users/update` | POST | JWT | `user.update` | Update user |
|
|
834
|
+
| `/administration/users/update-many` | POST | JWT | `user.update` | Bulk update users |
|
|
835
|
+
| `/administration/users/delete` | POST | JWT | `user.delete` | Delete/restore/permanent delete |
|
|
836
|
+
| `/administration/users/profile` | POST | JWT | - | Update own profile |
|
|
837
|
+
| `/administration/users/:id/verify-email` | POST | JWT | `user.update` | Mark email as verified |
|
|
838
|
+
| `/administration/users/:id/verify-phone` | POST | JWT | `user.update` | Mark phone as verified |
|
|
839
|
+
| `/administration/users/:id/status` | POST | JWT | `user.update` | Update user active status |
|
|
840
|
+
|
|
841
|
+
### User Profile Extensions Endpoints
|
|
842
|
+
|
|
843
|
+
| Endpoint | Method | Auth | Permission | Description |
|
|
844
|
+
|----------|--------|------|------------|-------------|
|
|
845
|
+
| `/administration/users/:id/profile-extras` | POST | JWT | `user.read` | Get profile with enricher extras |
|
|
846
|
+
| `/administration/users/profile-sections` | POST | JWT | `user.read` | Get profile section definitions |
|
|
847
|
+
| `/administration/users/:id/profile-section/:sectionId` | POST | JWT | `user.read` | Get specific section data |
|
|
848
|
+
| `/administration/users/:id/profile-section/:sectionId/update` | POST | JWT | `user.update` | Update specific section |
|
|
849
|
+
| `/administration/users/:id/profile-completion` | POST | JWT | `user.read` | Get profile completion % |
|
|
517
850
|
|
|
518
851
|
### User Permission Endpoints (when company feature enabled)
|
|
519
852
|
|
|
520
|
-
| Endpoint | Method | Description |
|
|
521
|
-
|
|
522
|
-
| `/administration/permissions/user-company/assign` | POST | Batch assign/revoke user-company permissions |
|
|
523
|
-
| `/administration/permissions/user-company` |
|
|
524
|
-
| `/administration/permissions/user-branch/assign` | POST | Batch assign/revoke user-branch permissions |
|
|
525
|
-
| `/administration/permissions/user-branch` |
|
|
526
|
-
|
|
527
|
-
### Company
|
|
528
|
-
|
|
529
|
-
|
|
|
530
|
-
|
|
531
|
-
|
|
|
532
|
-
|
|
|
853
|
+
| Endpoint | Method | Auth | Permission | Description |
|
|
854
|
+
|----------|--------|------|------------|-------------|
|
|
855
|
+
| `/administration/permissions/user-company/assign` | POST | JWT | `user.update` | Batch assign/revoke user-company permissions |
|
|
856
|
+
| `/administration/permissions/get-user-company` | POST | JWT | `user.read` | Get user's assigned companies |
|
|
857
|
+
| `/administration/permissions/user-branch/assign` | POST | JWT | `user.update` | Batch assign/revoke user-branch permissions |
|
|
858
|
+
| `/administration/permissions/get-user-branch` | POST | JWT | `user.read` | Get user's assigned branches |
|
|
859
|
+
|
|
860
|
+
### Company Management Endpoints (when company feature enabled)
|
|
861
|
+
|
|
862
|
+
| Endpoint | Method | Auth | Permission | Description |
|
|
863
|
+
|----------|--------|------|------------|-------------|
|
|
864
|
+
| `/administration/company/insert` | POST | JWT | `company.create` | Create company |
|
|
865
|
+
| `/administration/company/insert-many` | POST | JWT | `company.create` | Bulk create companies |
|
|
866
|
+
| `/administration/company/get/:id` | POST | JWT | `company.read` | Get company by ID |
|
|
867
|
+
| `/administration/company/get-all` | POST | JWT | `company.read` | Get paginated company list |
|
|
868
|
+
| `/administration/company/update` | POST | JWT | `company.update` | Update company |
|
|
869
|
+
| `/administration/company/update-many` | POST | JWT | `company.update` | Bulk update companies |
|
|
870
|
+
| `/administration/company/delete` | POST | JWT | `company.delete` | Delete/restore/permanent delete |
|
|
871
|
+
|
|
872
|
+
### Branch Management Endpoints (when company feature enabled)
|
|
873
|
+
|
|
874
|
+
| Endpoint | Method | Auth | Permission | Description |
|
|
875
|
+
|----------|--------|------|------------|-------------|
|
|
876
|
+
| `/administration/branch/insert` | POST | JWT | `branch.create` | Create branch |
|
|
877
|
+
| `/administration/branch/insert-many` | POST | JWT | `branch.create` | Bulk create branches |
|
|
878
|
+
| `/administration/branch/get/:id` | POST | JWT | `branch.read` | Get branch by ID |
|
|
879
|
+
| `/administration/branch/get-all` | POST | JWT | `branch.read` | Get paginated branch list |
|
|
880
|
+
| `/administration/branch/update` | POST | JWT | `branch.update` | Update branch |
|
|
881
|
+
| `/administration/branch/update-many` | POST | JWT | `branch.update` | Bulk update branches |
|
|
882
|
+
| `/administration/branch/delete` | POST | JWT | `branch.delete` | Delete/restore/permanent delete |
|
|
533
883
|
|
|
534
884
|
## Login Flows
|
|
535
885
|
|
|
@@ -743,6 +1093,22 @@ User Creation (with companyId/branchId)
|
|
|
743
1093
|
}
|
|
744
1094
|
```
|
|
745
1095
|
|
|
1096
|
+
**Registration with extension fields (additionalFields):**
|
|
1097
|
+
```json
|
|
1098
|
+
{
|
|
1099
|
+
"name": "John Doe",
|
|
1100
|
+
"email": "john@example.com",
|
|
1101
|
+
"password": "password123",
|
|
1102
|
+
"additionalFields": {
|
|
1103
|
+
"prevCompanyName": "Acme Corporation",
|
|
1104
|
+
"prevCompanyLocation": "New York, USA",
|
|
1105
|
+
"prevIndustryType": "technology"
|
|
1106
|
+
}
|
|
1107
|
+
}
|
|
1108
|
+
```
|
|
1109
|
+
|
|
1110
|
+
> **Note:** `additionalFields` are passed to the `USER_ENRICHER.onUserCreated` hook within the same database transaction. If the hook throws an error, the entire registration is rolled back, ensuring atomicity.
|
|
1111
|
+
|
|
746
1112
|
## No-IAM Mode
|
|
747
1113
|
|
|
748
1114
|
When not using `@flusys/nestjs-iam` but controllers use `level: 'permission'` security, set wildcard permissions after login:
|
|
@@ -798,13 +1164,112 @@ private async setWildcardPermissions(
|
|
|
798
1164
|
| `user.*` | All user permissions |
|
|
799
1165
|
| `branch.*` | All branch permissions |
|
|
800
1166
|
|
|
1167
|
+
## JWT Strategy
|
|
1168
|
+
|
|
1169
|
+
The `JwtStrategy` is a singleton Passport strategy that validates JWT tokens and extracts user info.
|
|
1170
|
+
|
|
1171
|
+
**Token Payload:**
|
|
1172
|
+
```typescript
|
|
1173
|
+
interface TokenPayload {
|
|
1174
|
+
id: string; // User ID
|
|
1175
|
+
email: string; // User email
|
|
1176
|
+
type: 'access' | 'refresh'; // Token type
|
|
1177
|
+
profilePictureId?: string; // Profile picture file ID
|
|
1178
|
+
tenantId?: string; // Tenant ID (multi-tenant)
|
|
1179
|
+
iat?: number; // Issued at
|
|
1180
|
+
exp?: number; // Expiration
|
|
1181
|
+
}
|
|
1182
|
+
|
|
1183
|
+
// When company feature enabled
|
|
1184
|
+
interface TokenPayloadWithCompany extends TokenPayload {
|
|
1185
|
+
companyId: string; // Selected company ID
|
|
1186
|
+
branchId?: string; // Selected branch ID (optional)
|
|
1187
|
+
companyLogoId?: string | null; // Company logo file ID
|
|
1188
|
+
branchLogoId?: string | null; // Branch logo file ID
|
|
1189
|
+
}
|
|
1190
|
+
```
|
|
1191
|
+
|
|
1192
|
+
**Validation Flow:**
|
|
1193
|
+
1. Extract token from `Authorization: Bearer <token>` header
|
|
1194
|
+
2. Verify token signature using JWT secret
|
|
1195
|
+
3. Check token revocation status (if cache available)
|
|
1196
|
+
4. Validate user exists and is active
|
|
1197
|
+
5. Return `ILoggedUserInfo` with user context
|
|
1198
|
+
|
|
1199
|
+
**Token Revocation:**
|
|
1200
|
+
- Uses cache to track revoked tokens
|
|
1201
|
+
- Key format: `auth:revoked:{userId}`
|
|
1202
|
+
- Stores timestamp of last logout
|
|
1203
|
+
- Tokens issued before logout timestamp are rejected
|
|
1204
|
+
|
|
1205
|
+
## Interceptors
|
|
1206
|
+
|
|
1207
|
+
### SetToken Interceptor
|
|
1208
|
+
|
|
1209
|
+
Automatically sets refresh token as HTTP-only cookie for browser clients:
|
|
1210
|
+
|
|
1211
|
+
```typescript
|
|
1212
|
+
@UseInterceptors(SetToken)
|
|
1213
|
+
async login(@Body() loginDto: LoginDto) { ... }
|
|
1214
|
+
```
|
|
1215
|
+
|
|
1216
|
+
**Behavior:**
|
|
1217
|
+
- Detects browser requests via `User-Agent` and `x-client-type` header
|
|
1218
|
+
- For browsers: Sets `refreshToken` as HTTP-only cookie, removes from response body
|
|
1219
|
+
- For API/Mobile: Returns `refreshToken` in response body
|
|
1220
|
+
- Cookie options: `httpOnly: true`, `secure: true` (production), `sameSite: 'lax'`
|
|
1221
|
+
|
|
1222
|
+
### ClearToken Interceptor
|
|
1223
|
+
|
|
1224
|
+
Clears refresh token cookie on logout:
|
|
1225
|
+
|
|
1226
|
+
```typescript
|
|
1227
|
+
@UseInterceptors(ClearToken)
|
|
1228
|
+
async logout(@CurrentUser('id') userId: string) { ... }
|
|
1229
|
+
```
|
|
1230
|
+
|
|
1231
|
+
## Validators
|
|
1232
|
+
|
|
1233
|
+
### IsStrongPassword
|
|
1234
|
+
|
|
1235
|
+
Custom password validation decorator:
|
|
1236
|
+
|
|
1237
|
+
```typescript
|
|
1238
|
+
@IsStrongPassword()
|
|
1239
|
+
password!: string;
|
|
1240
|
+
|
|
1241
|
+
// With custom options
|
|
1242
|
+
@IsStrongPassword({ minLength: 12, requireSpecialChar: false })
|
|
1243
|
+
password!: string;
|
|
1244
|
+
```
|
|
1245
|
+
|
|
1246
|
+
**Default Requirements:**
|
|
1247
|
+
- Minimum 8 characters
|
|
1248
|
+
- Maximum 128 characters
|
|
1249
|
+
- At least one uppercase letter
|
|
1250
|
+
- At least one lowercase letter
|
|
1251
|
+
- At least one number
|
|
1252
|
+
- At least one special character (`!@#$%^&*()_+-=[]{}...`)
|
|
1253
|
+
|
|
1254
|
+
**Custom Options:**
|
|
1255
|
+
```typescript
|
|
1256
|
+
interface PasswordComplexityOptions {
|
|
1257
|
+
minLength?: number; // Default: 8
|
|
1258
|
+
maxLength?: number; // Default: 128
|
|
1259
|
+
requireUppercase?: boolean; // Default: true
|
|
1260
|
+
requireLowercase?: boolean; // Default: true
|
|
1261
|
+
requireNumber?: boolean; // Default: true
|
|
1262
|
+
requireSpecialChar?: boolean; // Default: true
|
|
1263
|
+
}
|
|
1264
|
+
```
|
|
1265
|
+
|
|
801
1266
|
## API Reference
|
|
802
1267
|
|
|
803
1268
|
### Exports
|
|
804
1269
|
|
|
805
1270
|
```typescript
|
|
806
1271
|
// Config
|
|
807
|
-
export { AUTH_MODULE_OPTIONS, BCRYPT_SALT_ROUNDS, DEFAULT_COOKIE_NAME, MAX_COOKIE_BYTES, SESSION_CACHE_PREFIX, TOKEN_REVOKED_PREFIX } from './config';
|
|
1272
|
+
export { AUTH_MODULE_OPTIONS, USER_ENRICHER, BCRYPT_SALT_ROUNDS, DEFAULT_COOKIE_NAME, MAX_COOKIE_BYTES, SESSION_CACHE_PREFIX, TOKEN_REVOKED_PREFIX } from './config';
|
|
808
1273
|
|
|
809
1274
|
// Entities
|
|
810
1275
|
export { User } from './entities/user.entity';
|
|
@@ -813,16 +1278,19 @@ export { PendingRegistration } from './entities/pending-registration.entity';
|
|
|
813
1278
|
export { Company } from './entities/company.entity';
|
|
814
1279
|
export { CompanyBranch } from './entities/company-branch.entity';
|
|
815
1280
|
export { UserCompanyPermission, PermissionType } from './entities/user-company-permission.entity';
|
|
816
|
-
export {
|
|
1281
|
+
export { getEntitiesByConfig, IAuthEntitiesConfig } from './entities';
|
|
817
1282
|
|
|
818
1283
|
// Enums
|
|
819
1284
|
export { PermissionType } from './enums';
|
|
820
1285
|
|
|
821
1286
|
// Interfaces
|
|
822
1287
|
export { IAuthEmailProvider, AUTH_EMAIL_PROVIDER } from './interfaces/auth-email-provider.interface';
|
|
823
|
-
export { IUserEnricher, IProfileSection, IProfileExtras, IEnrichedUser } from './interfaces/user-enricher.interface';
|
|
824
|
-
export { AuthModuleOptions, AuthModuleAsyncOptions, AuthOptionsFactory } from './interfaces/auth-module-options.interface';
|
|
825
|
-
export { TokenPayload, TokenPayloadWithCompany, LoginResponse, MeResponse, RegistrationResponse } from './interfaces/authentication.interface';
|
|
1288
|
+
export { IUserEnricher, IProfileSection, IProfileSectionData, IProfileFile, IProfileExtras, IProfileRole, IProfileAction, IEnrichedUser } from './interfaces/user-enricher.interface';
|
|
1289
|
+
export { AuthModuleOptions, AuthModuleAsyncOptions, AuthOptionsFactory, IAuthModuleConfig } from './interfaces/auth-module-options.interface';
|
|
1290
|
+
export { TokenPayload, TokenPayloadWithCompany, LoginResponse, LoginResponseRequiresSelection, LoginResponseRequiresEmailVerification, MeResponse, RegistrationResponse, CompanyWithBranches, BranchForSelection } from './interfaces/authentication.interface';
|
|
1291
|
+
export { IUser, IUserMini, IUserWithPassword } from './interfaces/user.interface';
|
|
1292
|
+
export { ICompany, ICompanyMini } from './interfaces/company.interface';
|
|
1293
|
+
export { ICompanyBranch, ICompanyBranchMini } from './interfaces/company-branch.interface';
|
|
826
1294
|
|
|
827
1295
|
// Services
|
|
828
1296
|
export { AuthenticationService } from './services/authentication.service';
|
|
@@ -838,6 +1306,15 @@ export { CompanySelectionSessionService } from './services/company-selection-ses
|
|
|
838
1306
|
// Modules
|
|
839
1307
|
export { AuthModule } from './modules/auth.module';
|
|
840
1308
|
|
|
1309
|
+
// Controllers
|
|
1310
|
+
export { AuthenticationController } from './controllers/authentication.controller';
|
|
1311
|
+
export { EmailVerificationController } from './controllers/email-verification.controller';
|
|
1312
|
+
export { CompanySelectionController } from './controllers/company-selection.controller';
|
|
1313
|
+
export { UserController } from './controllers/user.controller';
|
|
1314
|
+
export { CompanyController } from './controllers/company.controller';
|
|
1315
|
+
export { BranchController } from './controllers/branch.controller';
|
|
1316
|
+
export { UserPermissionController } from './controllers/user-permission.controller';
|
|
1317
|
+
|
|
841
1318
|
// Strategies
|
|
842
1319
|
export { JwtStrategy } from './strategies/jwt.strategy';
|
|
843
1320
|
|
|
@@ -845,6 +1322,9 @@ export { JwtStrategy } from './strategies/jwt.strategy';
|
|
|
845
1322
|
export { SetToken } from './interceptors/set-token.interceptor';
|
|
846
1323
|
export { ClearToken } from './interceptors/clear-token.interceptor';
|
|
847
1324
|
|
|
1325
|
+
// Validators
|
|
1326
|
+
export { IsStrongPassword, PasswordComplexityOptions } from './validators/password.validator';
|
|
1327
|
+
|
|
848
1328
|
// DTOs
|
|
849
1329
|
export * from './dtos';
|
|
850
1330
|
|
|
@@ -855,14 +1335,49 @@ export { authSwaggerConfig } from './docs/auth-swagger.config';
|
|
|
855
1335
|
### Module Static Methods
|
|
856
1336
|
|
|
857
1337
|
```typescript
|
|
858
|
-
// Get entities based on feature flags
|
|
859
|
-
AuthModule.getEntities(
|
|
1338
|
+
// Get entities based on feature flags (requires IBootstrapAppConfig)
|
|
1339
|
+
AuthModule.getEntities(config: IBootstrapAppConfig): any[]
|
|
1340
|
+
|
|
1341
|
+
// Examples:
|
|
1342
|
+
AuthModule.getEntities({ enableCompanyFeature: false })
|
|
1343
|
+
// Returns: [User, UserToken, PendingRegistration]
|
|
860
1344
|
|
|
861
|
-
|
|
1345
|
+
AuthModule.getEntities({ enableCompanyFeature: true })
|
|
1346
|
+
// Returns: [User, UserToken, PendingRegistration, Company, CompanyBranch, UserCompanyPermission]
|
|
1347
|
+
|
|
1348
|
+
AuthModule.getEntities({ enableCompanyFeature: true, enableEmailVerification: false })
|
|
1349
|
+
// Returns: [User, UserToken, Company, CompanyBranch, UserCompanyPermission]
|
|
1350
|
+
|
|
1351
|
+
// Configure module synchronously
|
|
862
1352
|
AuthModule.forRoot(options: AuthModuleOptions): DynamicModule
|
|
1353
|
+
|
|
1354
|
+
// Configure module asynchronously
|
|
863
1355
|
AuthModule.forRootAsync(options: AuthModuleAsyncOptions): DynamicModule
|
|
864
1356
|
```
|
|
865
1357
|
|
|
1358
|
+
**AuthModuleOptions Interface:**
|
|
1359
|
+
```typescript
|
|
1360
|
+
interface AuthModuleOptions {
|
|
1361
|
+
global?: boolean; // Make module global (default: false)
|
|
1362
|
+
includeController?: boolean; // Include default controllers (default: true)
|
|
1363
|
+
bootstrapAppConfig?: IBootstrapAppConfig;
|
|
1364
|
+
config?: IAuthModuleConfig;
|
|
1365
|
+
providers?: Provider[]; // Additional providers (AUTH_EMAIL_PROVIDER, USER_ENRICHER)
|
|
1366
|
+
}
|
|
1367
|
+
|
|
1368
|
+
interface IAuthModuleConfig {
|
|
1369
|
+
defaultDatabaseConfig?: IDatabaseConfig;
|
|
1370
|
+
tenantDefaultDatabaseConfig?: IDatabaseConfig;
|
|
1371
|
+
tenants?: ITenantDatabaseConfig[];
|
|
1372
|
+
jwtSecret?: string;
|
|
1373
|
+
jwtExpiration?: string; // Default: '1h'
|
|
1374
|
+
refreshTokenSecret?: string;
|
|
1375
|
+
refreshTokenExpiration?: string; // Default: '7d'
|
|
1376
|
+
refreshTokenCookieName?: string; // Default: 'fsn_refresh_token'
|
|
1377
|
+
frontendUrl?: string; // For email links
|
|
1378
|
+
}
|
|
1379
|
+
```
|
|
1380
|
+
|
|
866
1381
|
### Swagger Schema Behavior
|
|
867
1382
|
|
|
868
1383
|
When `enableCompanyFeature: false`, the following are automatically hidden from Swagger:
|
|
@@ -880,4 +1395,4 @@ When `enableCompanyFeature: false`, the following are automatically hidden from
|
|
|
880
1395
|
|
|
881
1396
|
---
|
|
882
1397
|
|
|
883
|
-
**Last Updated:** 2026-02-
|
|
1398
|
+
**Last Updated:** 2026-02-25
|