@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.
Files changed (45) hide show
  1. package/README.md +151 -719
  2. package/cjs/config/message-keys.js +6 -61
  3. package/cjs/controllers/authentication.controller.js +113 -87
  4. package/cjs/controllers/company-selection.controller.js +24 -4
  5. package/cjs/controllers/email-verification.controller.js +12 -13
  6. package/cjs/docs/auth-swagger.config.js +143 -106
  7. package/cjs/dtos/authentication.dto.js +0 -15
  8. package/cjs/entities/user-company-permission.entity.js +0 -8
  9. package/cjs/entities/user-token.entity.js +0 -9
  10. package/cjs/interceptors/set-token.interceptor.js +15 -7
  11. package/cjs/services/auth-config.service.js +0 -4
  12. package/cjs/services/auth-email.service.js +8 -31
  13. package/cjs/services/authentication.service.js +99 -15
  14. package/cjs/services/user-permission.service.js +6 -8
  15. package/cjs/services/user.service.js +12 -9
  16. package/cjs/strategies/jwt.strategy.js +10 -3
  17. package/config/message-keys.d.ts +5 -153
  18. package/controllers/authentication.controller.d.ts +6 -7
  19. package/controllers/company-selection.controller.d.ts +3 -2
  20. package/controllers/email-verification.controller.d.ts +6 -2
  21. package/dtos/authentication.dto.d.ts +0 -2
  22. package/entities/user-company-permission.entity.d.ts +0 -1
  23. package/entities/user-token.entity.d.ts +0 -1
  24. package/fesm/config/message-keys.js +6 -53
  25. package/fesm/controllers/authentication.controller.js +115 -90
  26. package/fesm/controllers/company-selection.controller.js +25 -5
  27. package/fesm/controllers/email-verification.controller.js +13 -14
  28. package/fesm/docs/auth-swagger.config.js +146 -113
  29. package/fesm/dtos/authentication.dto.js +0 -15
  30. package/fesm/entities/user-company-permission.entity.js +0 -8
  31. package/fesm/entities/user-token.entity.js +0 -9
  32. package/fesm/interceptors/set-token.interceptor.js +15 -7
  33. package/fesm/services/auth-config.service.js +0 -4
  34. package/fesm/services/auth-email.service.js +8 -32
  35. package/fesm/services/authentication.service.js +100 -17
  36. package/fesm/services/user-permission.service.js +6 -8
  37. package/fesm/services/user.service.js +12 -10
  38. package/fesm/strategies/jwt.strategy.js +10 -3
  39. package/interfaces/auth-module-options.interface.d.ts +0 -1
  40. package/package.json +3 -3
  41. package/services/auth-config.service.d.ts +0 -1
  42. package/services/auth-email.service.d.ts +0 -4
  43. package/services/authentication.service.d.ts +1 -1
  44. package/services/user-permission.service.d.ts +1 -1
  45. package/services/user.service.d.ts +5 -5
@@ -1,31 +1,29 @@
1
1
  // ==================== AUTH MODULE MESSAGE KEYS ====================
