@flusys/nestjs-auth 1.1.0-beta → 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.
Files changed (94) hide show
  1. package/README.md +633 -468
  2. package/cjs/config/auth.constants.js +8 -0
  3. package/cjs/controllers/authentication.controller.js +175 -167
  4. package/cjs/controllers/branch.controller.js +44 -1
  5. package/cjs/controllers/company-selection.controller.js +27 -20
  6. package/cjs/controllers/company.controller.js +44 -1
  7. package/cjs/controllers/email-verification.controller.js +220 -0
  8. package/cjs/controllers/index.js +1 -0
  9. package/cjs/controllers/user-permission.controller.js +82 -154
  10. package/cjs/controllers/user.controller.js +68 -15
  11. package/cjs/docs/auth-swagger.config.js +14 -7
  12. package/cjs/dtos/authentication.dto.js +16 -43
  13. package/cjs/dtos/index.js +0 -1
  14. package/cjs/dtos/user-permission.dto.js +28 -0
  15. package/cjs/dtos/user.dto.js +19 -4
  16. package/cjs/entities/index.js +16 -17
  17. package/cjs/entities/user-company-permission.entity.js +3 -9
  18. package/cjs/interceptors/clear-token.interceptor.js +10 -23
  19. package/cjs/interceptors/set-token.interceptor.js +15 -55
  20. package/cjs/interfaces/auth-email-provider.interface.js +1 -1
  21. package/cjs/modules/auth.module.js +79 -154
  22. package/cjs/services/auth-config.service.js +33 -35
  23. package/cjs/services/auth-datasource.provider.js +18 -42
  24. package/cjs/services/auth-email.service.js +89 -85
  25. package/cjs/services/authentication.service.js +248 -414
  26. package/cjs/services/branch.service.js +9 -4
  27. package/cjs/services/company-selection-session.service.js +1 -1
  28. package/cjs/services/user-permission.service.js +43 -73
  29. package/cjs/services/user.service.js +78 -64
  30. package/cjs/strategies/jwt.strategy.js +44 -44
  31. package/cjs/validators/password.validator.js +45 -0
  32. package/config/auth.constants.d.ts +2 -0
  33. package/controllers/authentication.controller.d.ts +4 -10
  34. package/controllers/company-selection.controller.d.ts +6 -2
  35. package/controllers/email-verification.controller.d.ts +20 -0
  36. package/controllers/index.d.ts +1 -0
  37. package/controllers/user-permission.controller.d.ts +5 -4
  38. package/controllers/user.controller.d.ts +6 -0
  39. package/dtos/authentication.dto.d.ts +0 -4
  40. package/dtos/company-branch.dto.d.ts +0 -1
  41. package/dtos/company.dto.d.ts +0 -1
  42. package/dtos/index.d.ts +0 -1
  43. package/dtos/user-permission.dto.d.ts +4 -0
  44. package/dtos/user.dto.d.ts +1 -3
  45. package/entities/index.d.ts +5 -10
  46. package/entities/user-company-permission.entity.d.ts +1 -3
  47. package/fesm/config/auth.constants.js +6 -13
  48. package/fesm/controllers/authentication.controller.js +178 -170
  49. package/fesm/controllers/branch.controller.js +45 -2
  50. package/fesm/controllers/company-selection.controller.js +28 -21
  51. package/fesm/controllers/company.controller.js +45 -2
  52. package/fesm/controllers/email-verification.controller.js +210 -0
  53. package/fesm/controllers/index.js +1 -0
  54. package/fesm/controllers/user-permission.controller.js +84 -156
  55. package/fesm/controllers/user.controller.js +71 -18
  56. package/fesm/docs/auth-swagger.config.js +14 -7
  57. package/fesm/dtos/authentication.dto.js +17 -44
  58. package/fesm/dtos/index.js +0 -1
  59. package/fesm/dtos/user-permission.dto.js +28 -0
  60. package/fesm/dtos/user.dto.js +20 -5
  61. package/fesm/entities/index.js +17 -9
  62. package/fesm/entities/user-company-permission.entity.js +3 -9
  63. package/fesm/interceptors/clear-token.interceptor.js +9 -22
  64. package/fesm/interceptors/set-token.interceptor.js +14 -54
  65. package/fesm/interfaces/auth-email-provider.interface.js +1 -1
  66. package/fesm/modules/auth.module.js +82 -157
  67. package/fesm/services/auth-config.service.js +34 -36
  68. package/fesm/services/auth-datasource.provider.js +19 -43
  69. package/fesm/services/auth-email.service.js +90 -86
  70. package/fesm/services/authentication.service.js +248 -414
  71. package/fesm/services/branch.service.js +9 -4
  72. package/fesm/services/company-selection-session.service.js +1 -1
  73. package/fesm/services/user-permission.service.js +44 -74
  74. package/fesm/services/user.service.js +79 -65
  75. package/fesm/strategies/jwt.strategy.js +44 -44
  76. package/fesm/validators/password.validator.js +48 -0
  77. package/interceptors/clear-token.interceptor.d.ts +0 -1
  78. package/interceptors/set-token.interceptor.d.ts +1 -1
  79. package/interfaces/authentication.interface.d.ts +0 -4
  80. package/interfaces/user-enricher.interface.d.ts +1 -4
  81. package/modules/auth.module.d.ts +9 -4
  82. package/package.json +4 -4
  83. package/services/auth-config.service.d.ts +7 -8
  84. package/services/auth-datasource.provider.d.ts +3 -4
  85. package/services/auth-email.service.d.ts +8 -4
  86. package/services/authentication.service.d.ts +16 -16
  87. package/services/company-selection-session.service.d.ts +1 -1
  88. package/services/user-permission.service.d.ts +6 -9
  89. package/services/user.service.d.ts +3 -0
  90. package/strategies/jwt.strategy.d.ts +4 -1
  91. package/validators/password.validator.d.ts +10 -0
  92. package/cjs/dtos/user-company-permission.dto.js +0 -110
  93. package/dtos/user-company-permission.dto.d.ts +0 -10
  94. package/fesm/dtos/user-company-permission.dto.js +0 -98
