@flusys/nestjs-auth 1.1.0-beta → 2.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.
- package/README.md +590 -473
- package/cjs/config/auth.constants.js +8 -0
- package/cjs/controllers/authentication.controller.js +218 -39
- package/cjs/controllers/branch.controller.js +44 -1
- package/cjs/controllers/company-selection.controller.js +27 -20
- package/cjs/controllers/company.controller.js +44 -1
- package/cjs/controllers/user-permission.controller.js +82 -154
- package/cjs/controllers/user.controller.js +68 -15
- package/cjs/docs/auth-swagger.config.js +14 -7
- package/cjs/dtos/authentication.dto.js +16 -43
- package/cjs/dtos/index.js +0 -1
- package/cjs/dtos/user-permission.dto.js +28 -0
- package/cjs/dtos/user.dto.js +19 -4
- package/cjs/entities/user-company-permission.entity.js +0 -6
- package/cjs/interceptors/clear-token.interceptor.js +10 -23
- package/cjs/interceptors/set-token.interceptor.js +15 -55
- package/cjs/interfaces/auth-email-provider.interface.js +1 -1
- package/cjs/modules/auth.module.js +63 -147
- package/cjs/services/auth-config.service.js +22 -28
- package/cjs/services/auth-datasource.provider.js +9 -21
- package/cjs/services/auth-email.service.js +89 -85
- package/cjs/services/authentication.service.js +225 -396
- package/cjs/services/branch.service.js +9 -4
- package/cjs/services/company-selection-session.service.js +1 -1
- package/cjs/services/user-permission.service.js +43 -73
- package/cjs/services/user.service.js +78 -64
- package/cjs/strategies/jwt.strategy.js +44 -44
- package/cjs/validators/password.validator.js +45 -0
- package/config/auth.constants.d.ts +2 -0
- package/controllers/authentication.controller.d.ts +5 -3
- package/controllers/company-selection.controller.d.ts +6 -2
- package/controllers/user-permission.controller.d.ts +5 -4
- package/controllers/user.controller.d.ts +6 -0
- package/dtos/authentication.dto.d.ts +0 -4
- package/dtos/company-branch.dto.d.ts +0 -1
- package/dtos/company.dto.d.ts +0 -1
- package/dtos/index.d.ts +0 -1
- package/dtos/user-permission.dto.d.ts +4 -0
- package/dtos/user.dto.d.ts +1 -3
- package/entities/index.d.ts +3 -3
- package/entities/user-company-permission.entity.d.ts +0 -2
- package/fesm/config/auth.constants.js +6 -13
- package/fesm/controllers/authentication.controller.js +221 -42
- package/fesm/controllers/branch.controller.js +45 -2
- package/fesm/controllers/company-selection.controller.js +28 -21
- package/fesm/controllers/company.controller.js +45 -2
- package/fesm/controllers/user-permission.controller.js +84 -156
- package/fesm/controllers/user.controller.js +71 -18
- package/fesm/docs/auth-swagger.config.js +14 -7
- package/fesm/dtos/authentication.dto.js +17 -44
- package/fesm/dtos/index.js +0 -1
- package/fesm/dtos/user-permission.dto.js +28 -0
- package/fesm/dtos/user.dto.js +20 -5
- package/fesm/entities/user-company-permission.entity.js +0 -6
- package/fesm/interceptors/clear-token.interceptor.js +9 -22
- package/fesm/interceptors/set-token.interceptor.js +14 -54
- package/fesm/interfaces/auth-email-provider.interface.js +1 -1
- package/fesm/modules/auth.module.js +64 -148
- package/fesm/services/auth-config.service.js +23 -29
- package/fesm/services/auth-datasource.provider.js +10 -22
- package/fesm/services/auth-email.service.js +90 -86
- package/fesm/services/authentication.service.js +225 -396
- package/fesm/services/branch.service.js +9 -4
- package/fesm/services/company-selection-session.service.js +1 -1
- package/fesm/services/user-permission.service.js +44 -74
- package/fesm/services/user.service.js +79 -65
- package/fesm/strategies/jwt.strategy.js +44 -44
- package/fesm/validators/password.validator.js +48 -0
- package/interceptors/clear-token.interceptor.d.ts +0 -1
- package/interceptors/set-token.interceptor.d.ts +1 -1
- package/interfaces/authentication.interface.d.ts +0 -4
- package/interfaces/user-enricher.interface.d.ts +1 -4
- package/modules/auth.module.d.ts +6 -3
- package/package.json +4 -4
- package/services/auth-config.service.d.ts +6 -8
- package/services/auth-datasource.provider.d.ts +2 -4
- package/services/auth-email.service.d.ts +8 -4
- package/services/authentication.service.d.ts +15 -16
- package/services/company-selection-session.service.d.ts +1 -1
- package/services/user-permission.service.d.ts +6 -9
- package/services/user.service.d.ts +3 -0
- package/strategies/jwt.strategy.d.ts +4 -1
- package/validators/password.validator.d.ts +10 -0
- package/cjs/dtos/user-company-permission.dto.js +0 -110
- package/dtos/user-company-permission.dto.d.ts +0 -10
- package/fesm/dtos/user-company-permission.dto.js +0 -98
|
@@ -16,6 +16,12 @@ _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
|
},
|
|
@@ -29,5 +35,7 @@ _export(exports, {
|
|
|
29
35
|
const AUTH_MODULE_OPTIONS = 'AUTH_MODULE_OPTIONS';
|
|
30
36
|
const USER_ENRICHER = 'USER_ENRICHER';
|
|
31
37
|
const BCRYPT_SALT_ROUNDS = 12;
|
|
38
|
+
const DEFAULT_COOKIE_NAME = 'fsn_refresh_token';
|
|
39
|
+
const MAX_COOKIE_BYTES = 3500;
|
|
32
40
|
const SESSION_CACHE_PREFIX = 'auth:session';
|
|
33
41
|
const TOKEN_REVOKED_PREFIX = 'auth:revoked';
|
|
@@ -9,13 +9,15 @@ 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
|
-
const _dtos = require("@flusys/nestjs-shared/dtos");
|
|
19
21
|
const _cleartokeninterceptor = require("../interceptors/clear-token.interceptor");
|
|
20
22
|
const _settokeninterceptor = require("../interceptors/set-token.interceptor");
|
|
21
23
|
const _authconfigservice = require("../services/auth-config.service");
|
|
@@ -49,13 +51,24 @@ function _ts_param(paramIndex, decorator) {
|
|
|
49
51
|
};
|
|
50
52
|
}
|
|
51
53
|
let AuthenticationController = class AuthenticationController {
|
|
52
|
-
|
|
54
|
+
buildAuthUrl(req, path) {
|
|
53
55
|
const frontendUrl = this.authConfig?.getFrontendUrl();
|
|
54
56
|
return frontendUrl ? `${frontendUrl}${path}` : `${req.protocol}://${req.get('host')}${path}`;
|
|
55
57
|
}
|
|
56
|
-
|
|
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) {
|
|
58
68
|
const result = await this.authService.login(loginDto.email, loginDto.password);
|
|
69
|
+
if ('requiresEmailVerification' in result) {
|
|
70
|
+
return result;
|
|
71
|
+
}
|
|
59
72
|
if ('requiresSelection' in result) {
|
|
60
73
|
return result;
|
|
61
74
|
}
|
|
@@ -64,14 +77,15 @@ let AuthenticationController = class AuthenticationController {
|
|
|
64
77
|
/** Register new user. If company feature enabled, can join/create company. */ async register(req, registrationDto) {
|
|
65
78
|
const verifyUrlBase = this.buildAuthUrl(req, '/auth/verify-email');
|
|
66
79
|
const result = await this.authService.register(registrationDto, verifyUrlBase);
|
|
67
|
-
return
|
|
68
|
-
...result,
|
|
69
|
-
companyFeatureEnabled: this.authConfig?.isCompanyFeatureEnabled() ?? false
|
|
70
|
-
};
|
|
80
|
+
return result;
|
|
71
81
|
}
|
|
72
|
-
/**
|
|
73
|
-
|
|
74
|
-
|
|
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
|
|
75
89
|
const refreshToken = req.cookies?.[cookieName] || refreshTokenDto.refreshToken;
|
|
76
90
|
if (!refreshToken) {
|
|
77
91
|
throw new _common.UnauthorizedException('Refresh token is required');
|
|
@@ -88,63 +102,56 @@ let AuthenticationController = class AuthenticationController {
|
|
|
88
102
|
message: 'Logged out successfully'
|
|
89
103
|
};
|
|
90
104
|
}
|
|
91
|
-
|
|
105
|
+
async changePassword(userId, dto) {
|
|
92
106
|
await this.authService.changePassword(userId, dto.currentPassword, dto.newPassword);
|
|
93
107
|
return {
|
|
94
108
|
success: true,
|
|
95
109
|
message: 'Password changed successfully'
|
|
96
110
|
};
|
|
97
111
|
}
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
if (!this.authEmailService) {
|
|
112
|
+
async forgotPassword(req, dto) {
|
|
113
|
+
if (!this.isEmailEnabled) {
|
|
101
114
|
return {
|
|
102
115
|
success: false,
|
|
103
116
|
message: 'Email service is not configured'
|
|
104
117
|
};
|
|
105
118
|
}
|
|
106
|
-
return this.
|
|
119
|
+
return this.emailService.forgotPassword(dto.email, this.buildAuthUrl(req, '/auth/reset-password'));
|
|
107
120
|
}
|
|
108
|
-
|
|
109
|
-
if (!this.
|
|
121
|
+
async resetPassword(dto) {
|
|
122
|
+
if (!this.isEmailEnabled) {
|
|
110
123
|
return {
|
|
111
124
|
success: false,
|
|
112
125
|
message: 'Email service is not configured'
|
|
113
126
|
};
|
|
114
127
|
}
|
|
115
|
-
return this.
|
|
128
|
+
return this.emailService.resetPassword(dto.token, dto.newPassword);
|
|
116
129
|
}
|
|
117
|
-
|
|
118
|
-
if (!this.
|
|
130
|
+
async resendVerification(req, dto) {
|
|
131
|
+
if (!this.isEmailEnabled) {
|
|
119
132
|
return {
|
|
120
133
|
success: false,
|
|
121
134
|
message: 'Email service is not configured'
|
|
122
135
|
};
|
|
123
136
|
}
|
|
124
|
-
return this.
|
|
137
|
+
return this.emailService.resendVerificationEmail(dto.email, this.buildAuthUrl(req, '/auth/verify-email'));
|
|
125
138
|
}
|
|
126
139
|
/** Verify email - Verify email using token. Handles both pending registration and existing user verification. */ async verifyEmail(dto) {
|
|
127
|
-
if (!this.
|
|
140
|
+
if (!this.isEmailEnabled) {
|
|
128
141
|
return {
|
|
129
142
|
success: false,
|
|
130
143
|
message: 'Email service is not configured'
|
|
131
144
|
};
|
|
132
145
|
}
|
|
133
|
-
const result = await this.
|
|
146
|
+
const result = await this.emailService.verifyEmail(dto.token);
|
|
134
147
|
if (result.type === 'pending') {
|
|
135
|
-
|
|
136
|
-
const registrationResult = await this.authService.createUserFromPendingRegistration(result.pending);
|
|
137
|
-
return {
|
|
138
|
-
...registrationResult,
|
|
139
|
-
companyFeatureEnabled: this.authConfig?.isCompanyFeatureEnabled() ?? false
|
|
140
|
-
};
|
|
148
|
+
return this.authService.createUserFromPendingRegistration(result.pending);
|
|
141
149
|
}
|
|
142
150
|
return {
|
|
143
151
|
success: true,
|
|
144
152
|
message: result.message
|
|
145
153
|
};
|
|
146
154
|
}
|
|
147
|
-
// NOTE: @Inject() required for bundled code - type metadata may be lost during esbuild
|
|
148
155
|
constructor(authService, authConfig, authEmailService){
|
|
149
156
|
_define_property(this, "authService", void 0);
|
|
150
157
|
_define_property(this, "authConfig", void 0);
|
|
@@ -157,6 +164,12 @@ let AuthenticationController = class AuthenticationController {
|
|
|
157
164
|
_ts_decorate([
|
|
158
165
|
(0, _common.Post)('login'),
|
|
159
166
|
(0, _common.HttpCode)(_common.HttpStatus.OK),
|
|
167
|
+
(0, _throttler.Throttle)({
|
|
168
|
+
default: {
|
|
169
|
+
limit: 5,
|
|
170
|
+
ttl: 60000
|
|
171
|
+
}
|
|
172
|
+
}),
|
|
160
173
|
(0, _common.UseInterceptors)(_settokeninterceptor.SetToken),
|
|
161
174
|
(0, _swagger.ApiOperation)({
|
|
162
175
|
summary: 'User login'
|
|
@@ -164,13 +177,102 @@ _ts_decorate([
|
|
|
164
177
|
(0, _swagger.ApiBody)({
|
|
165
178
|
type: _authenticationdto.LoginDto
|
|
166
179
|
}),
|
|
180
|
+
(0, _swagger.ApiExtraModels)(_authenticationdto.LoginResponseDto, _authenticationdto.CompanySelectionResponseDto, _authenticationdto.LoginResponseRequiresEmailVerificationDto),
|
|
167
181
|
(0, _swagger.ApiResponse)({
|
|
168
182
|
status: 200,
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
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
|
+
}
|
|
174
276
|
}),
|
|
175
277
|
_ts_param(0, (0, _common.Body)()),
|
|
176
278
|
_ts_metadata("design:type", Function),
|
|
@@ -182,6 +284,12 @@ _ts_decorate([
|
|
|
182
284
|
_ts_decorate([
|
|
183
285
|
(0, _common.Post)('register'),
|
|
184
286
|
(0, _common.HttpCode)(_common.HttpStatus.CREATED),
|
|
287
|
+
(0, _throttler.Throttle)({
|
|
288
|
+
default: {
|
|
289
|
+
limit: 3,
|
|
290
|
+
ttl: 60000
|
|
291
|
+
}
|
|
292
|
+
}),
|
|
185
293
|
(0, _common.UseInterceptors)(_settokeninterceptor.SetToken),
|
|
186
294
|
(0, _swagger.ApiOperation)({
|
|
187
295
|
summary: 'Register new user'
|
|
@@ -205,11 +313,50 @@ _ts_decorate([
|
|
|
205
313
|
_ts_decorate([
|
|
206
314
|
(0, _common.Post)('refresh'),
|
|
207
315
|
(0, _common.HttpCode)(_common.HttpStatus.OK),
|
|
316
|
+
(0, _throttler.Throttle)({
|
|
317
|
+
default: {
|
|
318
|
+
limit: 30,
|
|
319
|
+
ttl: 60000
|
|
320
|
+
}
|
|
321
|
+
}),
|
|
208
322
|
(0, _swagger.ApiOperation)({
|
|
209
|
-
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'
|
|
210
339
|
}),
|
|
211
340
|
(0, _swagger.ApiBody)({
|
|
212
|
-
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'
|
|
213
360
|
}),
|
|
214
361
|
_ts_param(0, (0, _common.Req)()),
|
|
215
362
|
_ts_param(1, (0, _common.Body)()),
|
|
@@ -222,7 +369,8 @@ _ts_decorate([
|
|
|
222
369
|
], AuthenticationController.prototype, "refreshToken", null);
|
|
223
370
|
_ts_decorate([
|
|
224
371
|
(0, _common.UseGuards)(_guards.JwtAuthGuard),
|
|
225
|
-
(0, _common.
|
|
372
|
+
(0, _common.Post)('me'),
|
|
373
|
+
(0, _throttler.SkipThrottle)(),
|
|
226
374
|
(0, _swagger.ApiBearerAuth)(),
|
|
227
375
|
(0, _swagger.ApiOperation)({
|
|
228
376
|
summary: 'Get current user info'
|
|
@@ -242,6 +390,7 @@ _ts_decorate([
|
|
|
242
390
|
(0, _common.UseGuards)(_guards.JwtAuthGuard),
|
|
243
391
|
(0, _common.Post)('logout'),
|
|
244
392
|
(0, _common.HttpCode)(_common.HttpStatus.OK),
|
|
393
|
+
(0, _throttler.SkipThrottle)(),
|
|
245
394
|
(0, _common.UseInterceptors)(_cleartokeninterceptor.ClearToken),
|
|
246
395
|
(0, _swagger.ApiBearerAuth)(),
|
|
247
396
|
(0, _swagger.ApiOperation)({
|
|
@@ -262,6 +411,12 @@ _ts_decorate([
|
|
|
262
411
|
(0, _common.UseGuards)(_guards.JwtAuthGuard),
|
|
263
412
|
(0, _common.Post)('change-password'),
|
|
264
413
|
(0, _common.HttpCode)(_common.HttpStatus.OK),
|
|
414
|
+
(0, _throttler.Throttle)({
|
|
415
|
+
default: {
|
|
416
|
+
limit: 5,
|
|
417
|
+
ttl: 60000
|
|
418
|
+
}
|
|
419
|
+
}),
|
|
265
420
|
(0, _swagger.ApiBearerAuth)(),
|
|
266
421
|
(0, _swagger.ApiOperation)({
|
|
267
422
|
summary: 'Change password'
|
|
@@ -285,6 +440,12 @@ _ts_decorate([
|
|
|
285
440
|
_ts_decorate([
|
|
286
441
|
(0, _common.Post)('forgot-password'),
|
|
287
442
|
(0, _common.HttpCode)(_common.HttpStatus.OK),
|
|
443
|
+
(0, _throttler.Throttle)({
|
|
444
|
+
default: {
|
|
445
|
+
limit: 3,
|
|
446
|
+
ttl: 300000
|
|
447
|
+
}
|
|
448
|
+
}),
|
|
288
449
|
(0, _swagger.ApiOperation)({
|
|
289
450
|
summary: 'Request password reset email'
|
|
290
451
|
}),
|
|
@@ -307,6 +468,12 @@ _ts_decorate([
|
|
|
307
468
|
_ts_decorate([
|
|
308
469
|
(0, _common.Post)('reset-password'),
|
|
309
470
|
(0, _common.HttpCode)(_common.HttpStatus.OK),
|
|
471
|
+
(0, _throttler.Throttle)({
|
|
472
|
+
default: {
|
|
473
|
+
limit: 5,
|
|
474
|
+
ttl: 900000
|
|
475
|
+
}
|
|
476
|
+
}),
|
|
310
477
|
(0, _swagger.ApiOperation)({
|
|
311
478
|
summary: 'Reset password using token'
|
|
312
479
|
}),
|
|
@@ -327,6 +494,12 @@ _ts_decorate([
|
|
|
327
494
|
_ts_decorate([
|
|
328
495
|
(0, _common.Post)('resend-verification'),
|
|
329
496
|
(0, _common.HttpCode)(_common.HttpStatus.OK),
|
|
497
|
+
(0, _throttler.Throttle)({
|
|
498
|
+
default: {
|
|
499
|
+
limit: 3,
|
|
500
|
+
ttl: 300000
|
|
501
|
+
}
|
|
502
|
+
}),
|
|
330
503
|
(0, _swagger.ApiOperation)({
|
|
331
504
|
summary: 'Resend email verification link'
|
|
332
505
|
}),
|
|
@@ -349,6 +522,12 @@ _ts_decorate([
|
|
|
349
522
|
_ts_decorate([
|
|
350
523
|
(0, _common.Post)('verify-email'),
|
|
351
524
|
(0, _common.HttpCode)(_common.HttpStatus.OK),
|
|
525
|
+
(0, _throttler.Throttle)({
|
|
526
|
+
default: {
|
|
527
|
+
limit: 10,
|
|
528
|
+
ttl: 60000
|
|
529
|
+
}
|
|
530
|
+
}),
|
|
352
531
|
(0, _common.UseInterceptors)(_settokeninterceptor.SetToken),
|
|
353
532
|
(0, _swagger.ApiOperation)({
|
|
354
533
|
summary: 'Verify email using token'
|
|
@@ -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:
|
|
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
|
-
|
|
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
|
-
|
|
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.
|
|
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.
|
|
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.
|
|
159
|
+
_ts_param(1, (0, _common.Body)('companyId')),
|
|
153
160
|
_ts_metadata("design:type", Function),
|
|
154
161
|
_ts_metadata("design:paramtypes", [
|
|
155
162
|
String,
|
|
@@ -41,7 +41,50 @@ function _ts_param(paramIndex, decorator) {
|
|
|
41
41
|
};
|
|
42
42
|
}
|
|
43
43
|
let CompanyController = class CompanyController extends (0, _classes.createApiController)(_companydto.CreateCompanyDto, _companydto.UpdateCompanyDto, _companydto.CompanyResponseDto, {
|
|
44
|
-
security:
|
|
44
|
+
security: {
|
|
45
|
+
insert: {
|
|
46
|
+
level: 'permission',
|
|
47
|
+
permissions: [
|
|
48
|
+
_classes.COMPANY_PERMISSIONS.CREATE
|
|
49
|
+
]
|
|
50
|
+
},
|
|
51
|
+
insertMany: {
|
|
52
|
+
level: 'permission',
|
|
53
|
+
permissions: [
|
|
54
|
+
_classes.COMPANY_PERMISSIONS.CREATE
|
|
55
|
+
]
|
|
56
|
+
},
|
|
57
|
+
getById: {
|
|
58
|
+
level: 'permission',
|
|
59
|
+
permissions: [
|
|
60
|
+
_classes.COMPANY_PERMISSIONS.READ
|
|
61
|
+
]
|
|
62
|
+
},
|
|
63
|
+
getAll: {
|
|
64
|
+
level: 'permission',
|
|
65
|
+
permissions: [
|
|
66
|
+
_classes.COMPANY_PERMISSIONS.READ
|
|
67
|
+
]
|
|
68
|
+
},
|
|
69
|
+
update: {
|
|
70
|
+
level: 'permission',
|
|
71
|
+
permissions: [
|
|
72
|
+
_classes.COMPANY_PERMISSIONS.UPDATE
|
|
73
|
+
]
|
|
74
|
+
},
|
|
75
|
+
updateMany: {
|
|
76
|
+
level: 'permission',
|
|
77
|
+
permissions: [
|
|
78
|
+
_classes.COMPANY_PERMISSIONS.UPDATE
|
|
79
|
+
]
|
|
80
|
+
},
|
|
81
|
+
delete: {
|
|
82
|
+
level: 'permission',
|
|
83
|
+
permissions: [
|
|
84
|
+
_classes.COMPANY_PERMISSIONS.DELETE
|
|
85
|
+
]
|
|
86
|
+
}
|
|
87
|
+
}
|
|
45
88
|
}) {
|
|
46
89
|
constructor(companyService){
|
|
47
90
|
super(companyService), _define_property(this, "companyService", void 0), this.companyService = companyService;
|