2
2
  export const AUTH_MESSAGES = {
3
3
  LOGIN_SUCCESS: 'auth.login.success',
4
- LOGIN_FAILED: 'auth.login.failed',
4
+ LOGIN_REQUIRES_SELECTION: 'auth.login.requires.selection',
5
5
  LOGIN_INVALID_CREDENTIALS: 'auth.login.invalid.credentials',
6
6
  LOGIN_EMAIL_NOT_VERIFIED: 'auth.login.email.not.verified',
7
- LOGIN_REQUIRES_SELECTION: 'auth.login.requires.selection',
8
7
  LOGIN_ACCOUNT_DEACTIVATED: 'auth.login.account.deactivated',
9
8
  LOGOUT_SUCCESS: 'auth.logout.success',
10
9
  REGISTER_SUCCESS: 'auth.register.success',
11
10
  REGISTER_FAILED: 'auth.register.failed',
11
+ REFRESH_SUCCESS: 'auth.refresh.success',
12
+ ME_SUCCESS: 'auth.me.success',
13
+ SELECT_SUCCESS: 'auth.select.success',
14
+ SWITCH_COMPANY_SUCCESS: 'auth.switch.company.success',
12
15
  REGISTER_EMAIL_EXISTS: 'auth.register.email.exists',
13
16
  REGISTER_COMPANY_ALREADY_ASSIGNED: 'auth.register.company.already.assigned',
14
17
  PASSWORD_CHANGE_SUCCESS: 'auth.password.change.success',
15
- PASSWORD_CHANGE_FAILED: 'auth.password.change.failed',
16
18
  PASSWORD_CHANGE_INVALID_CURRENT: 'auth.password.change.invalid.current',
17
19
  PASSWORD_CHANGE_CURRENT_REQUIRED: 'auth.password.change.current.required',
18
20
  PASSWORD_RESET_EMAIL_SENT: 'auth.password.reset.email.sent',
19
21
  PASSWORD_RESET_SUCCESS: 'auth.password.reset.success',
20
- PASSWORD_RESET_FAILED: 'auth.password.reset.failed',
21
- TOKEN_REFRESH_SUCCESS: 'auth.token.refresh.success',
22
22
  TOKEN_REQUIRED: 'auth.token.required',
23
23
  TOKEN_INVALID: 'auth.token.invalid',
24
24
  TOKEN_EXPIRED: 'auth.token.expired',
25
25
  TOKEN_REVOKED: 'auth.token.revoked',
26
26
  TOKEN_TOO_LARGE: 'auth.token.too.large',
27
- COMPANY_SELECT_SUCCESS: 'auth.company.select.success',
28
- COMPANY_SWITCH_SUCCESS: 'auth.company.switch.success',
29
27
  COMPANY_LIST_SUCCESS: 'auth.company.list.success',
30
28
  COMPANY_NO_ACCESS: 'auth.company.no.access',
31
29
  COMPANY_NOT_FOUND: 'auth.company.not.found',
@@ -34,7 +32,6 @@ export const AUTH_MESSAGES = {
34
32
  BRANCH_LIST_SUCCESS: 'auth.branch.list.success',
35
33
  BRANCH_NO_ACCESS: 'auth.branch.no.access',
36
34
  BRANCH_NOT_FOUND: 'auth.branch.not.found',
37
- ME_SUCCESS: 'auth.me.success',
38
35
  EMAIL_NOT_CONFIGURED: 'auth.email.not.configured',
39
36
  EMAIL_SEND_FAILED: 'auth.email.send.failed',
40
37
  SESSION_INVALID: 'auth.session.invalid',
@@ -48,24 +45,13 @@ export const AUTH_MESSAGES = {
48
45
  export const EMAIL_VERIFICATION_MESSAGES = {
49
46
  VERIFICATION_SENT: 'email.verification.sent',
50
47
  VERIFICATION_SUCCESS: 'email.verification.success',
51
- VERIFICATION_FAILED: 'email.verification.failed',
52
48
  VERIFICATION_TOKEN_INVALID: 'email.verification.token.invalid',
53
49
  VERIFICATION_TOKEN_EXPIRED: 'email.verification.token.expired',
54
50
  VERIFICATION_NOT_ENABLED: 'email.verification.not.enabled',
55
- RESEND_SUCCESS: 'email.verification.resend.success',
56
- RESEND_THROTTLED: 'email.verification.resend.throttled'
51
+ RESEND_SUCCESS: 'email.verification.resend.success'
57
52
  };
58
53
  export const USER_MESSAGES = {
59
- CREATE_SUCCESS: 'user.create.success',
60
- CREATE_MANY_SUCCESS: 'user.create.many.success',
61
- GET_SUCCESS: 'user.get.success',
62
- GET_ALL_SUCCESS: 'user.get.all.success',
63
- UPDATE_SUCCESS: 'user.update.success',
64
- UPDATE_MANY_SUCCESS: 'user.update.many.success',
65
- DELETE_SUCCESS: 'user.delete.success',
66
- RESTORE_SUCCESS: 'user.restore.success',
67
54
  NOT_FOUND: 'user.not.found',
68
- PROFILE_SUCCESS: 'user.profile.success',
69
55
  PROFILE_UPDATE_SUCCESS: 'user.profile.update.success',
70
56
  PROFILE_EXTRAS_SUCCESS: 'user.profile.extras.success',
71
57
  PROFILE_SECTIONS_SUCCESS: 'user.profile.sections.success',
@@ -76,43 +62,10 @@ export const USER_MESSAGES = {
76
62
  PHONE_VERIFY_SUCCESS: 'user.phone.verify.success',
77
63
  STATUS_UPDATE_SUCCESS: 'user.status.update.success'
78
64
  };
79
- export const COMPANY_MESSAGES = {
80
- CREATE_SUCCESS: 'company.create.success',
81
- CREATE_MANY_SUCCESS: 'company.create.many.success',
82
- GET_SUCCESS: 'company.get.success',
83
- GET_ALL_SUCCESS: 'company.get.all.success',
84
- UPDATE_SUCCESS: 'company.update.success',
85
- UPDATE_MANY_SUCCESS: 'company.update.many.success',
86
- DELETE_SUCCESS: 'company.delete.success',
87
- RESTORE_SUCCESS: 'company.restore.success',
88
- NOT_FOUND: 'company.not.found'
89
- };
90
- export const BRANCH_MESSAGES = {
91
- CREATE_SUCCESS: 'branch.create.success',
92
- CREATE_MANY_SUCCESS: 'branch.create.many.success',
93
- GET_SUCCESS: 'branch.get.success',
94
- GET_ALL_SUCCESS: 'branch.get.all.success',
95
- UPDATE_SUCCESS: 'branch.update.success',
96
- UPDATE_MANY_SUCCESS: 'branch.update.many.success',
97
- DELETE_SUCCESS: 'branch.delete.success',
98
- RESTORE_SUCCESS: 'branch.restore.success',
99
- NOT_FOUND: 'branch.not.found'
100
- };
101
65
  export const USER_PERMISSION_MESSAGES = {
102
- COMPANY_ASSIGN_SUCCESS: 'user.permission.company.assign.success',
103
66
  COMPANY_LIST_SUCCESS: 'user.permission.company.list.success',
104
- BRANCH_ASSIGN_SUCCESS: 'user.permission.branch.assign.success',
105
67
  BRANCH_LIST_SUCCESS: 'user.permission.branch.list.success',
106
68
  BATCH_SUCCESS: 'user.permission.batch.success',
107
69
  ALREADY_ASSIGNED: 'user.permission.already.assigned',
108
70
  PERMISSION_NOT_FOUND: 'user.permission.not.found'
109
71
  };
110
- // Aggregated export for backward compatibility
111
- export const AUTH_MODULE_MESSAGES = {
112
- AUTH: AUTH_MESSAGES,
113
- EMAIL_VERIFICATION: EMAIL_VERIFICATION_MESSAGES,
114
- USER: USER_MESSAGES,
115
- COMPANY: COMPANY_MESSAGES,
116
- BRANCH: BRANCH_MESSAGES,
117
- USER_PERMISSION: USER_PERMISSION_MESSAGES
118
- };
@@ -25,40 +25,56 @@ function _ts_param(paramIndex, decorator) {
25
25
  decorator(target, key, paramIndex);
26
26
  };
27
27
  }
28
- import { AUTH_MESSAGES } from '../config';
28
+ import { buildFrontendUrl } from '@flusys/nestjs-shared';
29
29
  import { CurrentUser } from '@flusys/nestjs-shared/decorators';
30
30
  import { MessageResponseDto } from '@flusys/nestjs-shared/dtos';
31
31
  import { JwtAuthGuard } from '@flusys/nestjs-shared/guards';
32
32
  import { ILoggedUserInfo } from '@flusys/nestjs-shared/interfaces';
33
33
  import { Body, Controller, HttpCode, HttpStatus, Inject, Optional, Post, Req, UnauthorizedException, UseGuards, UseInterceptors } from '@nestjs/common';
34
- import { ApiBearerAuth, ApiBody, ApiExtraModels, ApiHeader, ApiOperation, ApiResponse, ApiTags, getSchemaPath } from '@nestjs/swagger';
34
+ import { ApiBearerAuth, ApiBody, ApiHeader, ApiOperation, ApiResponse, ApiTags } from '@nestjs/swagger';
35
35
  import { SkipThrottle, Throttle } from '@nestjs/throttler';
36
36
  import { Request } from 'express';
37
- import { DEFAULT_COOKIE_NAME } from '../config';
38
- import { ChangePasswordDto, CompanySelectionResponseDto, LoginDto, LoginResponseDto, LoginResponseRequiresEmailVerificationDto, MeResponseDto, RefreshTokenDto, RegistrationDto, RegistrationResponseDto } from '../dtos/authentication.dto';
37
+ import { AUTH_MESSAGES, DEFAULT_COOKIE_NAME, EMAIL_VERIFICATION_MESSAGES } from '../config';
38
+ import { ChangePasswordDto, LoginDto, RefreshTokenDto, RegistrationDto } from '../dtos/authentication.dto';
39
39
  import { ClearToken } from '../interceptors/clear-token.interceptor';
40
40
  import { SetToken } from '../interceptors/set-token.interceptor';
41
41
  import { AuthConfigService } from '../services/auth-config.service';
42
42
  import { AuthenticationService } from '../services/authentication.service';
43
43
  export class AuthenticationController {
44
- buildAuthUrl(req, path) {
45
- const frontendUrl = this.authConfig?.getFrontendUrl();
46
- return frontendUrl ? `${frontendUrl}${path}` : `${req.protocol}://${req.get('host')}${path}`;
47
- }
48
44
  async login(loginDto) {
49
45
  const result = await this.authService.login(loginDto.email, loginDto.password);
50
46
  if ('requiresEmailVerification' in result) {
51
- return result;
47
+ return {
48
+ success: true,
49
+ message: 'Email verification required',
50
+ messageKey: AUTH_MESSAGES.LOGIN_EMAIL_NOT_VERIFIED,
51
+ data: result
52
+ };
52
53
  }
53
54
  if ('requiresSelection' in result) {
54
- return result;
55
+ return {
56
+ success: true,
57
+ message: 'Company selection required',
58
+ messageKey: AUTH_MESSAGES.LOGIN_REQUIRES_SELECTION,
59
+ data: result
60
+ };
55
61
  }
56
- return result;
62
+ return {
63
+ success: true,
64
+ message: 'Login successful',
65
+ messageKey: AUTH_MESSAGES.LOGIN_SUCCESS,
66
+ data: result
67
+ };
57
68
  }
58
69
  /** Register new user. If company feature enabled, can join/create company. */ async register(req, registrationDto) {
59
- const verifyUrlBase = this.buildAuthUrl(req, '/auth/verify-email');
70
+ const verifyUrlBase = buildFrontendUrl(req, '/auth/verify-email');
60
71
  const result = await this.authService.register(registrationDto, verifyUrlBase);
61
- return result;
72
+ return {
73
+ success: true,
74
+ message: result.requiresEmailVerification ? 'Verification email sent' : 'Registration successful',
75
+ messageKey: result.requiresEmailVerification ? EMAIL_VERIFICATION_MESSAGES.VERIFICATION_SENT : AUTH_MESSAGES.REGISTER_SUCCESS,
76
+ data: result
77
+ };
62
78
  }
63
79
  /**
64
80
  * Refresh access token.
@@ -74,10 +90,22 @@ export class AuthenticationController {
74
90
  messageKey: AUTH_MESSAGES.TOKEN_REQUIRED
75
91
  });
76
92
  }
77
- return this.authService.refreshToken(refreshToken);
93
+ const data = await this.authService.refreshToken(refreshToken);
94
+ return {
95
+ success: true,
96
+ message: 'Token refreshed successfully',
97
+ messageKey: AUTH_MESSAGES.REFRESH_SUCCESS,
98
+ data
99
+ };
78
100
  }
79
101
  /** Get current user info. Returns user, company, and branch data (no tokens). */ async getCurrentUser(user) {
80
- return this.authService.getUserInfo(user.id, user.companyId, user.branchId);
102
+ const data = await this.authService.getUserInfo(user.id, user.companyId, user.branchId);
103
+ return {
104
+ success: true,
105
+ message: 'User info retrieved successfully',
106
+ messageKey: AUTH_MESSAGES.ME_SUCCESS,
107
+ data
108
+ };
81
109
  }
82
110
  /** Logout - Clears refresh token cookie for browsers */ async logout(userId) {
83
111
  await this.authService.logout(userId);
@@ -118,97 +146,93 @@ _ts_decorate([
118
146
  ApiBody({
119
147
  type: LoginDto
120
148
  }),
121
- ApiExtraModels(LoginResponseDto, CompanySelectionResponseDto, LoginResponseRequiresEmailVerificationDto),
122
149
  ApiResponse({
123
150
  status: 200,
124
151
  description: 'Login successful, requires company selection, or requires email verification',
125
152
  content: {
126
153
  'application/json': {
127
- schema: {
128
- oneOf: [
129
- {
130
- $ref: getSchemaPath(LoginResponseDto)
131
- },
132
- {
133
- $ref: getSchemaPath(CompanySelectionResponseDto)
134
- },
135
- {
136
- $ref: getSchemaPath(LoginResponseRequiresEmailVerificationDto)
137
- }
138
- ]
139
- },
140
154
  examples: {
141
155
  loginSuccess: {
142
156
  summary: 'Login Success',
143
- description: 'Successful login with tokens (company/branch included when company feature enabled)',
144
157
  value: {
145
- accessToken: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...',
146
- refreshToken: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...',
147
- user: {
148
- id: '550e8400-e29b-41d4-a716-446655440000',
149
- email: 'john@example.com',
150
- name: 'John Doe'
158
+ success: true,
159
+ message: 'Login successful',
160
+ messageKey: 'auth.login.success',
161
+ data: {
162
+ accessToken: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...',
163
+ user: {
164
+ id: '550e8400-e29b-41d4-a716-446655440000',
165
+ email: 'john@example.com',
166
+ name: 'John Doe'
167
+ }
151
168
  }
152
169
  }
153
170
  },
154
171
  loginSuccessWithCompany: {
155
- summary: 'Login Success (Company Feature)',
156
- description: 'Login with company/branch - only when company feature is enabled',
172
+ summary: 'Login Success (with company/branch)',
157
173
  value: {
158
- accessToken: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...',
159
- refreshToken: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...',
160
- user: {
161
- id: '550e8400-e29b-41d4-a716-446655440000',
162
- email: 'john@example.com',
163
- name: 'John Doe'
164
- },
165
- company: {
166
- id: '550e8400-e29b-41d4-a716-446655440001',
167
- name: 'Acme Corporation',
168
- slug: 'acme-corp'
169
- },
170
- branch: {
171
- id: '550e8400-e29b-41d4-a716-446655440002',
172
- name: 'Main Branch',
173
- slug: 'main-branch'
174
+ success: true,
175
+ message: 'Login successful',
176
+ messageKey: 'auth.login.success',
177
+ data: {
178
+ accessToken: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...',
179
+ user: {
180
+ id: '550e8400-e29b-41d4-a716-446655440000',
181
+ email: 'john@example.com',
182
+ name: 'John Doe'
183
+ },
184
+ company: {
185
+ id: 'company-id',
186
+ name: 'Acme Corp'
187
+ },
188
+ branch: {
189
+ id: 'branch-id',
190
+ name: 'Main Branch'
191
+ }
174
192
  }
175
193
  }
176
194
  },
177
195
  companySelection: {
178
- summary: 'Company Selection Required (Company Feature)',
179
- description: 'User has multiple companies/branches - only when company feature is enabled',
196
+ summary: 'Company Selection Required',
180
197
  value: {
181
- requiresSelection: true,
182
- sessionId: 'sess_abc123def456',
183
- expiresAt: '2024-12-18T15:30:00.000Z',
184
- user: {
185
- id: '550e8400-e29b-41d4-a716-446655440000',
186
- email: 'john@example.com',
187
- name: 'John Doe'
188
- },
189
- companies: [
190
- {
191
- id: '550e8400-e29b-41d4-a716-446655440001',
192
- name: 'Company A',
193
- slug: 'company-a',
194
- branches: [
195
- {
196
- id: '550e8400-e29b-41d4-a716-446655440010',
197
- name: 'Branch 1',
198
- slug: 'branch-1'
199
- }
200
- ]
201
- }
202
- ]
198
+ success: true,
199
+ message: 'Company selection required',
200
+ messageKey: 'auth.login.requires.selection',
201
+ data: {
202
+ requiresSelection: true,
203
+ sessionId: 'sess_abc123def456',
204
+ expiresAt: '2024-12-18T15:30:00.000Z',
205
+ user: {
206
+ id: '550e8400-e29b-41d4-a716-446655440000',
207
+ email: 'john@example.com'
208
+ },
209
+ companies: [
210
+ {
211
+ id: 'company-id',
212
+ name: 'Acme Corp',
213
+ slug: 'acme-corp',
214
+ branches: [
215
+ {
216
+ id: 'branch-id',
217
+ name: 'Main Branch',
218
+ slug: 'main-branch'
219
+ }
220
+ ]
221
+ }
222
+ ]
223
+ }
203
224
  }
204
225
  },
205
226
  emailVerification: {
206
227
  summary: 'Email Verification Required',
207
- description: 'User must verify email before logging in',
208
228
  value: {
209
- requiresEmailVerification: true,
210
- email: 'john@example.com',
211
- message: 'Please verify your email address before logging in.'
229
+ success: true,
230
+ message: 'Email verification required',
231
+ messageKey: 'auth.login.email.not.verified',
232
+ data: {
233
+ requiresEmailVerification: true,
234
+ email: 'john@example.com'
235
+ }
212
236
  }
213
237
  }
214
238
  }
@@ -240,7 +264,7 @@ _ts_decorate([
240
264
  }),
241
265
  ApiResponse({
242
266
  status: 201,
243
- type: RegistrationResponseDto
267
+ description: 'Registration successful or email verification required'
244
268
  }),
245
269
  _ts_param(0, Req()),
246
270
  _ts_param(1, Body()),
@@ -284,13 +308,14 @@ Set header \`x-client-type: mobile\` or \`x-client-type: api\` to identify as no
284
308
  }),
285
309
  ApiResponse({
286
310
  status: 200,
287
- description: 'New access token',
311
+ description: 'Token refreshed successfully',
288
312
  schema: {
289
- type: 'object',
290
- properties: {
291
- accessToken: {
292
- type: 'string',
293
- example: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...'
313
+ example: {
314
+ success: true,
315
+ message: 'Token refreshed successfully',
316
+ messageKey: 'auth.refresh.success',
317
+ data: {
318
+ accessToken: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...'
294
319
  }
295
320
  }
296
321
  }
@@ -318,7 +343,7 @@ _ts_decorate([
318
343
  }),
319
344
  ApiResponse({
320
345
  status: 200,
321
- type: MeResponseDto
346
+ description: 'Current user info retrieved successfully'
322
347
  }),
323
348
  _ts_param(0, CurrentUser()),
324
349
  _ts_metadata("design:type", Function),
@@ -29,16 +29,28 @@ import { AUTH_MESSAGES } from '../config';
29
29
  import { CurrentUser } from '@flusys/nestjs-shared/decorators';
30
30
  import { Body, Controller, HttpCode, HttpStatus, Inject, Post, UseGuards, UseInterceptors } from '@nestjs/common';
31
31
  import { ApiBearerAuth, ApiBody, ApiOperation, ApiResponse, ApiTags } from '@nestjs/swagger';
32
- import { LoginResponseDto, SelectDto, SwitchCompanyDto } from '../dtos/authentication.dto';
32
+ import { SelectDto, SwitchCompanyDto } from '../dtos/authentication.dto';
33
33
  import { JwtAuthGuard } from '@flusys/nestjs-shared/guards';
34
34
  import { SetToken } from '../interceptors/set-token.interceptor';
35
35
  import { AuthenticationService } from '../services/authentication.service';
36
36
  export class CompanySelectionController {
37
37
  async select(dto) {
38
- return this.authService.select(dto.sessionId, dto.companyId, dto.branchId);
38
+ const data = await this.authService.select(dto.sessionId, dto.companyId, dto.branchId);
39
+ return {
40
+ success: true,
41
+ message: 'Company selected successfully',
42
+ messageKey: AUTH_MESSAGES.SELECT_SUCCESS,
43
+ data
44
+ };
39
45
  }
40
46
  async switchCompany(userId, dto) {
41
- return this.authService.switchCompany(userId, dto.companyId, dto.branchId);
47
+ const data = await this.authService.switchCompany(userId, dto.companyId, dto.branchId);
48
+ return {
49
+ success: true,
50
+ message: 'Company switched successfully',
51
+ messageKey: AUTH_MESSAGES.SWITCH_COMPANY_SUCCESS,
52
+ data
53
+ };
42
54
  }
43
55
  async getUserCompanies(userId) {
44
56
  const companies = await this.authService.getUserCompanies(userId);
@@ -76,7 +88,7 @@ _ts_decorate([
76
88
  }),
77
89
  ApiResponse({
78
90
  status: 200,
79
- type: LoginResponseDto
91
+ description: 'Company selected, tokens returned'
80
92
  }),
81
93
  _ts_param(0, Body()),
82
94
  _ts_metadata("design:type", Function),
@@ -100,7 +112,7 @@ _ts_decorate([
100
112
  }),
101
113
  ApiResponse({
102
114
  status: 200,
103
- type: LoginResponseDto
115
+ description: 'Company switched, new tokens returned'
104
116
  }),
105
117
  _ts_param(0, CurrentUser('id')),
106
118
  _ts_param(1, Body()),
@@ -120,6 +132,10 @@ _ts_decorate([
120
132
  summary: "Get user's available companies",
121
133
  description: 'Get list of companies the current user has access to'
122
134
  }),
135
+ ApiResponse({
136
+ status: 200,
137
+ description: 'User companies retrieved successfully'
138
+ }),
123
139
  _ts_param(0, CurrentUser('id')),
124
140
  _ts_metadata("design:type", Function),
125
141
  _ts_metadata("design:paramtypes", [
@@ -148,6 +164,10 @@ _ts_decorate([
148
164
  ]
149
165
  }
150
166
  }),
167
+ ApiResponse({
168
+ status: 200,
169
+ description: 'Company branches retrieved successfully'
170
+ }),
151
171
  _ts_param(0, CurrentUser('id')),
152
172
  _ts_param(1, Body('companyId')),
153
173
  _ts_metadata("design:type", Function),
@@ -25,13 +25,14 @@ function _ts_param(paramIndex, decorator) {
25
25
  decorator(target, key, paramIndex);
26
26
  };
27
27
  }
28
- import { EMAIL_VERIFICATION_MESSAGES } from '../config';
28
+ import { buildFrontendUrl } from '@flusys/nestjs-shared';
29
29
  import { MessageResponseDto } from '@flusys/nestjs-shared/dtos';
30
30
  import { BadRequestException, Body, Controller, HttpCode, HttpStatus, Inject, Post, Req, UseInterceptors } from '@nestjs/common';
31
31
  import { ApiBody, ApiOperation, ApiResponse, ApiTags } from '@nestjs/swagger';
32
32
  import { Throttle } from '@nestjs/throttler';
33
33
  import { Request } from 'express';
34
- import { ForgotPasswordDto, RegistrationResponseDto, ResendVerificationDto, ResetPasswordDto, VerifyEmailDto } from '../dtos/authentication.dto';
34
+ import { AUTH_MESSAGES, EMAIL_VERIFICATION_MESSAGES } from '../config';
35
+ import { ForgotPasswordDto, ResendVerificationDto, ResetPasswordDto, VerifyEmailDto } from '../dtos/authentication.dto';
35
36
  import { SetToken } from '../interceptors/set-token.interceptor';
36
37
  import { AuthConfigService } from '../services/auth-config.service';
37
38
  import { AuthDataSourceProvider } from '../services/auth-datasource.provider';
@@ -46,13 +47,9 @@ export class EmailVerificationController {
46
47
  });
47
48
  }
48
49
  }
49
- buildAuthUrl(req, path) {
50
- const frontendUrl = this.authConfig.getFrontendUrl();
51
- return frontendUrl ? `${frontendUrl}${path}` : `${req.protocol}://${req.get('host')}${path}`;
52
- }
53
50
  async forgotPassword(req, dto) {
54
51
  this.ensureEmailVerificationEnabled();
55
- return this.authEmailService.forgotPassword(dto.email, this.buildAuthUrl(req, '/auth/reset-password'));
52
+ return this.authEmailService.forgotPassword(dto.email, buildFrontendUrl(req, '/auth/reset-password'));
56
53
  }
57
54
  async resetPassword(dto) {
58
55
  this.ensureEmailVerificationEnabled();
@@ -60,13 +57,19 @@ export class EmailVerificationController {
60
57
  }
61
58
  async resendVerification(req, dto) {
62
59
  this.ensureEmailVerificationEnabled();
63
- return this.authEmailService.resendVerificationEmail(dto.email, this.buildAuthUrl(req, '/auth/verify-email'));
60
+ return this.authEmailService.resendVerificationEmail(dto.email, buildFrontendUrl(req, '/auth/verify-email'));
64
61
  }
65
62
  async verifyEmail(dto) {
66
63
  this.ensureEmailVerificationEnabled();
67
64
  const result = await this.authEmailService.verifyEmail(dto.token);
68
65
  if (result.type === 'pending') {
69
- return this.authService.createUserFromPendingRegistration(result.pending);
66
+ const data = await this.authService.createUserFromPendingRegistration(result.pending);
67
+ return {
68
+ success: true,
69
+ message: 'Registration completed successfully',
70
+ messageKey: AUTH_MESSAGES.REGISTER_SUCCESS,
71
+ data
72
+ };
70
73
  }
71
74
  return {
72
75
  success: true,
@@ -185,11 +188,7 @@ _ts_decorate([
185
188
  }),
186
189
  ApiResponse({
187
190
  status: 200,
188
- type: MessageResponseDto
189
- }),
190
- ApiResponse({
191
- status: 200,
192
- type: RegistrationResponseDto
191
+ description: 'Email verified or registration completed'
193
192
  }),
194
193
  _ts_param(0, Body()),
195
194
  _ts_metadata("design:type", Function),