@@ -25,13 +25,56 @@ function _ts_param(paramIndex, decorator) {
25
25
  decorator(target, key, paramIndex);
26
26
  };
27
27
  }
28
- import { createApiController } from '@flusys/nestjs-shared/classes';
28
+ import { createApiController, BRANCH_PERMISSIONS } from '@flusys/nestjs-shared/classes';
29
29
  import { Controller, Inject } from '@nestjs/common';
30
30
  import { ApiTags } from '@nestjs/swagger';
31
31
  import { CompanyBranchResponseDto, CreateCompanyBranchDto, UpdateCompanyBranchDto } from '../dtos/company-branch.dto';
32
32
  import { BranchService } from '../services/branch.service';
33
33
  export class BranchController extends createApiController(CreateCompanyBranchDto, UpdateCompanyBranchDto, CompanyBranchResponseDto, {
34
- security: 'jwt'
34
+ security: {
35
+ insert: {
36
+ level: 'permission',
37
+ permissions: [
38
+ BRANCH_PERMISSIONS.CREATE
39
+ ]
40
+ },
41
+ insertMany: {
42
+ level: 'permission',
43
+ permissions: [
44
+ BRANCH_PERMISSIONS.CREATE
45
+ ]
46
+ },
47
+ getById: {
48
+ level: 'permission',
49
+ permissions: [
50
+ BRANCH_PERMISSIONS.READ
51
+ ]
52
+ },
53
+ getAll: {
54
+ level: 'permission',
55
+ permissions: [
56
+ BRANCH_PERMISSIONS.READ
57
+ ]
58
+ },
59
+ update: {
60
+ level: 'permission',
61
+ permissions: [
62
+ BRANCH_PERMISSIONS.UPDATE
63
+ ]
64
+ },
65
+ updateMany: {
66
+ level: 'permission',
67
+ permissions: [
68
+ BRANCH_PERMISSIONS.UPDATE
69
+ ]
70
+ },
71
+ delete: {
72
+ level: 'permission',
73
+ permissions: [
74
+ BRANCH_PERMISSIONS.DELETE
75
+ ]
76
+ }
77
+ }
35
78
  }) {
36
79
  constructor(branchService){
37
80
  super(branchService), _define_property(this, "branchService", void 0), this.branchService = branchService;
@@ -26,42 +26,35 @@ function _ts_param(paramIndex, decorator) {
26
26
  };
27
27
  }
28
28
  import { CurrentUser } from '@flusys/nestjs-shared/decorators';
29
- import { Body, Controller, Get, HttpCode, HttpStatus, Inject, Param, Post, UseGuards, UseInterceptors } from '@nestjs/common';
29
+ import { Body, Controller, HttpCode, HttpStatus, Inject, Post, UseGuards, UseInterceptors } from '@nestjs/common';
30
30
  import { ApiBearerAuth, ApiBody, ApiOperation, ApiResponse, ApiTags } from '@nestjs/swagger';
31
31
  import { LoginResponseDto, SelectDto, SwitchCompanyDto } from '../dtos/authentication.dto';
32
32
  import { JwtAuthGuard } from '@flusys/nestjs-shared/guards';
33
33
  import { SetToken } from '../interceptors/set-token.interceptor';
34
34
  import { AuthenticationService } from '../services/authentication.service';
35
35
  export class CompanySelectionController {
36
- /**
37
- * Select Company & Branch
38
- * Used after login when user needs to select company and branch
39
- */ async select(dto) {
36
+ async select(dto) {
40
37
  return this.authService.select(dto.sessionId, dto.companyId, dto.branchId);
41
38
  }
42
- /**
43
- * Switch Company/Branch
44
- * Used to switch company/branch after already logged in
45
- */ async switchCompany(userId, dto) {
39
+ async switchCompany(userId, dto) {
46
40
  return this.authService.switchCompany(userId, dto.companyId, dto.branchId);
47
41
  }
48
- /**
49
- * Get user's companies
50
- */ async getUserCompanies(userId) {
42
+ async getUserCompanies(userId) {
51
43
  const companies = await this.authService.getUserCompanies(userId);
52
44
  return {
53
- companies
45
+ success: true,
46
+ message: 'User companies retrieved successfully',
47
+ data: companies
54
48
  };
55
49
  }
56
- /**
57
- * Get branches for a specific company
58
- */ async getUserBranches(userId, companyId) {
50
+ async getUserBranches(userId, companyId) {
59
51
  const branches = await this.authService.getUserBranches(userId, companyId);
60
52
  return {
61
- branches
53
+ success: true,
54
+ message: 'Company branches retrieved successfully',
55
+ data: branches
62
56
  };
63
57
  }
64
- // NOTE: @Inject() required for bundled code - type metadata may be lost during esbuild
65
58
  constructor(authService){
66
59
  _define_property(this, "authService", void 0);
67
60
  this.authService = authService;
@@ -117,7 +110,8 @@ _ts_decorate([
117
110
  ], CompanySelectionController.prototype, "switchCompany", null);
118
111
  _ts_decorate([
119
112
  UseGuards(JwtAuthGuard),
120
- Get('companies'),
113
+ Post('get-companies'),
114
+ HttpCode(HttpStatus.OK),
121
115
  ApiBearerAuth(),
122
116
  ApiOperation({
123
117
  summary: "Get user's available companies",
@@ -132,14 +126,27 @@ _ts_decorate([
132
126
  ], CompanySelectionController.prototype, "getUserCompanies", null);
133
127
  _ts_decorate([
134
128
  UseGuards(JwtAuthGuard),
135
- Get('companies/:companyId/branches'),
129
+ Post('get-company-branches'),
130
+ HttpCode(HttpStatus.OK),
136
131
  ApiBearerAuth(),
137
132
  ApiOperation({
138
133
  summary: 'Get branches for a company',
139
134
  description: 'Get list of branches for a specific company that the user has access to'
140
135
  }),
136
+ ApiBody({
137
+ schema: {
138
+ properties: {
139
+ companyId: {
140
+ type: 'string'
141
+ }
142
+ },
143
+ required: [
144
+ 'companyId'
145
+ ]
146
+ }
147
+ }),
141
148
  _ts_param(0, CurrentUser('id')),
142
- _ts_param(1, Param('companyId')),
149
+ _ts_param(1, Body('companyId')),
143
150
  _ts_metadata("design:type", Function),
144
151
  _ts_metadata("design:paramtypes", [
145
152
  String,
@@ -25,13 +25,56 @@ function _ts_param(paramIndex, decorator) {
25
25
  decorator(target, key, paramIndex);
26
26
  };
27
27
  }
28
- import { createApiController } from '@flusys/nestjs-shared/classes';
28
+ import { createApiController, COMPANY_PERMISSIONS } from '@flusys/nestjs-shared/classes';
29
29
  import { Controller, Inject } from '@nestjs/common';
30
30
  import { ApiTags } from '@nestjs/swagger';
31
31
  import { CompanyResponseDto, CreateCompanyDto, UpdateCompanyDto } from '../dtos/company.dto';
32
32
  import { CompanyService } from '../services/company.service';
33
33
  export class CompanyController extends createApiController(CreateCompanyDto, UpdateCompanyDto, CompanyResponseDto, {
34
- security: 'jwt'
34
+ security: {
35
+ insert: {
36
+ level: 'permission',
37
+ permissions: [
38
+ COMPANY_PERMISSIONS.CREATE
39
+ ]
40
+ },
41
+ insertMany: {
42
+ level: 'permission',
43
+ permissions: [
44
+ COMPANY_PERMISSIONS.CREATE
45
+ ]
46
+ },
47
+ getById: {
48
+ level: 'permission',
49
+ permissions: [
50
+ COMPANY_PERMISSIONS.READ
51
+ ]
52
+ },
53
+ getAll: {
54
+ level: 'permission',
55
+ permissions: [
56
+ COMPANY_PERMISSIONS.READ
57
+ ]
58
+ },
59
+ update: {
60
+ level: 'permission',
61
+ permissions: [
62
+ COMPANY_PERMISSIONS.UPDATE
63
+ ]
64
+ },
65
+ updateMany: {
66
+ level: 'permission',
67
+ permissions: [
68
+ COMPANY_PERMISSIONS.UPDATE
69
+ ]
70
+ },
71
+ delete: {
72
+ level: 'permission',
73
+ permissions: [
74
+ COMPANY_PERMISSIONS.DELETE
75
+ ]
76
+ }
77
+ }
35
78
  }) {
36
79
  constructor(companyService){
37
80
  super(companyService), _define_property(this, "companyService", void 0), this.companyService = companyService;
@@ -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);
@@ -1,5 +1,6 @@
1
1
  export * from './authentication.controller';
2
2
  export * from './company-selection.controller';
3
+ export * from './email-verification.controller';
3
4
  export * from './user.controller';
4
5
  export * from './company.controller';
5
6
  export * from './branch.controller';