@flusys/nestjs-auth 1.0.0-beta → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (106) hide show
  1. package/README.md +590 -473
  2. package/cjs/config/auth.constants.js +12 -0
  3. package/cjs/controllers/authentication.controller.js +365 -24
  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/user-permission.controller.js +82 -154
  8. package/cjs/controllers/user.controller.js +211 -7
  9. package/cjs/docs/auth-swagger.config.js +14 -7
  10. package/cjs/dtos/authentication.dto.js +114 -38
  11. package/cjs/dtos/index.js +0 -1
  12. package/cjs/dtos/user-permission.dto.js +28 -0
  13. package/cjs/dtos/user.dto.js +19 -4
  14. package/cjs/entities/index.js +5 -1
  15. package/cjs/entities/pending-registration.entity.js +125 -0
  16. package/cjs/entities/user-company-permission.entity.js +3 -9
  17. package/cjs/entities/user-token.entity.js +129 -0
  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 +45 -0
  21. package/cjs/interfaces/index.js +2 -0
  22. package/cjs/interfaces/user-enricher.interface.js +4 -0
  23. package/cjs/modules/auth.module.js +65 -143
  24. package/cjs/services/auth-config.service.js +25 -27
  25. package/cjs/services/auth-datasource.provider.js +13 -23
  26. package/cjs/services/auth-email.service.js +456 -0
  27. package/cjs/services/authentication.service.js +297 -349
  28. package/cjs/services/branch.service.js +9 -4
  29. package/cjs/services/company-selection-session.service.js +1 -1
  30. package/cjs/services/index.js +1 -0
  31. package/cjs/services/user-permission.service.js +43 -73
  32. package/cjs/services/user.service.js +184 -34
  33. package/cjs/strategies/jwt.strategy.js +44 -44
  34. package/cjs/validators/password.validator.js +45 -0
  35. package/config/auth.constants.d.ts +3 -0
  36. package/controllers/authentication.controller.d.ts +16 -10
  37. package/controllers/company-selection.controller.d.ts +6 -2
  38. package/controllers/user-permission.controller.d.ts +5 -4
  39. package/controllers/user.controller.d.ts +33 -0
  40. package/dtos/authentication.dto.d.ts +20 -6
  41. package/dtos/company-branch.dto.d.ts +0 -1
  42. package/dtos/company.dto.d.ts +0 -1
  43. package/dtos/index.d.ts +0 -1
  44. package/dtos/user-permission.dto.d.ts +4 -0
  45. package/dtos/user.dto.d.ts +1 -2
  46. package/entities/index.d.ts +7 -3
  47. package/entities/pending-registration.entity.d.ts +17 -0
  48. package/entities/user-company-permission.entity.d.ts +1 -3
  49. package/entities/user-token.entity.d.ts +15 -0
  50. package/fesm/config/auth.constants.js +6 -2
  51. package/fesm/controllers/authentication.controller.js +368 -27
  52. package/fesm/controllers/branch.controller.js +45 -2
  53. package/fesm/controllers/company-selection.controller.js +28 -21
  54. package/fesm/controllers/company.controller.js +45 -2
  55. package/fesm/controllers/user-permission.controller.js +84 -156
  56. package/fesm/controllers/user.controller.js +214 -10
  57. package/fesm/docs/auth-swagger.config.js +14 -7
  58. package/fesm/dtos/authentication.dto.js +101 -39
  59. package/fesm/dtos/index.js +0 -1
  60. package/fesm/dtos/user-permission.dto.js +28 -0
  61. package/fesm/dtos/user.dto.js +20 -5
  62. package/fesm/entities/index.js +7 -1
  63. package/fesm/entities/pending-registration.entity.js +115 -0
  64. package/fesm/entities/user-company-permission.entity.js +3 -9
  65. package/fesm/entities/user-token.entity.js +113 -0
  66. package/fesm/interceptors/clear-token.interceptor.js +9 -22
  67. package/fesm/interceptors/set-token.interceptor.js +14 -54
  68. package/fesm/interfaces/auth-email-provider.interface.js +38 -0
  69. package/fesm/interfaces/authentication.interface.js +1 -1
  70. package/fesm/interfaces/index.js +2 -0
  71. package/fesm/interfaces/user-enricher.interface.js +26 -0
  72. package/fesm/modules/auth.module.js +67 -145
  73. package/fesm/services/auth-config.service.js +26 -28
  74. package/fesm/services/auth-datasource.provider.js +14 -24
  75. package/fesm/services/auth-email.service.js +405 -0
  76. package/fesm/services/authentication.service.js +297 -349
  77. package/fesm/services/branch.service.js +9 -4
  78. package/fesm/services/company-selection-session.service.js +1 -1
  79. package/fesm/services/index.js +1 -0
  80. package/fesm/services/user-permission.service.js +44 -74
  81. package/fesm/services/user.service.js +186 -36
  82. package/fesm/strategies/jwt.strategy.js +44 -44
  83. package/fesm/validators/password.validator.js +48 -0
  84. package/interceptors/clear-token.interceptor.d.ts +0 -1
  85. package/interceptors/set-token.interceptor.d.ts +1 -1
  86. package/interfaces/auth-email-provider.interface.d.ts +6 -0
  87. package/interfaces/auth-module-options.interface.d.ts +4 -1
  88. package/interfaces/authentication.interface.d.ts +13 -3
  89. package/interfaces/index.d.ts +2 -0
  90. package/interfaces/user-enricher.interface.d.ts +64 -0
  91. package/interfaces/user.interface.d.ts +1 -0
  92. package/modules/auth.module.d.ts +6 -3
  93. package/package.json +4 -4
  94. package/services/auth-config.service.d.ts +7 -8
  95. package/services/auth-datasource.provider.d.ts +2 -4
  96. package/services/auth-email.service.d.ts +54 -0
  97. package/services/authentication.service.d.ts +27 -16
  98. package/services/company-selection-session.service.d.ts +1 -1
  99. package/services/index.d.ts +1 -0
  100. package/services/user-permission.service.d.ts +6 -9
  101. package/services/user.service.d.ts +19 -3
  102. package/strategies/jwt.strategy.d.ts +4 -1
  103. package/validators/password.validator.d.ts +10 -0
  104. package/cjs/dtos/user-company-permission.dto.js +0 -110
  105. package/dtos/user-company-permission.dto.d.ts +0 -10
  106. package/fesm/dtos/user-company-permission.dto.js +0 -98
