@flusys/nestjs-auth 1.0.1 → 1.1.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 +61 -13
- 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/entities/index.js +16 -17
- 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/authentication.service.js +34 -29
- 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/entities/index.d.ts +5 -10
- 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/entities/index.js +17 -9
- 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/authentication.service.js +34 -29
- 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/authentication.service.d.ts +1 -0
|
@@ -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,
|
|
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
|
-
|
|
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);
|
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
function _define_property(obj, key, value) {
|
|
2
|
+
if (key in obj) {
|
|
3
|
+
Object.defineProperty(obj, key, {
|
|
4
|
+
value: value,
|
|
5
|
+
enumerable: true,
|
|
6
|
+
configurable: true,
|
|
7
|
+
writable: true
|
|
8
|
+
});
|
|
9
|
+
} else {
|
|
10
|
+
obj[key] = value;
|
|
11
|
+
}
|
|
12
|
+
return obj;
|
|
13
|
+
}
|
|
14
|
+
function _ts_decorate(decorators, target, key, desc) {
|
|
15
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
16
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
17
|
+
else for(var i = decorators.length - 1; i >= 0; i--)if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
18
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
19
|
+
}
|
|
20
|
+
function _ts_metadata(k, v) {
|
|
21
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
22
|
+
}
|
|
23
|
+
function _ts_param(paramIndex, decorator) {
|
|
24
|
+
return function(target, key) {
|
|
25
|
+
decorator(target, key, paramIndex);
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
import { MessageResponseDto } from '@flusys/nestjs-shared/dtos';
|
|
29
|
+
import { BadRequestException, Body, Controller, HttpCode, HttpStatus, Inject, Post, Req, UseInterceptors } from '@nestjs/common';
|
|
30
|
+
import { ApiBody, ApiOperation, ApiResponse, ApiTags } from '@nestjs/swagger';
|
|
31
|
+
import { Throttle } from '@nestjs/throttler';
|
|
32
|
+
import { Request } from 'express';
|
|
33
|
+
import { ForgotPasswordDto, RegistrationResponseDto, ResendVerificationDto, ResetPasswordDto, VerifyEmailDto } from '../dtos/authentication.dto';
|
|
34
|
+
import { SetToken } from '../interceptors/set-token.interceptor';
|
|
35
|
+
import { AuthConfigService } from '../services/auth-config.service';
|
|
36
|
+
import { AuthDataSourceProvider } from '../services/auth-datasource.provider';
|
|
37
|
+
import { AuthEmailService } from '../services/auth-email.service';
|
|
38
|
+
import { AuthenticationService } from '../services/authentication.service';
|
|
39
|
+
export class EmailVerificationController {
|
|
40
|
+
ensureEmailVerificationEnabled() {
|
|
41
|
+
if (!this.dataSourceProvider.isEmailVerificationEnabled()) {
|
|
42
|
+
throw new BadRequestException('Email verification is not enabled for this tenant');
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
buildAuthUrl(req, path) {
|
|
46
|
+
const frontendUrl = this.authConfig.getFrontendUrl();
|
|
47
|
+
return frontendUrl ? `${frontendUrl}${path}` : `${req.protocol}://${req.get('host')}${path}`;
|
|
48
|
+
}
|
|
49
|
+
async forgotPassword(req, dto) {
|
|
50
|
+
this.ensureEmailVerificationEnabled();
|
|
51
|
+
return this.authEmailService.forgotPassword(dto.email, this.buildAuthUrl(req, '/auth/reset-password'));
|
|
52
|
+
}
|
|
53
|
+
async resetPassword(dto) {
|
|
54
|
+
this.ensureEmailVerificationEnabled();
|
|
55
|
+
return this.authEmailService.resetPassword(dto.token, dto.newPassword);
|
|
56
|
+
}
|
|
57
|
+
async resendVerification(req, dto) {
|
|
58
|
+
this.ensureEmailVerificationEnabled();
|
|
59
|
+
return this.authEmailService.resendVerificationEmail(dto.email, this.buildAuthUrl(req, '/auth/verify-email'));
|
|
60
|
+
}
|
|
61
|
+
async verifyEmail(dto) {
|
|
62
|
+
this.ensureEmailVerificationEnabled();
|
|
63
|
+
const result = await this.authEmailService.verifyEmail(dto.token);
|
|
64
|
+
if (result.type === 'pending') {
|
|
65
|
+
return this.authService.createUserFromPendingRegistration(result.pending);
|
|
66
|
+
}
|
|
67
|
+
return {
|
|
68
|
+
success: true,
|
|
69
|
+
message: result.message
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
constructor(authService, authEmailService, authConfig, dataSourceProvider){
|
|
73
|
+
_define_property(this, "authService", void 0);
|
|
74
|
+
_define_property(this, "authEmailService", void 0);
|
|
75
|
+
_define_property(this, "authConfig", void 0);
|
|
76
|
+
_define_property(this, "dataSourceProvider", void 0);
|
|
77
|
+
this.authService = authService;
|
|
78
|
+
this.authEmailService = authEmailService;
|
|
79
|
+
this.authConfig = authConfig;
|
|
80
|
+
this.dataSourceProvider = dataSourceProvider;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
_ts_decorate([
|
|
84
|
+
Post('forgot-password'),
|
|
85
|
+
HttpCode(HttpStatus.OK),
|
|
86
|
+
Throttle({
|
|
87
|
+
default: {
|
|
88
|
+
limit: 3,
|
|
89
|
+
ttl: 300000
|
|
90
|
+
}
|
|
91
|
+
}),
|
|
92
|
+
ApiOperation({
|
|
93
|
+
summary: 'Request password reset email'
|
|
94
|
+
}),
|
|
95
|
+
ApiBody({
|
|
96
|
+
type: ForgotPasswordDto
|
|
97
|
+
}),
|
|
98
|
+
ApiResponse({
|
|
99
|
+
status: 200,
|
|
100
|
+
type: MessageResponseDto
|
|
101
|
+
}),
|
|
102
|
+
_ts_param(0, Req()),
|
|
103
|
+
_ts_param(1, Body()),
|
|
104
|
+
_ts_metadata("design:type", Function),
|
|
105
|
+
_ts_metadata("design:paramtypes", [
|
|
106
|
+
typeof Request === "undefined" ? Object : Request,
|
|
107
|
+
typeof ForgotPasswordDto === "undefined" ? Object : ForgotPasswordDto
|
|
108
|
+
]),
|
|
109
|
+
_ts_metadata("design:returntype", Promise)
|
|
110
|
+
], EmailVerificationController.prototype, "forgotPassword", null);
|
|
111
|
+
_ts_decorate([
|
|
112
|
+
Post('reset-password'),
|
|
113
|
+
HttpCode(HttpStatus.OK),
|
|
114
|
+
Throttle({
|
|
115
|
+
default: {
|
|
116
|
+
limit: 5,
|
|
117
|
+
ttl: 900000
|
|
118
|
+
}
|
|
119
|
+
}),
|
|
120
|
+
ApiOperation({
|
|
121
|
+
summary: 'Reset password using token'
|
|
122
|
+
}),
|
|
123
|
+
ApiBody({
|
|
124
|
+
type: ResetPasswordDto
|
|
125
|
+
}),
|
|
126
|
+
ApiResponse({
|
|
127
|
+
status: 200,
|
|
128
|
+
type: MessageResponseDto
|
|
129
|
+
}),
|
|
130
|
+
_ts_param(0, Body()),
|
|
131
|
+
_ts_metadata("design:type", Function),
|
|
132
|
+
_ts_metadata("design:paramtypes", [
|
|
133
|
+
typeof ResetPasswordDto === "undefined" ? Object : ResetPasswordDto
|
|
134
|
+
]),
|
|
135
|
+
_ts_metadata("design:returntype", Promise)
|
|
136
|
+
], EmailVerificationController.prototype, "resetPassword", null);
|
|
137
|
+
_ts_decorate([
|
|
138
|
+
Post('resend-verification'),
|
|
139
|
+
HttpCode(HttpStatus.OK),
|
|
140
|
+
Throttle({
|
|
141
|
+
default: {
|
|
142
|
+
limit: 3,
|
|
143
|
+
ttl: 300000
|
|
144
|
+
}
|
|
145
|
+
}),
|
|
146
|
+
ApiOperation({
|
|
147
|
+
summary: 'Resend email verification link'
|
|
148
|
+
}),
|
|
149
|
+
ApiBody({
|
|
150
|
+
type: ResendVerificationDto
|
|
151
|
+
}),
|
|
152
|
+
ApiResponse({
|
|
153
|
+
status: 200,
|
|
154
|
+
type: MessageResponseDto
|
|
155
|
+
}),
|
|
156
|
+
_ts_param(0, Req()),
|
|
157
|
+
_ts_param(1, Body()),
|
|
158
|
+
_ts_metadata("design:type", Function),
|
|
159
|
+
_ts_metadata("design:paramtypes", [
|
|
160
|
+
typeof Request === "undefined" ? Object : Request,
|
|
161
|
+
typeof ResendVerificationDto === "undefined" ? Object : ResendVerificationDto
|
|
162
|
+
]),
|
|
163
|
+
_ts_metadata("design:returntype", Promise)
|
|
164
|
+
], EmailVerificationController.prototype, "resendVerification", null);
|
|
165
|
+
_ts_decorate([
|
|
166
|
+
Post('verify-email'),
|
|
167
|
+
HttpCode(HttpStatus.OK),
|
|
168
|
+
Throttle({
|
|
169
|
+
default: {
|
|
170
|
+
limit: 10,
|
|
171
|
+
ttl: 60000
|
|
172
|
+
}
|
|
173
|
+
}),
|
|
174
|
+
UseInterceptors(SetToken),
|
|
175
|
+
ApiOperation({
|
|
176
|
+
summary: 'Verify email using token'
|
|
177
|
+
}),
|
|
178
|
+
ApiBody({
|
|
179
|
+
type: VerifyEmailDto
|
|
180
|
+
}),
|
|
181
|
+
ApiResponse({
|
|
182
|
+
status: 200,
|
|
183
|
+
type: MessageResponseDto
|
|
184
|
+
}),
|
|
185
|
+
ApiResponse({
|
|
186
|
+
status: 200,
|
|
187
|
+
type: RegistrationResponseDto
|
|
188
|
+
}),
|
|
189
|
+
_ts_param(0, Body()),
|
|
190
|
+
_ts_metadata("design:type", Function),
|
|
191
|
+
_ts_metadata("design:paramtypes", [
|
|
192
|
+
typeof VerifyEmailDto === "undefined" ? Object : VerifyEmailDto
|
|
193
|
+
]),
|
|
194
|
+
_ts_metadata("design:returntype", Promise)
|
|
195
|
+
], EmailVerificationController.prototype, "verifyEmail", null);
|
|
196
|
+
EmailVerificationController = _ts_decorate([
|
|
197
|
+
ApiTags('Authentication'),
|
|
198
|
+
Controller('auth'),
|
|
199
|
+
_ts_param(0, Inject(AuthenticationService)),
|
|
200
|
+
_ts_param(1, Inject(AuthEmailService)),
|
|
201
|
+
_ts_param(2, Inject(AuthConfigService)),
|
|
202
|
+
_ts_param(3, Inject(AuthDataSourceProvider)),
|
|
203
|
+
_ts_metadata("design:type", Function),
|
|
204
|
+
_ts_metadata("design:paramtypes", [
|
|
205
|
+
typeof AuthenticationService === "undefined" ? Object : AuthenticationService,
|
|
206
|
+
typeof AuthEmailService === "undefined" ? Object : AuthEmailService,
|
|
207
|
+
typeof AuthConfigService === "undefined" ? Object : AuthConfigService,
|
|
208
|
+
typeof AuthDataSourceProvider === "undefined" ? Object : AuthDataSourceProvider
|
|
209
|
+
])
|
|
210
|
+
], EmailVerificationController);
|
package/fesm/entities/index.js
CHANGED
|
@@ -10,20 +10,28 @@ import { PendingRegistration } from './pending-registration.entity';
|
|
|
10
10
|
import { UserCompanyPermission } from './user-company-permission.entity';
|
|
11
11
|
import { User } from './user.entity';
|
|
12
12
|
import { UserToken } from './user-token.entity';
|
|
13
|
-
|
|
13
|
+
const BaseEntities = [
|
|
14
14
|
User,
|
|
15
|
-
UserToken
|
|
15
|
+
UserToken
|
|
16
|
+
];
|
|
17
|
+
const EmailEntities = [
|
|
16
18
|
PendingRegistration
|
|
17
19
|
];
|
|
18
|
-
|
|
20
|
+
const CompanyEntities = [
|
|
19
21
|
Company,
|
|
20
22
|
CompanyBranch,
|
|
21
23
|
UserCompanyPermission
|
|
22
24
|
];
|
|
23
|
-
export
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
25
|
+
export function getEntitiesByConfig(config) {
|
|
26
|
+
const { enableCompanyFeature = false, enableEmailVerification = true } = config;
|
|
27
|
+
const entities = [
|
|
28
|
+
...BaseEntities
|
|
29
|
+
];
|
|
30
|
+
if (enableEmailVerification) {
|
|
31
|
+
entities.push(...EmailEntities);
|
|
32
|
+
}
|
|
33
|
+
if (enableCompanyFeature) {
|
|
34
|
+
entities.push(...CompanyEntities);
|
|
35
|
+
}
|
|
36
|
+
return entities;
|
|
29
37
|
}
|
|
@@ -10,8 +10,8 @@ import { JwtModule } from '@nestjs/jwt';
|
|
|
10
10
|
import { PassportModule } from '@nestjs/passport';
|
|
11
11
|
import { JwtAuthGuard } from '@flusys/nestjs-shared/guards';
|
|
12
12
|
import { AUTH_MODULE_OPTIONS } from '../config/auth.constants';
|
|
13
|
-
import { AuthenticationController, BranchController, CompanyController, CompanySelectionController, UserController, UserPermissionController } from '../controllers';
|
|
14
|
-
import {
|
|
13
|
+
import { AuthenticationController, BranchController, CompanyController, CompanySelectionController, EmailVerificationController, UserController, UserPermissionController } from '../controllers';
|
|
14
|
+
import { getEntitiesByConfig } from '../entities';
|
|
15
15
|
import { ClearToken } from '../interceptors/clear-token.interceptor';
|
|
16
16
|
import { SetToken } from '../interceptors/set-token.interceptor';
|
|
17
17
|
import { AuthEmailService, AuthenticationService, BranchService, CompanySelectionSessionService, CompanyService, UserPermissionService, UserService } from '../services';
|
|
@@ -36,9 +36,9 @@ export class AuthModule {
|
|
|
36
36
|
...options.providers ?? []
|
|
37
37
|
], options.imports);
|
|
38
38
|
}
|
|
39
|
-
|
|
39
|
+
static buildModule(options, providers, externalImports = []) {
|
|
40
40
|
const { global = false, includeController = true, bootstrapAppConfig } = options;
|
|
41
|
-
const
|
|
41
|
+
const featureFlags = this.getFeatureFlags(bootstrapAppConfig);
|
|
42
42
|
return {
|
|
43
43
|
module: AuthModule,
|
|
44
44
|
global,
|
|
@@ -46,15 +46,21 @@ export class AuthModule {
|
|
|
46
46
|
...externalImports,
|
|
47
47
|
...this.buildImports()
|
|
48
48
|
],
|
|
49
|
-
controllers: this.buildControllers(includeController,
|
|
49
|
+
controllers: this.buildControllers(includeController, featureFlags),
|
|
50
50
|
providers: [
|
|
51
51
|
...providers,
|
|
52
|
-
...this.buildProviders(
|
|
52
|
+
...this.buildProviders(featureFlags)
|
|
53
53
|
],
|
|
54
|
-
exports: this.buildExports(
|
|
54
|
+
exports: this.buildExports(featureFlags)
|
|
55
55
|
};
|
|
56
56
|
}
|
|
57
|
-
|
|
57
|
+
static getFeatureFlags(bootstrapAppConfig) {
|
|
58
|
+
return {
|
|
59
|
+
enableCompanyFeature: bootstrapAppConfig?.enableCompanyFeature ?? false,
|
|
60
|
+
enableEmailVerification: bootstrapAppConfig?.enableEmailVerification ?? true
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
static buildImports() {
|
|
58
64
|
return [
|
|
59
65
|
PassportModule.register({
|
|
60
66
|
defaultStrategy: 'jwt'
|
|
@@ -64,35 +70,40 @@ export class AuthModule {
|
|
|
64
70
|
UtilsModule
|
|
65
71
|
];
|
|
66
72
|
}
|
|
67
|
-
|
|
73
|
+
static buildControllers(includeController, flags) {
|
|
68
74
|
if (!includeController) return [];
|
|
69
75
|
const controllers = [
|
|
70
76
|
AuthenticationController,
|
|
71
77
|
UserController
|
|
72
78
|
];
|
|
73
|
-
if (
|
|
79
|
+
if (flags.enableEmailVerification) {
|
|
80
|
+
controllers.push(EmailVerificationController);
|
|
81
|
+
}
|
|
82
|
+
if (flags.enableCompanyFeature) {
|
|
74
83
|
controllers.push(CompanySelectionController, CompanyController, BranchController, UserPermissionController);
|
|
75
84
|
}
|
|
76
85
|
return controllers;
|
|
77
86
|
}
|
|
78
|
-
|
|
87
|
+
static buildProviders(flags) {
|
|
79
88
|
const providers = [
|
|
80
89
|
AuthConfigService,
|
|
81
90
|
AuthDataSourceProvider,
|
|
82
91
|
JwtStrategy,
|
|
83
92
|
JwtAuthGuard,
|
|
84
93
|
AuthenticationService,
|
|
85
|
-
AuthEmailService,
|
|
86
94
|
SetToken,
|
|
87
95
|
ClearToken,
|
|
88
96
|
UserService
|
|
89
97
|
];
|
|
90
|
-
if (
|
|
98
|
+
if (flags.enableEmailVerification) {
|
|
99
|
+
providers.push(AuthEmailService);
|
|
100
|
+
}
|
|
101
|
+
if (flags.enableCompanyFeature) {
|
|
91
102
|
providers.push(CompanySelectionSessionService, CompanyService, BranchService, UserPermissionService);
|
|
92
103
|
}
|
|
93
104
|
return providers;
|
|
94
105
|
}
|
|
95
|
-
|
|
106
|
+
static buildExports(flags) {
|
|
96
107
|
const exports = [
|
|
97
108
|
PassportModule,
|
|
98
109
|
AUTH_MODULE_OPTIONS,
|
|
@@ -101,15 +112,17 @@ export class AuthModule {
|
|
|
101
112
|
JwtStrategy,
|
|
102
113
|
JwtAuthGuard,
|
|
103
114
|
AuthenticationService,
|
|
104
|
-
AuthEmailService,
|
|
105
115
|
UserService
|
|
106
116
|
];
|
|
107
|
-
if (
|
|
117
|
+
if (flags.enableEmailVerification) {
|
|
118
|
+
exports.push(AuthEmailService);
|
|
119
|
+
}
|
|
120
|
+
if (flags.enableCompanyFeature) {
|
|
108
121
|
exports.push(CompanySelectionSessionService, CompanyService, BranchService, UserPermissionService);
|
|
109
122
|
}
|
|
110
123
|
return exports;
|
|
111
124
|
}
|
|
112
|
-
|
|
125
|
+
static createAsyncProviders(options) {
|
|
113
126
|
const staticOptions = {
|
|
114
127
|
global: options.global,
|
|
115
128
|
includeController: options.includeController,
|
|
@@ -166,15 +179,11 @@ export class AuthModule {
|
|
|
166
179
|
}
|
|
167
180
|
];
|
|
168
181
|
}
|
|
169
|
-
|
|
170
|
-
return
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
UserCompanyPermission
|
|
175
|
-
] : [
|
|
176
|
-
User
|
|
177
|
-
];
|
|
182
|
+
static getEntities(config) {
|
|
183
|
+
return getEntitiesByConfig({
|
|
184
|
+
enableCompanyFeature: config.enableCompanyFeature ?? false,
|
|
185
|
+
enableEmailVerification: config.enableEmailVerification ?? true
|
|
186
|
+
});
|
|
178
187
|
}
|
|
179
188
|
}
|
|
180
189
|
AuthModule = _ts_decorate([
|
|
@@ -25,6 +25,7 @@ function _ts_param(paramIndex, decorator) {
|
|
|
25
25
|
decorator(target, key, paramIndex);
|
|
26
26
|
};
|
|
27
27
|
}
|
|
28
|
+
import { envConfig } from '@flusys/nestjs-core/config';
|
|
28
29
|
import { Inject, Injectable, InternalServerErrorException, Logger, Optional } from '@nestjs/common';
|
|
29
30
|
import { AUTH_MODULE_OPTIONS } from '../config/auth.constants';
|
|
30
31
|
import { AuthModuleOptions } from '../interfaces/auth-module-options.interface';
|
|
@@ -40,21 +41,24 @@ export class AuthConfigService {
|
|
|
40
41
|
isCompanyFeatureEnabled() {
|
|
41
42
|
return this.options.bootstrapAppConfig?.enableCompanyFeature ?? false;
|
|
42
43
|
}
|
|
44
|
+
isEmailVerificationEnabled() {
|
|
45
|
+
return this.options.bootstrapAppConfig?.enableEmailVerification ?? true;
|
|
46
|
+
}
|
|
43
47
|
// JWT Configuration
|
|
44
|
-
|
|
48
|
+
getJwtSecret() {
|
|
45
49
|
if (!this.config.jwtSecret) {
|
|
46
50
|
throw new InternalServerErrorException('[AuthModule] JWT_SECRET is required - set via environment or module config');
|
|
47
51
|
}
|
|
48
52
|
return this.config.jwtSecret;
|
|
49
53
|
}
|
|
50
|
-
|
|
54
|
+
getJwtExpiration() {
|
|
51
55
|
return this.config.jwtExpiration ?? '1h';
|
|
52
56
|
}
|
|
53
|
-
|
|
57
|
+
getRefreshTokenSecret() {
|
|
54
58
|
if (this.config.refreshTokenSecret) {
|
|
55
59
|
return this.config.refreshTokenSecret;
|
|
56
60
|
}
|
|
57
|
-
if (
|
|
61
|
+
if (envConfig.isProduction()) {
|
|
58
62
|
throw new InternalServerErrorException('[AuthModule] REFRESH_TOKEN_SECRET is required in production - ' + 'using the same secret for access and refresh tokens is a security risk');
|
|
59
63
|
}
|
|
60
64
|
if (!this.refreshTokenSecretWarned) {
|
|
@@ -63,14 +67,14 @@ export class AuthConfigService {
|
|
|
63
67
|
}
|
|
64
68
|
return this.getJwtSecret();
|
|
65
69
|
}
|
|
66
|
-
|
|
70
|
+
getRefreshTokenExpiration() {
|
|
67
71
|
return this.config.refreshTokenExpiration ?? '7d';
|
|
68
72
|
}
|
|
69
|
-
|
|
73
|
+
getRefreshTokenCookieName() {
|
|
70
74
|
return this.config.refreshTokenCookieName ?? 'fsn_refresh_token';
|
|
71
75
|
}
|
|
72
76
|
// Frontend Configuration
|
|
73
|
-
|
|
77
|
+
getFrontendUrl() {
|
|
74
78
|
return this.config.frontendUrl;
|
|
75
79
|
}
|
|
76
80
|
constructor(injectedOptions){
|