@flusys/nestjs-auth 7.0.2 → 8.0.0-beta.1

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 (237) hide show
  1. package/README.md +68 -1
  2. package/config/auth.constants.d.ts +2 -0
  3. package/config/event-actions.d.ts +2 -0
  4. package/config/index.d.ts +3 -3
  5. package/config/message-keys.d.ts +23 -0
  6. package/controllers/authentication.controller.d.ts +5 -5
  7. package/controllers/branch.controller.d.ts +2 -2
  8. package/controllers/company-selection.controller.d.ts +4 -4
  9. package/controllers/company.controller.d.ts +2 -2
  10. package/controllers/email-verification.controller.d.ts +6 -6
  11. package/controllers/index.d.ts +9 -7
  12. package/controllers/social-auth-config.controller.d.ts +22 -0
  13. package/controllers/social-auth.controller.d.ts +11 -0
  14. package/controllers/user-permission.controller.d.ts +5 -4
  15. package/controllers/user.controller.d.ts +7 -7
  16. package/docs/auth-swagger.config.d.ts +2 -2
  17. package/docs/index.d.ts +1 -1
  18. package/dtos/index.d.ts +6 -5
  19. package/dtos/social-auth.dto.d.ts +42 -0
  20. package/entities/company-branch.entity.d.ts +1 -1
  21. package/entities/company.entity.d.ts +1 -1
  22. package/entities/index.d.ts +15 -13
  23. package/entities/pending-registration.entity.d.ts +1 -1
  24. package/entities/social-auth-config.entity.d.ts +9 -0
  25. package/entities/user-company-permission.entity.d.ts +4 -4
  26. package/enums/index.d.ts +2 -1
  27. package/enums/social-provider-type.enum.d.ts +6 -0
  28. package/fesm/118.js +1230 -0
  29. package/fesm/120.js +2197 -0
  30. package/fesm/24.js +4389 -0
  31. package/fesm/370.js +1163 -0
  32. package/fesm/446.js +877 -0
  33. package/fesm/chunks/117.js +69 -0
  34. package/fesm/config/index.js +244 -3
  35. package/fesm/controllers/index.js +27 -7
  36. package/fesm/docs/index.js +479 -1
  37. package/fesm/dtos/index.js +123 -5
  38. package/fesm/entities/index.js +68 -19
  39. package/fesm/enums/index.js +53 -1
  40. package/fesm/helpers/index.js +115 -2
  41. package/fesm/index.js +1437 -12
  42. package/fesm/interceptors/index.js +508 -2
  43. package/fesm/interfaces/index.js +75 -7
  44. package/fesm/modules/index.js +546 -1
  45. package/fesm/runtime.js +134 -0
  46. package/fesm/services/index.js +67 -9
  47. package/helpers/auth-response.mapper.d.ts +3 -3
  48. package/helpers/index.d.ts +2 -2
  49. package/helpers/token.helper.d.ts +2 -2
  50. package/index.d.ts +13 -12
  51. package/interceptors/clear-token.interceptor.d.ts +2 -2
  52. package/interceptors/index.d.ts +2 -2
  53. package/interceptors/set-token.interceptor.d.ts +2 -2
  54. package/interfaces/auth-module-options.interface.d.ts +3 -3
  55. package/interfaces/authentication.interface.d.ts +3 -3
  56. package/interfaces/company-branch.interface.d.ts +2 -2
  57. package/interfaces/company.interface.d.ts +1 -1
  58. package/interfaces/index.d.ts +8 -7
  59. package/interfaces/social-auth.interface.d.ts +43 -0
  60. package/interfaces/user-enricher.interface.d.ts +3 -3
  61. package/modules/auth.module.d.ts +4 -4
  62. package/modules/index.d.ts +1 -1
  63. package/package.json +32 -39
  64. package/providers/facebook.social-provider.d.ts +10 -0
  65. package/providers/google.social-provider.d.ts +10 -0
  66. package/providers/index.d.ts +1 -0
  67. package/providers/linkedin.social-provider.d.ts +10 -0
  68. package/providers/microsoft.social-provider.d.ts +10 -0
  69. package/providers/oauth-http.util.d.ts +10 -0
  70. package/providers/social-provider.registry.d.ts +3 -0
  71. package/services/auth-config.service.d.ts +4 -3
  72. package/services/auth-datasource.provider.d.ts +4 -3
  73. package/services/auth-email.service.d.ts +3 -3
  74. package/services/authentication.service.d.ts +15 -11
  75. package/services/branch.service.d.ts +7 -7
  76. package/services/company.service.d.ts +6 -6
  77. package/services/index.d.ts +11 -9
  78. package/services/social-auth-config.service.d.ts +21 -0
  79. package/services/social-auth.service.d.ts +24 -0
  80. package/services/user-permission.service.d.ts +8 -4
  81. package/services/user.service.d.ts +7 -7
  82. package/strategies/jwt.strategy.d.ts +4 -4
  83. package/validators/password.validator.d.ts +1 -1
  84. package/cjs/config/auth.constants.js +0 -41
  85. package/cjs/config/event-actions.js +0 -45
  86. package/cjs/config/index.js +0 -20
  87. package/cjs/config/message-keys.js +0 -108
  88. package/cjs/controllers/authentication.controller.js +0 -427
  89. package/cjs/controllers/authentication.controller.spec.js +0 -219
  90. package/cjs/controllers/branch.controller.js +0 -102
  91. package/cjs/controllers/branch.controller.spec.js +0 -134
  92. package/cjs/controllers/company-selection.controller.js +0 -198
  93. package/cjs/controllers/company-selection.controller.spec.js +0 -84
  94. package/cjs/controllers/company.controller.js +0 -102
  95. package/cjs/controllers/company.controller.spec.js +0 -131
  96. package/cjs/controllers/email-verification.controller.js +0 -224
  97. package/cjs/controllers/email-verification.controller.spec.js +0 -142
  98. package/cjs/controllers/index.js +0 -24
  99. package/cjs/controllers/user-permission.controller.js +0 -223
  100. package/cjs/controllers/user-permission.controller.spec.js +0 -138
  101. package/cjs/controllers/user.controller.js +0 -438
  102. package/cjs/controllers/user.controller.spec.js +0 -204
  103. package/cjs/docs/auth-swagger.config.js +0 -453
  104. package/cjs/docs/auth-swagger.config.spec.js +0 -130
  105. package/cjs/docs/index.js +0 -18
  106. package/cjs/dtos/authentication.dto.js +0 -755
  107. package/cjs/dtos/company-branch.dto.js +0 -294
  108. package/cjs/dtos/company.dto.js +0 -298
  109. package/cjs/dtos/index.js +0 -22
  110. package/cjs/dtos/user-permission.dto.js +0 -358
  111. package/cjs/dtos/user.dto.js +0 -413
  112. package/cjs/entities/app-user.entity.js +0 -25
  113. package/cjs/entities/company-branch.entity.js +0 -163
  114. package/cjs/entities/company.entity.js +0 -146
  115. package/cjs/entities/index.js +0 -65
  116. package/cjs/entities/index.spec.js +0 -73
  117. package/cjs/entities/pending-registration.entity.js +0 -135
  118. package/cjs/entities/user-company-permission.entity.js +0 -153
  119. package/cjs/entities/user-token.entity.js +0 -120
  120. package/cjs/enums/index.js +0 -18
  121. package/cjs/enums/user-org-permission-type.enum.js +0 -15
  122. package/cjs/helpers/auth-response.mapper.js +0 -46
  123. package/cjs/helpers/auth-response.mapper.spec.js +0 -139
  124. package/cjs/helpers/index.js +0 -19
  125. package/cjs/helpers/token.helper.js +0 -58
  126. package/cjs/helpers/token.helper.spec.js +0 -86
  127. package/cjs/index.js +0 -29
  128. package/cjs/interceptors/clear-token.interceptor.js +0 -73
  129. package/cjs/interceptors/clear-token.interceptor.spec.js +0 -107
  130. package/cjs/interceptors/index.js +0 -19
  131. package/cjs/interceptors/set-token.interceptor.js +0 -107
  132. package/cjs/interceptors/set-token.interceptor.spec.js +0 -165
  133. package/cjs/interfaces/auth-email-provider.interface.js +0 -45
  134. package/cjs/interfaces/auth-module-options.interface.js +0 -4
  135. package/cjs/interfaces/authentication.interface.js +0 -4
  136. package/cjs/interfaces/company-branch.interface.js +0 -4
  137. package/cjs/interfaces/company.interface.js +0 -4
  138. package/cjs/interfaces/index.js +0 -24
  139. package/cjs/interfaces/user-enricher.interface.js +0 -4
  140. package/cjs/interfaces/user.interface.js +0 -4
  141. package/cjs/modules/auth.module.js +0 -202
  142. package/cjs/modules/auth.module.spec.js +0 -243
  143. package/cjs/modules/index.js +0 -18
  144. package/cjs/services/auth-config.service.js +0 -110
  145. package/cjs/services/auth-config.service.spec.js +0 -97
  146. package/cjs/services/auth-datasource.provider.js +0 -134
  147. package/cjs/services/auth-datasource.provider.spec.js +0 -161
  148. package/cjs/services/auth-email.service.js +0 -539
  149. package/cjs/services/auth-email.service.spec.js +0 -456
  150. package/cjs/services/authentication.service.js +0 -1173
  151. package/cjs/services/authentication.service.spec.js +0 -962
  152. package/cjs/services/branch.service.js +0 -153
  153. package/cjs/services/branch.service.spec.js +0 -169
  154. package/cjs/services/company-selection-session.service.js +0 -121
  155. package/cjs/services/company-selection-session.service.spec.js +0 -90
  156. package/cjs/services/company.service.js +0 -140
  157. package/cjs/services/company.service.spec.js +0 -127
  158. package/cjs/services/index.js +0 -26
  159. package/cjs/services/user-permission.service.js +0 -236
  160. package/cjs/services/user-permission.service.spec.js +0 -254
  161. package/cjs/services/user.service.js +0 -671
  162. package/cjs/services/user.service.spec.js +0 -718
  163. package/cjs/strategies/jwt.strategy.js +0 -140
  164. package/cjs/strategies/jwt.strategy.spec.js +0 -166
  165. package/cjs/validators/password.validator.js +0 -45
  166. package/cjs/validators/password.validator.spec.js +0 -161
  167. package/fesm/config/auth.constants.js +0 -11
  168. package/fesm/config/event-actions.js +0 -24
  169. package/fesm/config/message-keys.js +0 -78
  170. package/fesm/controllers/authentication.controller.js +0 -417
  171. package/fesm/controllers/authentication.controller.spec.js +0 -215
  172. package/fesm/controllers/branch.controller.js +0 -92
  173. package/fesm/controllers/branch.controller.spec.js +0 -130
  174. package/fesm/controllers/company-selection.controller.js +0 -188
  175. package/fesm/controllers/company-selection.controller.spec.js +0 -80
  176. package/fesm/controllers/company.controller.js +0 -92
  177. package/fesm/controllers/company.controller.spec.js +0 -127
  178. package/fesm/controllers/email-verification.controller.js +0 -214
  179. package/fesm/controllers/email-verification.controller.spec.js +0 -138
  180. package/fesm/controllers/user-permission.controller.js +0 -213
  181. package/fesm/controllers/user-permission.controller.spec.js +0 -134
  182. package/fesm/controllers/user.controller.js +0 -428
  183. package/fesm/controllers/user.controller.spec.js +0 -200
  184. package/fesm/docs/auth-swagger.config.js +0 -446
  185. package/fesm/docs/auth-swagger.config.spec.js +0 -126
  186. package/fesm/dtos/authentication.dto.js +0 -683
  187. package/fesm/dtos/company-branch.dto.js +0 -279
  188. package/fesm/dtos/company.dto.js +0 -283
  189. package/fesm/dtos/user-permission.dto.js +0 -339
  190. package/fesm/dtos/user.dto.js +0 -391
  191. package/fesm/entities/app-user.entity.js +0 -15
  192. package/fesm/entities/company-branch.entity.js +0 -153
  193. package/fesm/entities/company.entity.js +0 -136
  194. package/fesm/entities/index.spec.js +0 -69
  195. package/fesm/entities/pending-registration.entity.js +0 -125
  196. package/fesm/entities/user-company-permission.entity.js +0 -136
  197. package/fesm/entities/user-token.entity.js +0 -104
  198. package/fesm/enums/user-org-permission-type.enum.js +0 -5
  199. package/fesm/helpers/auth-response.mapper.js +0 -25
  200. package/fesm/helpers/auth-response.mapper.spec.js +0 -135
  201. package/fesm/helpers/token.helper.js +0 -40
  202. package/fesm/helpers/token.helper.spec.js +0 -82
  203. package/fesm/interceptors/clear-token.interceptor.js +0 -63
  204. package/fesm/interceptors/clear-token.interceptor.spec.js +0 -103
  205. package/fesm/interceptors/set-token.interceptor.js +0 -98
  206. package/fesm/interceptors/set-token.interceptor.spec.js +0 -161
  207. package/fesm/interfaces/auth-email-provider.interface.js +0 -38
  208. package/fesm/interfaces/auth-module-options.interface.js +0 -3
  209. package/fesm/interfaces/authentication.interface.js +0 -1
  210. package/fesm/interfaces/company-branch.interface.js +0 -1
  211. package/fesm/interfaces/company.interface.js +0 -1
  212. package/fesm/interfaces/user-enricher.interface.js +0 -4
  213. package/fesm/interfaces/user.interface.js +0 -1
  214. package/fesm/modules/auth.module.js +0 -192
  215. package/fesm/modules/auth.module.spec.js +0 -239
  216. package/fesm/services/auth-config.service.js +0 -100
  217. package/fesm/services/auth-config.service.spec.js +0 -93
  218. package/fesm/services/auth-datasource.provider.js +0 -83
  219. package/fesm/services/auth-datasource.provider.spec.js +0 -157
  220. package/fesm/services/auth-email.service.js +0 -488
  221. package/fesm/services/auth-email.service.spec.js +0 -411
  222. package/fesm/services/authentication.service.js +0 -1122
  223. package/fesm/services/authentication.service.spec.js +0 -917
  224. package/fesm/services/branch.service.js +0 -143
  225. package/fesm/services/branch.service.spec.js +0 -165
  226. package/fesm/services/company-selection-session.service.js +0 -111
  227. package/fesm/services/company-selection-session.service.spec.js +0 -86
  228. package/fesm/services/company.service.js +0 -130
  229. package/fesm/services/company.service.spec.js +0 -123
  230. package/fesm/services/user-permission.service.js +0 -226
  231. package/fesm/services/user-permission.service.spec.js +0 -250
  232. package/fesm/services/user.service.js +0 -620
  233. package/fesm/services/user.service.spec.js +0 -673
  234. package/fesm/strategies/jwt.strategy.js +0 -130
  235. package/fesm/strategies/jwt.strategy.spec.js +0 -162
  236. package/fesm/validators/password.validator.js +0 -48
  237. package/fesm/validators/password.validator.spec.js +0 -157