@@ -16,14 +16,26 @@ _export(exports, {
16
16
  get BCRYPT_SALT_ROUNDS () {
17
17
  return BCRYPT_SALT_ROUNDS;
18
18
  },
19
+ get DEFAULT_COOKIE_NAME () {
20
+ return DEFAULT_COOKIE_NAME;
21
+ },
22
+ get MAX_COOKIE_BYTES () {
23
+ return MAX_COOKIE_BYTES;
24
+ },
19
25
  get SESSION_CACHE_PREFIX () {
20
26
  return SESSION_CACHE_PREFIX;
21
27
  },
22
28
  get TOKEN_REVOKED_PREFIX () {
23
29
  return TOKEN_REVOKED_PREFIX;
30
+ },
31
+ get USER_ENRICHER () {
32
+ return USER_ENRICHER;
24
33
  }
25
34
  });
26
35
  const AUTH_MODULE_OPTIONS = 'AUTH_MODULE_OPTIONS';
36
+ const USER_ENRICHER = 'USER_ENRICHER';
27
37
  const BCRYPT_SALT_ROUNDS = 12;
38
+ const DEFAULT_COOKIE_NAME = 'fsn_refresh_token';
39
+ const MAX_COOKIE_BYTES = 3500;
28
40
  const SESSION_CACHE_PREFIX = 'auth:session';
29
41
  const TOKEN_REVOKED_PREFIX = 'auth:revoked';
@@ -9,15 +9,19 @@ Object.defineProperty(exports, "AuthenticationController", {
9
9
  }
10
10
  });
11
11
  const _decorators = require("@flusys/nestjs-shared/decorators");
12
+ const _dtos = require("@flusys/nestjs-shared/dtos");
12
13
  const _guards = require("@flusys/nestjs-shared/guards");
13
14
  const _interfaces = require("@flusys/nestjs-shared/interfaces");
14
15
  const _common = require("@nestjs/common");
15
16
  const _swagger = require("@nestjs/swagger");
17
+ const _throttler = require("@nestjs/throttler");
16
18
  const _express = require("express");
19
+ const _config = require("../config");
17
20
  const _authenticationdto = require("../dtos/authentication.dto");
18
21
  const _cleartokeninterceptor = require("../interceptors/clear-token.interceptor");
19
22
  const _settokeninterceptor = require("../interceptors/set-token.interceptor");
20
23
  const _authconfigservice = require("../services/auth-config.service");
24
+ const _authemailservice = require("../services/auth-email.service");
21
25
  const _authenticationservice = require("../services/authentication.service");
