@flusys/nestjs-auth 4.1.0 → 5.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 +151 -719
- package/cjs/config/message-keys.js +6 -61
- package/cjs/controllers/authentication.controller.js +113 -87
- package/cjs/controllers/company-selection.controller.js +24 -4
- package/cjs/controllers/email-verification.controller.js +12 -13
- package/cjs/docs/auth-swagger.config.js +143 -106
- package/cjs/dtos/authentication.dto.js +0 -15
- package/cjs/entities/user-company-permission.entity.js +0 -8
- package/cjs/entities/user-token.entity.js +0 -9
- package/cjs/interceptors/set-token.interceptor.js +15 -7
- package/cjs/services/auth-config.service.js +0 -4
- package/cjs/services/auth-email.service.js +8 -31
- package/cjs/services/authentication.service.js +99 -15
- package/cjs/services/user-permission.service.js +6 -8
- package/cjs/services/user.service.js +12 -9
- package/cjs/strategies/jwt.strategy.js +10 -3
- package/config/message-keys.d.ts +5 -153
- package/controllers/authentication.controller.d.ts +6 -7
- package/controllers/company-selection.controller.d.ts +3 -2
- package/controllers/email-verification.controller.d.ts +6 -2
- package/dtos/authentication.dto.d.ts +0 -2
- package/entities/user-company-permission.entity.d.ts +0 -1
- package/entities/user-token.entity.d.ts +0 -1
- package/fesm/config/message-keys.js +6 -53
- package/fesm/controllers/authentication.controller.js +115 -90
- package/fesm/controllers/company-selection.controller.js +25 -5
- package/fesm/controllers/email-verification.controller.js +13 -14
- package/fesm/docs/auth-swagger.config.js +146 -113
- package/fesm/dtos/authentication.dto.js +0 -15
- package/fesm/entities/user-company-permission.entity.js +0 -8
- package/fesm/entities/user-token.entity.js +0 -9
- package/fesm/interceptors/set-token.interceptor.js +15 -7
- package/fesm/services/auth-config.service.js +0 -4
- package/fesm/services/auth-email.service.js +8 -32
- package/fesm/services/authentication.service.js +100 -17
- package/fesm/services/user-permission.service.js +6 -8
- package/fesm/services/user.service.js +12 -10
- package/fesm/strategies/jwt.strategy.js +10 -3
- package/interfaces/auth-module-options.interface.d.ts +0 -1
- package/package.json +3 -3
- package/services/auth-config.service.d.ts +0 -1
- package/services/auth-email.service.d.ts +0 -4
- package/services/authentication.service.d.ts +1 -1
- package/services/user-permission.service.d.ts +1 -1
- package/services/user.service.d.ts +5 -5
|
@@ -1,33 +1,14 @@
|
|
|
1
|
-
|
|
1
|
+
// ============================================================================
|
|
2
|
+
// Company feature exclusions
|
|
3
|
+
// ============================================================================
|
|
4
|
+
const COMPANY_RELATED_TAGS = [
|
|
2
5
|
'Companies',
|
|
3
6
|
'Branches',
|
|
4
7
|
'User Permissions',
|
|
5
8
|
'Company Selection'
|
|
6
9
|
];
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
pathPattern: '/auth/login',
|
|
10
|
-
method: 'post',
|
|
11
|
-
examples: [
|
|
12
|
-
'loginSuccessWithCompany',
|
|
13
|
-
'companySelection'
|
|
14
|
-
]
|
|
15
|
-
}
|
|
16
|
-
];
|
|
17
|
-
/**
|
|
18
|
-
* Schema properties to exclude when company feature is disabled
|
|
19
|
-
*
|
|
20
|
-
* This list controls which DTO properties are hidden from Swagger documentation
|
|
21
|
-
* when bootstrapConfig.enableCompanyFeature = false
|
|
22
|
-
*
|
|
23
|
-
* **Documentation:**
|
|
24
|
-
* - Usage: See FLUSYS_NEST/docs/AUTH-GUIDE.md "Swagger Schema Behavior" section
|
|
25
|
-
* - Mechanism: See FLUSYS_NEST/docs/CORE-GUIDE.md "excludeSchemaProperties" section
|
|
26
|
-
*
|
|
27
|
-
* @see setupSwaggerDocs in @flusys/nestjs-core/docs
|
|
28
|
-
* @see ISchemaPropertyExclusion interface
|
|
29
|
-
*/ const COMPANY_SCHEMA_EXCLUSIONS = [
|
|
30
|
-
// ===== Authentication Request DTOs =====
|
|
10
|
+
const COMPANY_SCHEMA_EXCLUSIONS = [
|
|
11
|
+
// Request DTOs
|
|
31
12
|
{
|
|
32
13
|
schemaName: 'RegistrationDto',
|
|
33
14
|
properties: [
|
|
@@ -53,7 +34,7 @@
|
|
|
53
34
|
'branchId'
|
|
54
35
|
]
|
|
55
36
|
},
|
|
56
|
-
//
|
|
37
|
+
// Response DTOs
|
|
57
38
|
{
|
|
58
39
|
schemaName: 'RegistrationResponseDto',
|
|
59
40
|
properties: [
|
|
@@ -75,7 +56,7 @@
|
|
|
75
56
|
'branch'
|
|
76
57
|
]
|
|
77
58
|
},
|
|
78
|
-
//
|
|
59
|
+
// Nested helper DTOs
|
|
79
60
|
{
|
|
80
61
|
schemaName: 'CompanyInfoDto',
|
|
81
62
|
properties: [
|
|
@@ -123,7 +104,7 @@
|
|
|
123
104
|
'companies'
|
|
124
105
|
]
|
|
125
106
|
},
|
|
126
|
-
//
|
|
107
|
+
// Company management DTOs
|
|
127
108
|
{
|
|
128
109
|
schemaName: 'CreateCompanyDto',
|
|
129
110
|
properties: [
|
|
@@ -177,7 +158,7 @@
|
|
|
177
158
|
'updatedAt'
|
|
178
159
|
]
|
|
179
160
|
},
|
|
180
|
-
//
|
|
161
|
+
// Branch management DTOs
|
|
181
162
|
{
|
|
182
163
|
schemaName: 'CreateCompanyBranchDto',
|
|
183
164
|
properties: [
|
|
@@ -231,7 +212,7 @@
|
|
|
231
212
|
'updatedAt'
|
|
232
213
|
]
|
|
233
214
|
},
|
|
234
|
-
//
|
|
215
|
+
// User permission DTOs
|
|
235
216
|
{
|
|
236
217
|
schemaName: 'UserCompanyPermissionDto',
|
|
237
218
|
properties: [
|
|
@@ -287,127 +268,179 @@
|
|
|
287
268
|
]
|
|
288
269
|
}
|
|
289
270
|
];
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
271
|
+
const COMPANY_EXAMPLE_EXCLUSIONS = [
|
|
272
|
+
{
|
|
273
|
+
pathPattern: '/auth/login',
|
|
274
|
+
method: 'post',
|
|
275
|
+
examples: [
|
|
276
|
+
'loginSuccessWithCompany',
|
|
277
|
+
'companySelection'
|
|
278
|
+
]
|
|
279
|
+
}
|
|
280
|
+
];
|
|
281
|
+
// ============================================================================
|
|
282
|
+
// Email verification exclusions
|
|
283
|
+
// ============================================================================
|
|
284
|
+
const EMAIL_VERIFICATION_PATHS = [
|
|
285
|
+
'/auth/forgot-password',
|
|
286
|
+
'/auth/reset-password',
|
|
287
|
+
'/auth/resend-verification',
|
|
288
|
+
'/auth/verify-email'
|
|
289
|
+
];
|
|
290
|
+
const EMAIL_VERIFICATION_SCHEMA_EXCLUSIONS = [
|
|
291
|
+
{
|
|
292
|
+
schemaName: 'RegistrationResponseDto',
|
|
293
|
+
properties: [
|
|
294
|
+
'requiresEmailVerification'
|
|
295
|
+
]
|
|
296
|
+
},
|
|
297
|
+
{
|
|
298
|
+
schemaName: 'LoginResponseRequiresEmailVerificationDto',
|
|
299
|
+
properties: [
|
|
300
|
+
'requiresEmailVerification',
|
|
301
|
+
'email'
|
|
302
|
+
]
|
|
303
|
+
}
|
|
304
|
+
];
|
|
305
|
+
const EMAIL_VERIFICATION_EXAMPLE_EXCLUSIONS = [
|
|
306
|
+
{
|
|
307
|
+
pathPattern: '/auth/login',
|
|
308
|
+
method: 'post',
|
|
309
|
+
examples: [
|
|
310
|
+
'emailVerification'
|
|
311
|
+
]
|
|
312
|
+
}
|
|
313
|
+
];
|
|
314
|
+
// ============================================================================
|
|
315
|
+
// Description builder
|
|
316
|
+
// ============================================================================
|
|
317
|
+
function buildDescription(enableCompanyFeature, enableEmailVerification, isMultiTenant) {
|
|
318
|
+
const multiTenantNote = isMultiTenant ? `\n> **Multi-Tenant Mode**: Include \`x-tenant-id\` header to target a specific tenant database.\n` : '';
|
|
319
|
+
const features = [
|
|
320
|
+
'- User registration',
|
|
321
|
+
'- Login with email/password',
|
|
322
|
+
'- JWT token-based authentication',
|
|
323
|
+
...enableEmailVerification ? [
|
|
324
|
+
'- Email verification',
|
|
325
|
+
'- Forgot/reset password'
|
|
326
|
+
] : [],
|
|
327
|
+
...enableCompanyFeature ? [
|
|
328
|
+
'- Company/Branch selection flow (multi-company enabled)'
|
|
329
|
+
] : [],
|
|
330
|
+
'- Token refresh',
|
|
331
|
+
'- Password change'
|
|
332
|
+
].join('\n');
|
|
333
|
+
const loginFlowSection = enableCompanyFeature ? `
|
|
316
334
|
### Authentication Flow
|
|
317
335
|
|
|
318
|
-
#### Simple Login (
|
|
319
|
-
\`\`\`
|
|
320
|
-
POST /auth/login → { accessToken, refreshToken, user }
|
|
321
|
-
\`\`\`
|
|
322
|
-
|
|
323
|
-
#### Company-Based Login (Company feature enabled)
|
|
324
|
-
|
|
325
|
-
**Case 1: Single company, single branch**
|
|
336
|
+
#### Simple Login (single company/branch)
|
|
326
337
|
\`\`\`
|
|
327
338
|
POST /auth/login → { accessToken, refreshToken, user, company, branch }
|
|
328
339
|
\`\`\`
|
|
329
340
|
|
|
330
|
-
|
|
341
|
+
#### Multi-Company Login (multiple companies or branches)
|
|
331
342
|
\`\`\`
|
|
332
343
|
POST /auth/login → { requiresSelection: true, sessionId, companies }
|
|
333
344
|
POST /auth/select → { accessToken, refreshToken, user, company, branch }
|
|
334
345
|
\`\`\`
|
|
335
|
-
|
|
346
|
+
${enableEmailVerification ? `
|
|
347
|
+
#### Email Verification Required
|
|
348
|
+
\`\`\`
|
|
349
|
+
POST /auth/login → { requiresEmailVerification: true, email }
|
|
350
|
+
POST /auth/verify-email → { accessToken, refreshToken, user }
|
|
351
|
+
\`\`\`
|
|
352
|
+
` : ''}
|
|
336
353
|
### Company/Branch Selection Endpoints
|
|
337
354
|
- \`POST /auth/select\` - Complete login by selecting company and branch
|
|
338
355
|
- \`POST /auth/switch-company\` - Switch to different company/branch while logged in
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
356
|
+
` : `
|
|
357
|
+
### Authentication Flow
|
|
358
|
+
\`\`\`
|
|
359
|
+
POST /auth/login → { accessToken, refreshToken, user }
|
|
360
|
+
\`\`\`
|
|
361
|
+
${enableEmailVerification ? `
|
|
362
|
+
#### Email Verification Required
|
|
363
|
+
\`\`\`
|
|
364
|
+
POST /auth/login → { requiresEmailVerification: true, email }
|
|
365
|
+
POST /auth/verify-email → { accessToken, refreshToken, user }
|
|
366
|
+
\`\`\`
|
|
367
|
+
` : ''}`;
|
|
368
|
+
const emailVerificationSection = enableEmailVerification ? `
|
|
369
|
+
### Email Verification Endpoints
|
|
370
|
+
- \`POST /auth/forgot-password\` - Request password reset email
|
|
371
|
+
- \`POST /auth/reset-password\` - Reset password using token
|
|
372
|
+
- \`POST /auth/resend-verification\` - Resend verification email
|
|
373
|
+
- \`POST /auth/verify-email\` - Verify email using token
|
|
374
|
+
` : '';
|
|
375
|
+
const administrationSection = enableCompanyFeature ? `
|
|
342
376
|
### Administration Endpoints
|
|
343
377
|
- \`POST /administration/users/*\` - User management
|
|
344
378
|
- \`POST /administration/company/*\` - Company management
|
|
345
379
|
- \`POST /administration/branch/*\` - Branch management
|
|
346
380
|
- \`POST /administration/user-permissions/*\` - User permission management
|
|
347
|
-
|
|
381
|
+
` : `
|
|
382
|
+
### Administration Endpoints
|
|
383
|
+
- \`POST /administration/users/*\` - User management
|
|
384
|
+
`;
|
|
385
|
+
const registrationSection = enableCompanyFeature ? `
|
|
348
386
|
### Registration Flow
|
|
349
387
|
|
|
350
388
|
**Simple registration:**
|
|
351
389
|
\`\`\`json
|
|
352
|
-
{
|
|
353
|
-
"name": "John Doe",
|
|
354
|
-
"email": "john@example.com",
|
|
355
|
-
"password": "password123"
|
|
356
|
-
}
|
|
390
|
+
{ "name": "John Doe", "email": "john@example.com", "password": "password123" }
|
|
357
391
|
\`\`\`
|
|
358
392
|
|
|
359
393
|
**Join existing company:**
|
|
360
394
|
\`\`\`json
|
|
361
|
-
{
|
|
362
|
-
"name": "John Doe",
|
|
363
|
-
"email": "john@example.com",
|
|
364
|
-
"password": "password123",
|
|
365
|
-
"companySlug": "acme-corp",
|
|
366
|
-
"branchSlug": "main-branch"
|
|
367
|
-
}
|
|
395
|
+
{ "name": "John Doe", "email": "john@example.com", "password": "password123", "companySlug": "acme-corp", "branchSlug": "main-branch" }
|
|
368
396
|
\`\`\`
|
|
369
397
|
|
|
370
398
|
**Create new company:**
|
|
371
399
|
\`\`\`json
|
|
372
|
-
{
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
}
|
|
400
|
+
{ "name": "John Doe", "email": "john@example.com", "password": "password123", "newCompanyName": "My New Company" }
|
|
401
|
+
\`\`\`
|
|
402
|
+
` : `
|
|
403
|
+
### Registration Flow
|
|
404
|
+
\`\`\`json
|
|
405
|
+
{ "name": "John Doe", "email": "john@example.com", "password": "password123" }
|
|
379
406
|
\`\`\`
|
|
380
|
-
|
|
407
|
+
`;
|
|
408
|
+
return `
|
|
381
409
|
## Authentication API
|
|
382
|
-
|
|
383
|
-
Handles user authentication and registration.
|
|
410
|
+
${multiTenantNote}
|
|
411
|
+
Handles user authentication${enableCompanyFeature ? ', company/branch management' : ''}, and registration.
|
|
384
412
|
|
|
385
413
|
### Features
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
- JWT token-based authentication
|
|
389
|
-
- Token refresh
|
|
390
|
-
- Password change
|
|
391
|
-
|
|
392
|
-
### Authentication Flow
|
|
393
|
-
\`\`\`
|
|
394
|
-
POST /auth/login → { accessToken, refreshToken, user }
|
|
395
|
-
\`\`\`
|
|
396
|
-
|
|
397
|
-
### Registration Flow
|
|
398
|
-
\`\`\`json
|
|
399
|
-
{
|
|
400
|
-
"name": "John Doe",
|
|
401
|
-
"email": "john@example.com",
|
|
402
|
-
"password": "password123"
|
|
414
|
+
${features}
|
|
415
|
+
${loginFlowSection}${emailVerificationSection}${administrationSection}${registrationSection}`;
|
|
403
416
|
}
|
|
404
|
-
|
|
405
|
-
|
|
417
|
+
// ============================================================================
|
|
418
|
+
// Config factory
|
|
419
|
+
// ============================================================================
|
|
420
|
+
export function authSwaggerConfig(bootstrapConfig) {
|
|
421
|
+
const enableCompanyFeature = bootstrapConfig?.enableCompanyFeature ?? true;
|
|
422
|
+
const enableEmailVerification = bootstrapConfig?.enableEmailVerification ?? true;
|
|
423
|
+
const isMultiTenant = bootstrapConfig?.databaseMode === 'multi-tenant';
|
|
424
|
+
const excludeTags = enableCompanyFeature ? [] : COMPANY_RELATED_TAGS;
|
|
425
|
+
const excludeSchemaProperties = [
|
|
426
|
+
...enableCompanyFeature ? [] : COMPANY_SCHEMA_EXCLUSIONS,
|
|
427
|
+
...enableEmailVerification ? [] : EMAIL_VERIFICATION_SCHEMA_EXCLUSIONS
|
|
428
|
+
];
|
|
429
|
+
// Merge example exclusions — both may target /auth/login with different example names
|
|
430
|
+
const excludeExamples = [
|
|
431
|
+
...enableCompanyFeature ? [] : COMPANY_EXAMPLE_EXCLUSIONS,
|
|
432
|
+
...enableEmailVerification ? [] : EMAIL_VERIFICATION_EXAMPLE_EXCLUSIONS
|
|
433
|
+
];
|
|
434
|
+
const excludePaths = enableEmailVerification ? undefined : EMAIL_VERIFICATION_PATHS;
|
|
435
|
+
return {
|
|
436
|
+
title: 'Auth API',
|
|
437
|
+
description: buildDescription(enableCompanyFeature, enableEmailVerification, isMultiTenant),
|
|
406
438
|
version: '1.0',
|
|
407
439
|
path: 'api/docs/auth',
|
|
408
440
|
bearerAuth: true,
|
|
409
441
|
excludeTags,
|
|
410
|
-
excludeSchemaProperties:
|
|
411
|
-
excludeExamples:
|
|
442
|
+
excludeSchemaProperties: excludeSchemaProperties.length ? excludeSchemaProperties : undefined,
|
|
443
|
+
excludeExamples: excludeExamples.length ? excludeExamples : undefined,
|
|
444
|
+
excludePaths
|
|
412
445
|
};
|
|
413
446
|
}
|
|
@@ -612,8 +612,6 @@ export class LoginResponseRequiresEmailVerificationDto {
|
|
|
612
612
|
constructor(){
|
|
613
613
|
_define_property(this, "requiresEmailVerification", void 0);
|
|
614
614
|
_define_property(this, "email", void 0);
|
|
615
|
-
_define_property(this, "message", void 0);
|
|
616
|
-
_define_property(this, "messageKey", void 0);
|
|
617
615
|
}
|
|
618
616
|
}
|
|
619
617
|
_ts_decorate([
|
|
@@ -628,19 +626,6 @@ _ts_decorate([
|
|
|
628
626
|
}),
|
|
629
627
|
_ts_metadata("design:type", String)
|
|
630
628
|
], LoginResponseRequiresEmailVerificationDto.prototype, "email", void 0);
|
|
631
|
-
_ts_decorate([
|
|
632
|
-
ApiProperty({
|
|
633
|
-
example: 'Please verify your email address before logging in.'
|
|
634
|
-
}),
|
|
635
|
-
_ts_metadata("design:type", String)
|
|
636
|
-
], LoginResponseRequiresEmailVerificationDto.prototype, "message", void 0);
|
|
637
|
-
_ts_decorate([
|
|
638
|
-
ApiProperty({
|
|
639
|
-
example: 'auth.login.email.not.verified',
|
|
640
|
-
description: 'Translation key for localization'
|
|
641
|
-
}),
|
|
642
|
-
_ts_metadata("design:type", String)
|
|
643
|
-
], LoginResponseRequiresEmailVerificationDto.prototype, "messageKey", void 0);
|
|
644
629
|
export class ForgotPasswordDto {
|
|
645
630
|
constructor(){
|
|
646
631
|
_define_property(this, "email", void 0);
|
|
@@ -33,7 +33,6 @@ export class UserCompanyPermission {
|
|
|
33
33
|
_define_property(this, "user", void 0);
|
|
34
34
|
/* ---------- Polymorphic Target ---------- */ _define_property(this, "permissionType", void 0);
|
|
35
35
|
_define_property(this, "targetId", void 0);
|
|
36
|
-
_define_property(this, "metadata", void 0);
|
|
37
36
|
_define_property(this, "isActive", void 0);
|
|
38
37
|
/* ---------- Optional Relations (no FK - polymorphic) ---------- */ _define_property(this, "company", void 0);
|
|
39
38
|
_define_property(this, "branch", void 0);
|
|
@@ -76,13 +75,6 @@ _ts_decorate([
|
|
|
76
75
|
}),
|
|
77
76
|
_ts_metadata("design:type", String)
|
|
78
77
|
], UserCompanyPermission.prototype, "targetId", void 0);
|
|
79
|
-
_ts_decorate([
|
|
80
|
-
Column({
|
|
81
|
-
type: 'json',
|
|
82
|
-
nullable: true
|
|
83
|
-
}),
|
|
84
|
-
_ts_metadata("design:type", typeof Record === "undefined" ? Object : Record)
|
|
85
|
-
], UserCompanyPermission.prototype, "metadata", void 0);
|
|
86
78
|
_ts_decorate([
|
|
87
79
|
Column({
|
|
88
80
|
type: 'boolean',
|
|
@@ -37,7 +37,6 @@ export class UserToken {
|
|
|
37
37
|
_define_property(this, "token", void 0);
|
|
38
38
|
_define_property(this, "expiresAt", void 0);
|
|
39
39
|
_define_property(this, "usedAt", void 0);
|
|
40
|
-
_define_property(this, "metadata", void 0);
|
|
41
40
|
_define_property(this, "createdAt", void 0);
|
|
42
41
|
}
|
|
43
42
|
}
|
|
@@ -81,14 +80,6 @@ _ts_decorate([
|
|
|
81
80
|
}),
|
|
82
81
|
_ts_metadata("design:type", Object)
|
|
83
82
|
], UserToken.prototype, "usedAt", void 0);
|
|
84
|
-
_ts_decorate([
|
|
85
|
-
Column({
|
|
86
|
-
type: 'varchar',
|
|
87
|
-
length: 255,
|
|
88
|
-
nullable: true
|
|
89
|
-
}),
|
|
90
|
-
_ts_metadata("design:type", Object)
|
|
91
|
-
], UserToken.prototype, "metadata", void 0);
|
|
92
83
|
_ts_decorate([
|
|
93
84
|
CreateDateColumn({
|
|
94
85
|
type: 'timestamp',
|
|
@@ -43,16 +43,24 @@ export class SetToken {
|
|
|
43
43
|
const req = context.switchToHttp().getRequest();
|
|
44
44
|
const res = context.switchToHttp().getResponse();
|
|
45
45
|
return next.handle().pipe(map((value)=>{
|
|
46
|
-
if (typeof value !== 'object' || value === null
|
|
46
|
+
if (typeof value !== 'object' || value === null) {
|
|
47
47
|
return value;
|
|
48
48
|
}
|
|
49
49
|
const response = value;
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
return
|
|
50
|
+
const data = typeof response['data'] === 'object' && response['data'] !== null ? response['data'] : null;
|
|
51
|
+
const tokenInData = data && typeof data['refreshToken'] === 'string';
|
|
52
|
+
if (!tokenInData) {
|
|
53
|
+
return value;
|
|
54
|
+
}
|
|
55
|
+
if (!isBrowserRequest(req)) {
|
|
56
|
+
return value;
|
|
54
57
|
}
|
|
55
|
-
|
|
58
|
+
this.setRefreshTokenCookie(req, res, data['refreshToken']);
|
|
59
|
+
const { refreshToken: _, ...dataWithoutToken } = data;
|
|
60
|
+
return {
|
|
61
|
+
...response,
|
|
62
|
+
data: dataWithoutToken
|
|
63
|
+
};
|
|
56
64
|
}), catchError((err)=>throwError(()=>err)));
|
|
57
65
|
}
|
|
58
66
|
setRefreshTokenCookie(req, res, tokenValue) {
|
|
@@ -62,7 +70,7 @@ export class SetToken {
|
|
|
62
70
|
throw new PayloadTooLargeException({
|
|
63
71
|
message: `Refresh token too large (≈${estimatedBytes} bytes)`,
|
|
64
72
|
messageKey: AUTH_MESSAGES.TOKEN_TOO_LARGE,
|
|
65
|
-
|
|
73
|
+
messageVariables: {
|
|
66
74
|
size: estimatedBytes
|
|
67
75
|
}
|
|
68
76
|
});
|
|
@@ -76,10 +76,6 @@ export class AuthConfigService {
|
|
|
76
76
|
getRefreshTokenCookieName() {
|
|
77
77
|
return this.config.refreshTokenCookieName ?? 'fsn_refresh_token';
|
|
78
78
|
}
|
|
79
|
-
// Frontend Configuration
|
|
80
|
-
getFrontendUrl() {
|
|
81
|
-
return this.config.frontendUrl;
|
|
82
|
-
}
|
|
83
79
|
constructor(injectedOptions){
|
|
84
80
|
_define_property(this, "options", void 0);
|
|
85
81
|
_define_property(this, "config", void 0);
|
|
@@ -25,14 +25,12 @@ function _ts_param(paramIndex, decorator) {
|
|
|
25
25
|
decorator(target, key, paramIndex);
|
|
26
26
|
};
|
|
27
27
|
}
|
|
28
|
-
import { SYSTEM_MESSAGES } from '@flusys/nestjs-shared/constants';
|
|
29
28
|
import { LogAction } from '@flusys/nestjs-shared';
|
|
30
|
-
import {
|
|
29
|
+
import { SYSTEM_MESSAGES } from '@flusys/nestjs-shared/constants';
|
|
31
30
|
import { BadRequestException, Inject, Injectable, InternalServerErrorException, Optional, Scope } from '@nestjs/common';
|
|
32
31
|
import * as bcrypt from 'bcrypt';
|
|
33
32
|
import * as crypto from 'crypto';
|
|
34
|
-
import {
|
|
35
|
-
import { BCRYPT_SALT_ROUNDS } from '../config';
|
|
33
|
+
import { AUTH_MESSAGES, BCRYPT_SALT_ROUNDS, EMAIL_VERIFICATION_MESSAGES, USER_MESSAGES } from '../config';
|
|
36
34
|
import { PendingRegistration } from '../entities/pending-registration.entity';
|
|
37
35
|
import { TokenType, UserToken } from '../entities/user-token.entity';
|
|
38
36
|
import { User } from '../entities/user.entity';
|
|
@@ -47,7 +45,7 @@ export class AuthEmailService {
|
|
|
47
45
|
throw new InternalServerErrorException({
|
|
48
46
|
message: `${String(entity)} repository not available`,
|
|
49
47
|
messageKey: SYSTEM_MESSAGES.REPOSITORY_NOT_AVAILABLE,
|
|
50
|
-
|
|
48
|
+
messageVariables: {
|
|
51
49
|
entity: String(entity)
|
|
52
50
|
}
|
|
53
51
|
});
|
|
@@ -186,7 +184,11 @@ export class AuthEmailService {
|
|
|
186
184
|
} catch {
|
|
187
185
|
throw new BadRequestException({
|
|
188
186
|
message: 'Failed to process request. Please try again later.',
|
|
189
|
-
messageKey: SYSTEM_MESSAGES.INTERNAL_ERROR
|
|
187
|
+
messageKey: SYSTEM_MESSAGES.INTERNAL_ERROR,
|
|
188
|
+
messageVariables: {
|
|
189
|
+
provider: 'EmailProvider',
|
|
190
|
+
error: 'Send email failed'
|
|
191
|
+
}
|
|
190
192
|
});
|
|
191
193
|
}
|
|
192
194
|
return {
|
|
@@ -377,23 +379,6 @@ export class AuthEmailService {
|
|
|
377
379
|
messageKey: EMAIL_VERIFICATION_MESSAGES.RESEND_SUCCESS
|
|
378
380
|
};
|
|
379
381
|
}
|
|
380
|
-
async cleanupExpired() {
|
|
381
|
-
const tokenRepository = await this.getRepository(UserToken);
|
|
382
|
-
const pendingRepository = await this.getRepository(PendingRegistration);
|
|
383
|
-
const now = new Date();
|
|
384
|
-
const tokenResult = await tokenRepository.delete({
|
|
385
|
-
expiresAt: LessThan(now)
|
|
386
|
-
});
|
|
387
|
-
const pendingResult = await pendingRepository.delete({
|
|
388
|
-
expiresAt: LessThan(now)
|
|
389
|
-
});
|
|
390
|
-
const deletedTokens = tokenResult.affected ?? 0;
|
|
391
|
-
const deletedPending = pendingResult.affected ?? 0;
|
|
392
|
-
return {
|
|
393
|
-
deletedTokens,
|
|
394
|
-
deletedPending
|
|
395
|
-
};
|
|
396
|
-
}
|
|
397
382
|
constructor(dataSourceProvider, emailProvider){
|
|
398
383
|
_define_property(this, "dataSourceProvider", void 0);
|
|
399
384
|
_define_property(this, "emailProvider", void 0);
|
|
@@ -466,15 +451,6 @@ _ts_decorate([
|
|
|
466
451
|
]),
|
|
467
452
|
_ts_metadata("design:returntype", Promise)
|
|
468
453
|
], AuthEmailService.prototype, "resendVerificationEmail", null);
|
|
469
|
-
_ts_decorate([
|
|
470
|
-
LogAction({
|
|
471
|
-
action: 'auth.cleanupExpiredTokens',
|
|
472
|
-
module: 'auth'
|
|
473
|
-
}),
|
|
474
|
-
_ts_metadata("design:type", Function),
|
|
475
|
-
_ts_metadata("design:paramtypes", []),
|
|
476
|
-
_ts_metadata("design:returntype", Promise)
|
|
477
|
-
], AuthEmailService.prototype, "cleanupExpired", null);
|
|
478
454
|
AuthEmailService = _ts_decorate([
|
|
479
455
|
Injectable({
|
|
480
456
|
scope: Scope.REQUEST
|