@@ -1,417 +0,0 @@
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 { buildFrontendUrl } from '@flusys/nestjs-shared';
29
- import { CurrentUser } from '@flusys/nestjs-shared/decorators';
30
- import { MessageResponseDto } from '@flusys/nestjs-shared/dtos';
31
- import { JwtAuthGuard } from '@flusys/nestjs-shared/guards';
32
- import { ILoggedUserInfo } from '@flusys/nestjs-shared/interfaces';
33
- import { Body, Controller, HttpCode, HttpStatus, Inject, Optional, Post, Req, UnauthorizedException, UseGuards, UseInterceptors } from '@nestjs/common';
34
- import { ApiBearerAuth, ApiBody, ApiHeader, ApiOperation, ApiResponse, ApiTags } from '@nestjs/swagger';
35
- import { SkipThrottle, Throttle } from '@nestjs/throttler';
36
- import { Request } from 'express';
37
- import { AUTH_MESSAGES, DEFAULT_COOKIE_NAME, EMAIL_VERIFICATION_MESSAGES } from '../config';
38
- import { ChangePasswordDto, LoginDto, RefreshTokenDto, RegistrationDto } from '../dtos/authentication.dto';
39
- import { ClearToken } from '../interceptors/clear-token.interceptor';
40
- import { SetToken } from '../interceptors/set-token.interceptor';
41
- import { AuthConfigService } from '../services/auth-config.service';
42
- import { AuthenticationService } from '../services/authentication.service';
43
- export class AuthenticationController {
44
- async login(loginDto) {
45
- const result = await this.authService.login(loginDto.email, loginDto.password);
46
- if ('requiresEmailVerification' in result) {
47
- return {
48
- success: true,
49
- message: 'Email verification required',
50
- messageKey: AUTH_MESSAGES.LOGIN_EMAIL_NOT_VERIFIED,
51
- data: result
52
- };
53
- }
54
- if ('requiresSelection' in result) {
55
- return {
56
- success: true,
57
- message: 'Company selection required',
58
- messageKey: AUTH_MESSAGES.LOGIN_REQUIRES_SELECTION,
59
- data: result
60
- };
61
- }
62
- return {
63
- success: true,
64
- message: 'Login successful',
65
- messageKey: AUTH_MESSAGES.LOGIN_SUCCESS,
66
- data: result
67
- };
68
- }
69
- /** Register new user. If company feature enabled, can join/create company. */ async register(req, registrationDto) {
70
- const verifyUrlBase = buildFrontendUrl(req, '/auth/verify-email');
71
- const result = await this.authService.register(registrationDto, verifyUrlBase);
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
- };
78
- }
79
- /**
80
- * Refresh access token.
81
- * - **Browser**: Prefers HTTP-only cookie, falls back to body if cookie missing.
82
- * - **API/Mobile**: Must send `refreshToken` in request body. Set header `x-client-type: mobile` or `x-client-type: api`.
83
- */ async refreshToken(req, refreshTokenDto) {
84
- const cookieName = this.authConfig?.getRefreshTokenCookieName() ?? DEFAULT_COOKIE_NAME;
85
- // Always check cookie first, then body - handles Browser, SSR, and Mobile/API
86
- const refreshToken = req.cookies?.[cookieName] || refreshTokenDto.refreshToken;
87
- if (!refreshToken) {
88
- throw new UnauthorizedException({
89
- message: 'Refresh token is required',
90
- messageKey: AUTH_MESSAGES.TOKEN_REQUIRED
91
- });
92
- }
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
- };
100
- }
101
- /** Get current user info. Returns user, company, and branch data (no tokens). */ async getCurrentUser(user) {
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
- };
109
- }
110
- /** Logout - Clears refresh token cookie for browsers */ async logout(userId) {
111
- await this.authService.logout(userId);
112
- return {
113
- success: true,
114
- message: 'Logged out successfully',
115
- messageKey: AUTH_MESSAGES.LOGOUT_SUCCESS
116
- };
117
- }
118
- async changePassword(userId, dto) {
119
- await this.authService.changePassword(userId, dto.currentPassword, dto.newPassword);
120
- return {
121
- success: true,
122
- message: 'Password changed successfully',
123
- messageKey: AUTH_MESSAGES.PASSWORD_CHANGE_SUCCESS
124
- };
125
- }
126
- constructor(authService, authConfig){
127
- _define_property(this, "authService", void 0);
128
- _define_property(this, "authConfig", void 0);
129
- this.authService = authService;
130
- this.authConfig = authConfig;
131
- }
132
- }
133
- _ts_decorate([
134
- Post('login'),
135
- HttpCode(HttpStatus.OK),
136
- Throttle({
137
- default: {
138
- limit: 5,
139
- ttl: 60000
140
- }
141
- }),
142
- UseInterceptors(SetToken),
143
- ApiOperation({
144
- summary: 'User login'
145
- }),
146
- ApiBody({
147
- type: LoginDto
148
- }),
149
- ApiResponse({
150
- status: 200,
151
- description: 'Login successful, requires company selection, or requires email verification',
152
- content: {
153
- 'application/json': {
154
- examples: {
155
- loginSuccess: {
156
- summary: 'Login Success',
157
- value: {
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
- }
168
- }
169
- }
170
- },
171
- loginSuccessWithCompany: {
172
- summary: 'Login Success (with company/branch)',
173
- value: {
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
- }
192
- }
193
- }
194
- },
195
- companySelection: {
196
- summary: 'Company Selection Required',
197
- value: {
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
- }
224
- }
225
- },
226
- emailVerification: {
227
- summary: 'Email Verification Required',
228
- value: {
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
- }
236
- }
237
- }
238
- }
239
- }
240
- }
241
- }),
242
- _ts_param(0, Body()),
243
- _ts_metadata("design:type", Function),
244
- _ts_metadata("design:paramtypes", [
245
- typeof LoginDto === "undefined" ? Object : LoginDto
246
- ]),
247
- _ts_metadata("design:returntype", Promise)
248
- ], AuthenticationController.prototype, "login", null);
249
- _ts_decorate([
250
- Post('register'),
251
- HttpCode(HttpStatus.CREATED),
252
- Throttle({
253
- default: {
254
- limit: 3,
255
- ttl: 60000
256
- }
257
- }),
258
- UseInterceptors(SetToken),
259
- ApiOperation({
260
- summary: 'Register new user'
261
- }),
262
- ApiBody({
263
- type: RegistrationDto
264
- }),
265
- ApiResponse({
266
- status: 201,
267
- description: 'Registration successful or email verification required'
268
- }),
269
- _ts_param(0, Req()),
270
- _ts_param(1, Body()),
271
- _ts_metadata("design:type", Function),
272
- _ts_metadata("design:paramtypes", [
273
- typeof Request === "undefined" ? Object : Request,
274
- typeof RegistrationDto === "undefined" ? Object : RegistrationDto
275
- ]),
276
- _ts_metadata("design:returntype", Promise)
277
- ], AuthenticationController.prototype, "register", null);
278
- _ts_decorate([
279
- Post('refresh'),
280
- HttpCode(HttpStatus.OK),
281
- Throttle({
282
- default: {
283
- limit: 30,
284
- ttl: 60000
285
- }
286
- }),
287
- ApiOperation({
288
- summary: 'Refresh access token',
289
- description: `
290
- **Browser clients**: Refresh token is read from HTTP-only cookie (automatically set on login/register).
291
- Falls back to request body if cookie is not available.
292
-
293
- **API/Mobile clients**: Must send \`refreshToken\` in request body.
294
- Set header \`x-client-type: mobile\` or \`x-client-type: api\` to identify as non-browser client.
295
-
296
- **Client detection**: Uses \`x-client-type\` header first, then falls back to User-Agent detection.
297
- `
298
- }),
299
- ApiHeader({
300
- name: 'x-client-type',
301
- required: false,
302
- description: 'Client type: "browser"/"web" for cookie-based auth, "mobile"/"api" for body-based auth',
303
- example: 'mobile'
304
- }),
305
- ApiBody({
306
- type: RefreshTokenDto,
307
- description: 'Required for API/Mobile clients. Browser clients prefer HTTP-only cookie with body fallback.'
308
- }),
309
- ApiResponse({
310
- status: 200,
311
- description: 'Token refreshed successfully',
312
- schema: {
313
- example: {
314
- success: true,
315
- message: 'Token refreshed successfully',
316
- messageKey: 'auth.refresh.success',
317
- data: {
318
- accessToken: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...'
319
- }
320
- }
321
- }
322
- }),
323
- ApiResponse({
324
- status: 401,
325
- description: 'Invalid or missing refresh token'
326
- }),
327
- _ts_param(0, Req()),
328
- _ts_param(1, Body()),
329
- _ts_metadata("design:type", Function),
330
- _ts_metadata("design:paramtypes", [
331
- typeof Request === "undefined" ? Object : Request,
332
- typeof RefreshTokenDto === "undefined" ? Object : RefreshTokenDto
333
- ]),
334
- _ts_metadata("design:returntype", Promise)
335
- ], AuthenticationController.prototype, "refreshToken", null);
336
- _ts_decorate([
337
- UseGuards(JwtAuthGuard),
338
- Post('me'),
339
- SkipThrottle(),
340
- ApiBearerAuth(),
341
- ApiOperation({
342
- summary: 'Get current user info'
343
- }),
344
- ApiResponse({
345
- status: 200,
346
- description: 'Current user info retrieved successfully'
347
- }),
348
- _ts_param(0, CurrentUser()),
349
- _ts_metadata("design:type", Function),
350
- _ts_metadata("design:paramtypes", [
351
- typeof ILoggedUserInfo === "undefined" ? Object : ILoggedUserInfo
352
- ]),
353
- _ts_metadata("design:returntype", Promise)
354
- ], AuthenticationController.prototype, "getCurrentUser", null);
355
- _ts_decorate([
356
- UseGuards(JwtAuthGuard),
357
- Post('logout'),
358
- HttpCode(HttpStatus.OK),
359
- SkipThrottle(),
360
- UseInterceptors(ClearToken),
361
- ApiBearerAuth(),
362
- ApiOperation({
363
- summary: 'Logout user'
364
- }),
365
- ApiResponse({
366
- status: 200,
367
- type: MessageResponseDto
368
- }),
369
- _ts_param(0, CurrentUser('id')),
370
- _ts_metadata("design:type", Function),
371
- _ts_metadata("design:paramtypes", [
372
- String
373
- ]),
374
- _ts_metadata("design:returntype", Promise)
375
- ], AuthenticationController.prototype, "logout", null);
376
- _ts_decorate([
377
- UseGuards(JwtAuthGuard),
378
- Post('change-password'),
379
- HttpCode(HttpStatus.OK),
380
- Throttle({
381
- default: {
382
- limit: 5,
383
- ttl: 60000
384
- }
385
- }),
386
- ApiBearerAuth(),
387
- ApiOperation({
388
- summary: 'Change password'
389
- }),
390
- ApiBody({
391
- type: ChangePasswordDto
392
- }),
393
- ApiResponse({
394
- status: 200,
395
- type: MessageResponseDto
396
- }),
397
- _ts_param(0, CurrentUser('id')),
398
- _ts_param(1, Body()),
399
- _ts_metadata("design:type", Function),
400
- _ts_metadata("design:paramtypes", [
401
- String,
402
- typeof ChangePasswordDto === "undefined" ? Object : ChangePasswordDto
403
- ]),
404
- _ts_metadata("design:returntype", Promise)
405
- ], AuthenticationController.prototype, "changePassword", null);
406
- AuthenticationController = _ts_decorate([
407
- ApiTags('Authentication'),
408
- Controller('auth'),
409
- _ts_param(0, Inject(AuthenticationService)),
410
- _ts_param(1, Optional()),
411
- _ts_param(1, Inject(AuthConfigService)),
412
- _ts_metadata("design:type", Function),
413
- _ts_metadata("design:paramtypes", [
414
- typeof AuthenticationService === "undefined" ? Object : AuthenticationService,
415
- typeof AuthConfigService === "undefined" ? Object : AuthConfigService
416
- ])
417
- ], AuthenticationController);
@@ -1,215 +0,0 @@
1
- import { UnauthorizedException } from '@nestjs/common';
2
- import { buildMockUser } from '@test-utils/mocks/logged-user.mock';
3
- import { AuthenticationController } from './authentication.controller';
4
- describe('AuthenticationController', ()=>{
5
- let controller;
6
- let mockAuthService;
7
- let mockAuthConfig;
8
- beforeEach(()=>{
9
- mockAuthService = {
10
- login: jest.fn(),
11
- register: jest.fn(),
12
- refreshToken: jest.fn(),
13
- getUserInfo: jest.fn(),
14
- logout: jest.fn(),
15
- changePassword: jest.fn()
16
- };
17
- mockAuthConfig = {
18
- getRefreshTokenCookieName: jest.fn().mockReturnValue('fsn_refresh_token')
19
- };
20
- controller = new AuthenticationController(mockAuthService, mockAuthConfig);
21
- });
22
- describe('login', ()=>{
23
- it('wraps a standard login response', async ()=>{
24
- mockAuthService.login.mockResolvedValue({
25
- accessToken: 'a',
26
- refreshToken: 'r',
27
- user: {
28
- id: 'u1',
29
- email: 'u@example.com'
30
- }
31
- });
32
- const result = await controller.login({
33
- email: 'u@example.com',
34
- password: 'pw'
35
- });
36
- expect(result).toEqual(expect.objectContaining({
37
- success: true,
38
- data: expect.objectContaining({
39
- accessToken: 'a'
40
- })
41
- }));
42
- expect(mockAuthService.login).toHaveBeenCalledWith('u@example.com', 'pw');
43
- });
44
- it('wraps a company-selection-required response', async ()=>{
45
- mockAuthService.login.mockResolvedValue({
46
- requiresSelection: true,
47
- sessionId: 'sess-1'
48
- });
49
- const result = await controller.login({
50
- email: 'u@example.com',
51
- password: 'pw'
52
- });
53
- expect(result.message).toBe('Company selection required');
54
- expect(result.data).toEqual(expect.objectContaining({
55
- requiresSelection: true
56
- }));
57
- });
58
- it('wraps an email-verification-required response', async ()=>{
59
- mockAuthService.login.mockResolvedValue({
60
- requiresEmailVerification: true,
61
- email: 'u@example.com'
62
- });
63
- const result = await controller.login({
64
- email: 'u@example.com',
65
- password: 'pw'
66
- });
67
- expect(result.message).toBe('Email verification required');
68
- expect(result.data).toEqual(expect.objectContaining({
69
- requiresEmailVerification: true
70
- }));
71
- });
72
- it('propagates errors thrown by the service', async ()=>{
73
- mockAuthService.login.mockRejectedValue(new UnauthorizedException('bad creds'));
74
- await expect(controller.login({
75
- email: 'u@example.com',
76
- password: 'wrong'
77
- })).rejects.toThrow(UnauthorizedException);
78
- });
79
- });
80
- describe('register', ()=>{
81
- it('reports success message when registration completes without verification', async ()=>{
82
- mockAuthService.register.mockResolvedValue({
83
- accessToken: 'a',
84
- user: {
85
- id: 'u1'
86
- },
87
- requiresEmailVerification: false
88
- });
89
- const req = {
90
- headers: {},
91
- get: jest.fn((h)=>h === 'host' ? 'app.example.com' : undefined),
92
- protocol: 'https'
93
- };
94
- const result = await controller.register(req, {
95
- name: 'New',
96
- email: 'new@example.com',
97
- password: 'Password1!'
98
- });
99
- expect(result.message).toBe('Registration successful');
100
- expect(result.success).toBe(true);
101
- });
102
- it('reports verification-sent message when email verification is required', async ()=>{
103
- mockAuthService.register.mockResolvedValue({
104
- requiresEmailVerification: true,
105
- user: {
106
- id: 'u1'
107
- }
108
- });
109
- const req = {
110
- headers: {},
111
- get: jest.fn((h)=>h === 'host' ? 'app.example.com' : undefined),
112
- protocol: 'https'
113
- };
114
- const result = await controller.register(req, {
115
- name: 'New',
116
- email: 'new@example.com',
117
- password: 'Password1!'
118
- });
119
- expect(result.message).toBe('Verification email sent');
120
- });
121
- });
122
- describe('refreshToken', ()=>{
123
- it('reads the refresh token from the cookie first', async ()=>{
124
- mockAuthService.refreshToken.mockResolvedValue({
125
- accessToken: 'new-token'
126
- });
127
- const req = {
128
- cookies: {
129
- fsn_refresh_token: 'cookie-token'
130
- }
131
- };
132
- await controller.refreshToken(req, {
133
- refreshToken: 'body-token'
134
- });
135
- expect(mockAuthService.refreshToken).toHaveBeenCalledWith('cookie-token');
136
- });
137
- it('falls back to the request body when no cookie is present', async ()=>{
138
- mockAuthService.refreshToken.mockResolvedValue({
139
- accessToken: 'new-token'
140
- });
141
- const req = {
142
- cookies: {}
143
- };
144
- await controller.refreshToken(req, {
145
- refreshToken: 'body-token'
146
- });
147
- expect(mockAuthService.refreshToken).toHaveBeenCalledWith('body-token');
148
- });
149
- it('throws UnauthorizedException when no refresh token is available', async ()=>{
150
- const req = {
151
- cookies: {}
152
- };
153
- await expect(controller.refreshToken(req, {})).rejects.toThrow(UnauthorizedException);
154
- expect(mockAuthService.refreshToken).not.toHaveBeenCalled();
155
- });
156
- it('uses the default cookie name when authConfig is unavailable', async ()=>{
157
- controller = new AuthenticationController(mockAuthService, undefined);
158
- mockAuthService.refreshToken.mockResolvedValue({
159
- accessToken: 'new-token'
160
- });
161
- const req = {
162
- cookies: {
163
- fsn_refresh_token: 'cookie-token'
164
- }
165
- };
166
- await controller.refreshToken(req, {});
167
- expect(mockAuthService.refreshToken).toHaveBeenCalledWith('cookie-token');
168
- });
169
- });
170
- describe('getCurrentUser', ()=>{
171
- it('delegates to authService.getUserInfo with the current user context', async ()=>{
172
- mockAuthService.getUserInfo.mockResolvedValue({
173
- user: {
174
- id: 'u1'
175
- }
176
- });
177
- const user = buildMockUser();
178
- const result = await controller.getCurrentUser(user);
179
- expect(mockAuthService.getUserInfo).toHaveBeenCalledWith(user.id, user.companyId, user.branchId);
180
- expect(result.data).toEqual({
181
- user: {
182
- id: 'u1'
183
- }
184
- });
185
- });
186
- });
187
- describe('logout', ()=>{
188
- it('delegates to authService.logout and returns a success message', async ()=>{
189
- const result = await controller.logout('user-1');
190
- expect(mockAuthService.logout).toHaveBeenCalledWith('user-1');
191
- expect(result).toEqual(expect.objectContaining({
192
- success: true
193
- }));
194
- });
195
- });
196
- describe('changePassword', ()=>{
197
- it('delegates to authService.changePassword', async ()=>{
198
- const result = await controller.changePassword('user-1', {
199
- currentPassword: 'old',
200
- newPassword: 'New1!aaaa'
201
- });
202
- expect(mockAuthService.changePassword).toHaveBeenCalledWith('user-1', 'old', 'New1!aaaa');
203
- expect(result).toEqual(expect.objectContaining({
204
- success: true
205
- }));
206
- });
207
- it('propagates errors from an invalid current password', async ()=>{
208
- mockAuthService.changePassword.mockRejectedValue(new UnauthorizedException());
209
- await expect(controller.changePassword('user-1', {
210
- currentPassword: 'wrong',
211
- newPassword: 'New1!aaaa'
212
- })).rejects.toThrow(UnauthorizedException);
213
- });
214
- });
215
- });