22
26
  function _define_property(obj, key, value) {
23
27
  if (key in obj) {
@@ -47,24 +51,41 @@ function _ts_param(paramIndex, decorator) {
47
51
  };
48
52
  }
49
53
  let AuthenticationController = class AuthenticationController {
50
- // Core Endpoints
51
- /** Login - Returns tokens or company/branch selection requirement */ async login(loginDto) {
54
+ buildAuthUrl(req, path) {
55
+ const frontendUrl = this.authConfig?.getFrontendUrl();
56
+ return frontendUrl ? `${frontendUrl}${path}` : `${req.protocol}://${req.get('host')}${path}`;
57
+ }
58
+ get emailService() {
59
+ if (!this.authEmailService) {
60
+ throw new Error('Email service is not configured');
61
+ }
62
+ return this.authEmailService;
63
+ }
64
+ get isEmailEnabled() {
65
+ return !!this.authEmailService;
66
+ }
67
+ async login(loginDto) {
52
68
  const result = await this.authService.login(loginDto.email, loginDto.password);
69
+ if ('requiresEmailVerification' in result) {
70
+ return result;
71
+ }
53
72
  if ('requiresSelection' in result) {
54
73
  return result;
55
74
  }
56
75
  return result;
57
76
  }
58
- /** Register new user. If company feature enabled, can join/create company. */ async register(registrationDto) {
59
- const result = await this.authService.register(registrationDto);
60
- return {
61
- ...result,
62
- companyFeatureEnabled: this.authConfig?.isCompanyFeatureEnabled() ?? false
63
- };
77
+ /** Register new user. If company feature enabled, can join/create company. */ async register(req, registrationDto) {
78
+ const verifyUrlBase = this.buildAuthUrl(req, '/auth/verify-email');
79
+ const result = await this.authService.register(registrationDto, verifyUrlBase);
80
+ return result;
64
81
  }
65
- /** Refresh access token. Browser uses HTTP-only cookie, API/Mobile uses request body. */ async refreshToken(req, refreshTokenDto) {
66
- // Get refresh token from cookie (browser) or body (API/mobile)
67
- const cookieName = this.authConfig?.getRefreshTokenCookieName() ?? 'fsn_refresh_token';
82
+ /**
83
+ * Refresh access token.
84
+ * - **Browser**: Prefers HTTP-only cookie, falls back to body if cookie missing.
85
+ * - **API/Mobile**: Must send `refreshToken` in request body. Set header `x-client-type: mobile` or `x-client-type: api`.
86
+ */ async refreshToken(req, refreshTokenDto) {
87
+ const cookieName = this.authConfig?.getRefreshTokenCookieName() ?? _config.DEFAULT_COOKIE_NAME;
88
+ // Always check cookie first, then body - handles Browser, SSR, and Mobile/API
68
89
  const refreshToken = req.cookies?.[cookieName] || refreshTokenDto.refreshToken;
69
90
  if (!refreshToken) {
70
91
  throw new _common.UnauthorizedException('Refresh token is required');
@@ -77,26 +98,78 @@ let AuthenticationController = class AuthenticationController {
77
98
  /** Logout - Clears refresh token cookie for browsers */ async logout(userId) {
78
99
  await this.authService.logout(userId);
79
100
  return {
101
+ success: true,
80
102
  message: 'Logged out successfully'
81
103
  };
82
104
  }
83
- /** Change password */ async changePassword(userId, dto) {
105
+ async changePassword(userId, dto) {
84
106
  await this.authService.changePassword(userId, dto.currentPassword, dto.newPassword);
85
107
  return {
108
+ success: true,
86
109
  message: 'Password changed successfully'
87
110
  };
88
111
  }
89
- // NOTE: @Inject() required for bundled code - type metadata may be lost during esbuild
90
- constructor(authService, authConfig){
112
+ async forgotPassword(req, dto) {
113
+ if (!this.isEmailEnabled) {
114
+ return {
115
+ success: false,
116
+ message: 'Email service is not configured'
117
+ };
118
+ }
119
+ return this.emailService.forgotPassword(dto.email, this.buildAuthUrl(req, '/auth/reset-password'));
120
+ }
121
+ async resetPassword(dto) {
122
+ if (!this.isEmailEnabled) {
123
+ return {
124
+ success: false,
125
+ message: 'Email service is not configured'
126
+ };
127
+ }
128
+ return this.emailService.resetPassword(dto.token, dto.newPassword);
129
+ }
130
+ async resendVerification(req, dto) {
131
+ if (!this.isEmailEnabled) {
132
+ return {
133
+ success: false,
134
+ message: 'Email service is not configured'
135
+ };
136
+ }
137
+ return this.emailService.resendVerificationEmail(dto.email, this.buildAuthUrl(req, '/auth/verify-email'));
138
+ }
139
+ /** Verify email - Verify email using token. Handles both pending registration and existing user verification. */ async verifyEmail(dto) {
140
+ if (!this.isEmailEnabled) {
141
+ return {
142
+ success: false,
143
+ message: 'Email service is not configured'
144
+ };
145
+ }
146
+ const result = await this.emailService.verifyEmail(dto.token);
147
+ if (result.type === 'pending') {
148
+ return this.authService.createUserFromPendingRegistration(result.pending);
149
+ }
150
+ return {
151
+ success: true,
152
+ message: result.message
153
+ };
154
+ }
155
+ constructor(authService, authConfig, authEmailService){
91
156
  _define_property(this, "authService", void 0);
92
157
  _define_property(this, "authConfig", void 0);
158
+ _define_property(this, "authEmailService", void 0);
93
159
  this.authService = authService;
94
160
  this.authConfig = authConfig;
161
+ this.authEmailService = authEmailService;
95
162
  }
96
163
  };
97
164
  _ts_decorate([
98
165
  (0, _common.Post)('login'),
99
166
  (0, _common.HttpCode)(_common.HttpStatus.OK),
167
+ (0, _throttler.Throttle)({
168
+ default: {
169
+ limit: 5,
170
+ ttl: 60000
171
+ }
172
+ }),
100
173
  (0, _common.UseInterceptors)(_settokeninterceptor.SetToken),
101
174
  (0, _swagger.ApiOperation)({
102
175
  summary: 'User login'
@@ -104,13 +177,102 @@ _ts_decorate([
104
177
  (0, _swagger.ApiBody)({
105
178
  type: _authenticationdto.LoginDto
106
179
  }),
180
+ (0, _swagger.ApiExtraModels)(_authenticationdto.LoginResponseDto, _authenticationdto.CompanySelectionResponseDto, _authenticationdto.LoginResponseRequiresEmailVerificationDto),
107
181
  (0, _swagger.ApiResponse)({
108
182
  status: 200,
109
- type: _authenticationdto.LoginResponseDto
110
- }),
111
- (0, _swagger.ApiResponse)({
112
- status: 200,
113
- type: _authenticationdto.CompanySelectionResponseDto
183
+ description: 'Login successful, requires company selection, or requires email verification',
184
+ content: {
185
+ 'application/json': {
186
+ schema: {
187
+ oneOf: [
188
+ {
189
+ $ref: (0, _swagger.getSchemaPath)(_authenticationdto.LoginResponseDto)
190
+ },
191
+ {
192
+ $ref: (0, _swagger.getSchemaPath)(_authenticationdto.CompanySelectionResponseDto)
193
+ },
194
+ {
195
+ $ref: (0, _swagger.getSchemaPath)(_authenticationdto.LoginResponseRequiresEmailVerificationDto)
196
+ }
197
+ ]
198
+ },
199
+ examples: {
200
+ loginSuccess: {
201
+ summary: 'Login Success',
202
+ description: 'Successful login with tokens (company/branch included when company feature enabled)',
203
+ value: {
204
+ accessToken: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...',
205
+ refreshToken: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...',
206
+ user: {
207
+ id: '550e8400-e29b-41d4-a716-446655440000',
208
+ email: 'john@example.com',
209
+ name: 'John Doe'
210
+ }
211
+ }
212
+ },
213
+ loginSuccessWithCompany: {
214
+ summary: 'Login Success (Company Feature)',
215
+ description: 'Login with company/branch - only when company feature is enabled',
216
+ value: {
217
+ accessToken: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...',
218
+ refreshToken: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...',
219
+ user: {
220
+ id: '550e8400-e29b-41d4-a716-446655440000',
221
+ email: 'john@example.com',
222
+ name: 'John Doe'
223
+ },
224
+ company: {
225
+ id: '550e8400-e29b-41d4-a716-446655440001',
226
+ name: 'Acme Corporation',
227
+ slug: 'acme-corp'
228
+ },
229
+ branch: {
230
+ id: '550e8400-e29b-41d4-a716-446655440002',
231
+ name: 'Main Branch',
232
+ slug: 'main-branch'
233
+ }
234
+ }
235
+ },
236
+ companySelection: {
237
+ summary: 'Company Selection Required (Company Feature)',
238
+ description: 'User has multiple companies/branches - only when company feature is enabled',
239
+ value: {
240
+ requiresSelection: true,
241
+ sessionId: 'sess_abc123def456',
242
+ expiresAt: '2024-12-18T15:30:00.000Z',
243
+ user: {
244
+ id: '550e8400-e29b-41d4-a716-446655440000',
245
+ email: 'john@example.com',
246
+ name: 'John Doe'
247
+ },
248
+ companies: [
249
+ {
250
+ id: '550e8400-e29b-41d4-a716-446655440001',
251
+ name: 'Company A',
252
+ slug: 'company-a',
253
+ branches: [
254
+ {
255
+ id: '550e8400-e29b-41d4-a716-446655440010',
256
+ name: 'Branch 1',
257
+ slug: 'branch-1'
258
+ }
259
+ ]
260
+ }
261
+ ]
262
+ }
263
+ },
264
+ emailVerification: {
265
+ summary: 'Email Verification Required',
266
+ description: 'User must verify email before logging in',
267
+ value: {
268
+ requiresEmailVerification: true,
269
+ email: 'john@example.com',
270
+ message: 'Please verify your email address before logging in.'
271
+ }
272
+ }
273
+ }
274
+ }
275
+ }
114
276
  }),
115
277
  _ts_param(0, (0, _common.Body)()),
116
278
  _ts_metadata("design:type", Function),
@@ -122,6 +284,12 @@ _ts_decorate([
122
284
  _ts_decorate([
123
285
  (0, _common.Post)('register'),
124
286
  (0, _common.HttpCode)(_common.HttpStatus.CREATED),
287
+ (0, _throttler.Throttle)({
288
+ default: {
289
+ limit: 3,
290
+ ttl: 60000
291
+ }
292
+ }),
125
293
  (0, _common.UseInterceptors)(_settokeninterceptor.SetToken),
126
294
  (0, _swagger.ApiOperation)({
127
295
  summary: 'Register new user'
@@ -133,9 +301,11 @@ _ts_decorate([
133
301
  status: 201,
134
302
  type: _authenticationdto.RegistrationResponseDto
135
303
  }),
136
- _ts_param(0, (0, _common.Body)()),
304
+ _ts_param(0, (0, _common.Req)()),
305
+ _ts_param(1, (0, _common.Body)()),
137
306
  _ts_metadata("design:type", Function),
138
307
  _ts_metadata("design:paramtypes", [
308
+ typeof _express.Request === "undefined" ? Object : _express.Request,
139
309
  typeof _authenticationdto.RegistrationDto === "undefined" ? Object : _authenticationdto.RegistrationDto
140
310
  ]),
141
311
  _ts_metadata("design:returntype", Promise)
@@ -143,11 +313,50 @@ _ts_decorate([
143
313
  _ts_decorate([
144
314
  (0, _common.Post)('refresh'),
145
315
  (0, _common.HttpCode)(_common.HttpStatus.OK),
316
+ (0, _throttler.Throttle)({
317
+ default: {
318
+ limit: 30,
319
+ ttl: 60000
320
+ }
321
+ }),
146
322
  (0, _swagger.ApiOperation)({
147
- summary: 'Refresh access token'
323
+ summary: 'Refresh access token',
324
+ description: `
325
+ **Browser clients**: Refresh token is read from HTTP-only cookie (automatically set on login/register).
326
+ Falls back to request body if cookie is not available.
327
+
328
+ **API/Mobile clients**: Must send \`refreshToken\` in request body.
329
+ Set header \`x-client-type: mobile\` or \`x-client-type: api\` to identify as non-browser client.
330
+
331
+ **Client detection**: Uses \`x-client-type\` header first, then falls back to User-Agent detection.
332
+ `
333
+ }),
334
+ (0, _swagger.ApiHeader)({
335
+ name: 'x-client-type',
336
+ required: false,
337
+ description: 'Client type: "browser"/"web" for cookie-based auth, "mobile"/"api" for body-based auth',
338
+ example: 'mobile'
148
339
  }),
149
340
  (0, _swagger.ApiBody)({
150
- type: _authenticationdto.RefreshTokenDto
341
+ type: _authenticationdto.RefreshTokenDto,
342
+ description: 'Required for API/Mobile clients. Browser clients prefer HTTP-only cookie with body fallback.'
343
+ }),
344
+ (0, _swagger.ApiResponse)({
345
+ status: 200,
346
+ description: 'New access token',
347
+ schema: {
348
+ type: 'object',
349
+ properties: {
350
+ accessToken: {
351
+ type: 'string',
352
+ example: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...'
353
+ }
354
+ }
355
+ }
356
+ }),
357
+ (0, _swagger.ApiResponse)({
358
+ status: 401,
359
+ description: 'Invalid or missing refresh token'
151
360
  }),
152
361
  _ts_param(0, (0, _common.Req)()),
153
362
  _ts_param(1, (0, _common.Body)()),
@@ -160,7 +369,8 @@ _ts_decorate([
160
369
  ], AuthenticationController.prototype, "refreshToken", null);
161
370
  _ts_decorate([
162
371
  (0, _common.UseGuards)(_guards.JwtAuthGuard),
163
- (0, _common.Get)('me'),
372
+ (0, _common.Post)('me'),
373
+ (0, _throttler.SkipThrottle)(),
164
374
  (0, _swagger.ApiBearerAuth)(),
165
375
  (0, _swagger.ApiOperation)({
166
376
  summary: 'Get current user info'
@@ -180,11 +390,16 @@ _ts_decorate([
180
390
  (0, _common.UseGuards)(_guards.JwtAuthGuard),
181
391
  (0, _common.Post)('logout'),
182
392
  (0, _common.HttpCode)(_common.HttpStatus.OK),
393
+ (0, _throttler.SkipThrottle)(),
183
394
  (0, _common.UseInterceptors)(_cleartokeninterceptor.ClearToken),
184
395
  (0, _swagger.ApiBearerAuth)(),
185
396
  (0, _swagger.ApiOperation)({
186
397
  summary: 'Logout user'
187
398
  }),
399
+ (0, _swagger.ApiResponse)({
400
+ status: 200,
401
+ type: _dtos.MessageResponseDto
402
+ }),
188
403
  _ts_param(0, (0, _decorators.CurrentUser)('id')),
189
404
  _ts_metadata("design:type", Function),
190
405
  _ts_metadata("design:paramtypes", [
@@ -196,6 +411,12 @@ _ts_decorate([
196
411
  (0, _common.UseGuards)(_guards.JwtAuthGuard),
197
412
  (0, _common.Post)('change-password'),
198
413
  (0, _common.HttpCode)(_common.HttpStatus.OK),
414
+ (0, _throttler.Throttle)({
415
+ default: {
416
+ limit: 5,
417
+ ttl: 60000
418
+ }
419
+ }),
199
420
  (0, _swagger.ApiBearerAuth)(),
200
421
  (0, _swagger.ApiOperation)({
201
422
  summary: 'Change password'
@@ -203,6 +424,10 @@ _ts_decorate([
203
424
  (0, _swagger.ApiBody)({
204
425
  type: _authenticationdto.ChangePasswordDto
205
426
  }),
427
+ (0, _swagger.ApiResponse)({
428
+ status: 200,
429
+ type: _dtos.MessageResponseDto
430
+ }),
206
431
  _ts_param(0, (0, _decorators.CurrentUser)('id')),
207
432
  _ts_param(1, (0, _common.Body)()),
208
433
  _ts_metadata("design:type", Function),
@@ -212,15 +437,131 @@ _ts_decorate([
212
437
  ]),
213
438
  _ts_metadata("design:returntype", Promise)
214
439
  ], AuthenticationController.prototype, "changePassword", null);
440
+ _ts_decorate([
441
+ (0, _common.Post)('forgot-password'),
442
+ (0, _common.HttpCode)(_common.HttpStatus.OK),
443
+ (0, _throttler.Throttle)({
444
+ default: {
445
+ limit: 3,
446
+ ttl: 300000
447
+ }
448
+ }),
449
+ (0, _swagger.ApiOperation)({
450
+ summary: 'Request password reset email'
451
+ }),
452
+ (0, _swagger.ApiBody)({
453
+ type: _authenticationdto.ForgotPasswordDto
454
+ }),
455
+ (0, _swagger.ApiResponse)({
456
+ status: 200,
457
+ type: _dtos.MessageResponseDto
458
+ }),
459
+ _ts_param(0, (0, _common.Req)()),
460
+ _ts_param(1, (0, _common.Body)()),
461
+ _ts_metadata("design:type", Function),
462
+ _ts_metadata("design:paramtypes", [
463
+ typeof _express.Request === "undefined" ? Object : _express.Request,
464
+ typeof _authenticationdto.ForgotPasswordDto === "undefined" ? Object : _authenticationdto.ForgotPasswordDto
465
+ ]),
466
+ _ts_metadata("design:returntype", Promise)
467
+ ], AuthenticationController.prototype, "forgotPassword", null);
468
+ _ts_decorate([
469
+ (0, _common.Post)('reset-password'),
470
+ (0, _common.HttpCode)(_common.HttpStatus.OK),
471
+ (0, _throttler.Throttle)({
472
+ default: {
473
+ limit: 5,
474
+ ttl: 900000
475
+ }
476
+ }),
477
+ (0, _swagger.ApiOperation)({
478
+ summary: 'Reset password using token'
479
+ }),
480
+ (0, _swagger.ApiBody)({
481
+ type: _authenticationdto.ResetPasswordDto
482
+ }),
483
+ (0, _swagger.ApiResponse)({
484
+ status: 200,
485
+ type: _dtos.MessageResponseDto
486
+ }),
487
+ _ts_param(0, (0, _common.Body)()),
488
+ _ts_metadata("design:type", Function),
489
+ _ts_metadata("design:paramtypes", [
490
+ typeof _authenticationdto.ResetPasswordDto === "undefined" ? Object : _authenticationdto.ResetPasswordDto
491
+ ]),
492
+ _ts_metadata("design:returntype", Promise)
493
+ ], AuthenticationController.prototype, "resetPassword", null);
494
+ _ts_decorate([
495
+ (0, _common.Post)('resend-verification'),
496
+ (0, _common.HttpCode)(_common.HttpStatus.OK),
497
+ (0, _throttler.Throttle)({
498
+ default: {
499
+ limit: 3,
500
+ ttl: 300000
501
+ }
502
+ }),
503
+ (0, _swagger.ApiOperation)({
504
+ summary: 'Resend email verification link'
505
+ }),
506
+ (0, _swagger.ApiBody)({
507
+ type: _authenticationdto.ResendVerificationDto
508
+ }),
509
+ (0, _swagger.ApiResponse)({
510
+ status: 200,
511
+ type: _dtos.MessageResponseDto
512
+ }),
513
+ _ts_param(0, (0, _common.Req)()),
514
+ _ts_param(1, (0, _common.Body)()),
515
+ _ts_metadata("design:type", Function),
516
+ _ts_metadata("design:paramtypes", [
517
+ typeof _express.Request === "undefined" ? Object : _express.Request,
518
+ typeof _authenticationdto.ResendVerificationDto === "undefined" ? Object : _authenticationdto.ResendVerificationDto
519
+ ]),
520
+ _ts_metadata("design:returntype", Promise)
521
+ ], AuthenticationController.prototype, "resendVerification", null);
522
+ _ts_decorate([
523
+ (0, _common.Post)('verify-email'),
524
+ (0, _common.HttpCode)(_common.HttpStatus.OK),
525
+ (0, _throttler.Throttle)({
526
+ default: {
527
+ limit: 10,
528
+ ttl: 60000
529
+ }
530
+ }),
531
+ (0, _common.UseInterceptors)(_settokeninterceptor.SetToken),
532
+ (0, _swagger.ApiOperation)({
533
+ summary: 'Verify email using token'
534
+ }),
535
+ (0, _swagger.ApiBody)({
536
+ type: _authenticationdto.VerifyEmailDto
537
+ }),
538
+ (0, _swagger.ApiResponse)({
539
+ status: 200,
540
+ type: _dtos.MessageResponseDto
541
+ }),
542
+ (0, _swagger.ApiResponse)({
543
+ status: 200,
544
+ type: _authenticationdto.RegistrationResponseDto
545
+ }),
546
+ _ts_param(0, (0, _common.Body)()),
547
+ _ts_metadata("design:type", Function),
548
+ _ts_metadata("design:paramtypes", [
549
+ typeof _authenticationdto.VerifyEmailDto === "undefined" ? Object : _authenticationdto.VerifyEmailDto
550
+ ]),
551
+ _ts_metadata("design:returntype", Promise)
552
+ ], AuthenticationController.prototype, "verifyEmail", null);
215
553
  AuthenticationController = _ts_decorate([
216
554
  (0, _swagger.ApiTags)('Authentication'),
217
555
  (0, _common.Controller)('auth'),
218
556
  _ts_param(0, (0, _common.Inject)(_authenticationservice.AuthenticationService)),
219
557
  _ts_param(1, (0, _common.Optional)()),
220
558
  _ts_param(1, (0, _common.Inject)(_authconfigservice.AuthConfigService)),
559
+ _ts_param(2, (0, _common.Optional)()),
560
+ _ts_param(2, (0, _common.Inject)(_authemailservice.AuthEmailService)),
221
561
  _ts_metadata("design:type", Function),
222
562
  _ts_metadata("design:paramtypes", [
223
563
  typeof _authenticationservice.AuthenticationService === "undefined" ? Object : _authenticationservice.AuthenticationService,
224
- typeof _authconfigservice.AuthConfigService === "undefined" ? Object : _authconfigservice.AuthConfigService
564
+ typeof _authconfigservice.AuthConfigService === "undefined" ? Object : _authconfigservice.AuthConfigService,
565
+ typeof _authemailservice.AuthEmailService === "undefined" ? Object : _authemailservice.AuthEmailService
225
566
  ])
226
567
  ], AuthenticationController);
@@ -41,7 +41,50 @@ function _ts_param(paramIndex, decorator) {
41
41
  };
42
42
  }
43
43
  let BranchController = class BranchController extends (0, _classes.createApiController)(_companybranchdto.CreateCompanyBranchDto, _companybranchdto.UpdateCompanyBranchDto, _companybranchdto.CompanyBranchResponseDto, {
44
- security: 'jwt'
44
+ security: {
45
+ insert: {
46
+ level: 'permission',
47
+ permissions: [
48
+ _classes.BRANCH_PERMISSIONS.CREATE
49
+ ]
50
+ },
51
+ insertMany: {
52
+ level: 'permission',
53
+ permissions: [
54
+ _classes.BRANCH_PERMISSIONS.CREATE
55
+ ]
56
+ },
57
+ getById: {
58
+ level: 'permission',
59
+ permissions: [
60
+ _classes.BRANCH_PERMISSIONS.READ
61
+ ]
62
+ },
63
+ getAll: {
64
+ level: 'permission',
65
+ permissions: [
66
+ _classes.BRANCH_PERMISSIONS.READ
67
+ ]
68
+ },
69
+ update: {
70
+ level: 'permission',
71
+ permissions: [
72
+ _classes.BRANCH_PERMISSIONS.UPDATE
73
+ ]
74
+ },
75
+ updateMany: {
76
+ level: 'permission',
77
+ permissions: [
78
+ _classes.BRANCH_PERMISSIONS.UPDATE
79
+ ]
80
+ },
81
+ delete: {
82
+ level: 'permission',
83
+ permissions: [
84
+ _classes.BRANCH_PERMISSIONS.DELETE
85
+ ]
86
+ }
87
+ }
45
88
  }) {
46
89
  constructor(branchService){
47
90
  super(branchService), _define_property(this, "branchService", void 0), this.branchService = branchService;
@@ -43,35 +43,28 @@ function _ts_param(paramIndex, decorator) {
43
43
  };
44
44
  }
45
45
  let CompanySelectionController = class CompanySelectionController {
46
- /**
47
- * Select Company & Branch
48
- * Used after login when user needs to select company and branch
49
- */ async select(dto) {
46
+ async select(dto) {
50
47
  return this.authService.select(dto.sessionId, dto.companyId, dto.branchId);
51
48
  }
52
- /**
53
- * Switch Company/Branch
54
- * Used to switch company/branch after already logged in
55
- */ async switchCompany(userId, dto) {
49
+ async switchCompany(userId, dto) {
56
50
  return this.authService.switchCompany(userId, dto.companyId, dto.branchId);
57
51
  }
58
- /**
59
- * Get user's companies
60
- */ async getUserCompanies(userId) {
52
+ async getUserCompanies(userId) {
61
53
  const companies = await this.authService.getUserCompanies(userId);
62
54
  return {
63
- companies
55
+ success: true,
56
+ message: 'User companies retrieved successfully',
57
+ data: companies
64
58
  };
65
59
  }
66
- /**
67
- * Get branches for a specific company
68
- */ async getUserBranches(userId, companyId) {
60
+ async getUserBranches(userId, companyId) {
69
61
  const branches = await this.authService.getUserBranches(userId, companyId);
70
62
  return {
71
- branches
63
+ success: true,
64
+ message: 'Company branches retrieved successfully',
65
+ data: branches
72
66
  };
73
67
  }
74
- // NOTE: @Inject() required for bundled code - type metadata may be lost during esbuild
75
68
  constructor(authService){
76
69
  _define_property(this, "authService", void 0);
77
70
  this.authService = authService;
@@ -127,7 +120,8 @@ _ts_decorate([
127
120
  ], CompanySelectionController.prototype, "switchCompany", null);
128
121
  _ts_decorate([
129
122
  (0, _common.UseGuards)(_guards.JwtAuthGuard),
130
- (0, _common.Get)('companies'),
123
+ (0, _common.Post)('get-companies'),
124
+ (0, _common.HttpCode)(_common.HttpStatus.OK),
131
125
  (0, _swagger.ApiBearerAuth)(),
132
126
  (0, _swagger.ApiOperation)({
133
127
  summary: "Get user's available companies",
@@ -142,14 +136,27 @@ _ts_decorate([
142
136
  ], CompanySelectionController.prototype, "getUserCompanies", null);
143
137
  _ts_decorate([
144
138
  (0, _common.UseGuards)(_guards.JwtAuthGuard),
145
- (0, _common.Get)('companies/:companyId/branches'),
139
+ (0, _common.Post)('get-company-branches'),
140
+ (0, _common.HttpCode)(_common.HttpStatus.OK),
146
141
  (0, _swagger.ApiBearerAuth)(),
147
142
  (0, _swagger.ApiOperation)({
148
143
  summary: 'Get branches for a company',
149
144
  description: 'Get list of branches for a specific company that the user has access to'
150
145
  }),
146
+ (0, _swagger.ApiBody)({
147
+ schema: {
148
+ properties: {
149
+ companyId: {
150
+ type: 'string'
151
+ }
152
+ },
153
+ required: [
154
+ 'companyId'
155
+ ]
156
+ }
157
+ }),
151
158
  _ts_param(0, (0, _decorators.CurrentUser)('id')),
152
- _ts_param(1, (0, _common.Param)('companyId')),
159
+ _ts_param(1, (0, _common.Body)('companyId')),
153
160
  _ts_metadata("design:type", Function),
154
161
  _ts_metadata("design:paramtypes", [
155
162
  String,