@flusys/nestjs-auth 1.0.0-rc → 1.0.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 (61) hide show
  1. package/README.md +530 -396
  2. package/cjs/controllers/authentication.controller.js +160 -28
  3. package/cjs/controllers/user-permission.controller.js +49 -136
  4. package/cjs/docs/auth-swagger.config.js +14 -7
  5. package/cjs/dtos/authentication.dto.js +0 -30
  6. package/cjs/dtos/index.js +0 -1
  7. package/cjs/entities/user-company-permission.entity.js +3 -3
  8. package/cjs/interceptors/clear-token.interceptor.js +8 -18
  9. package/cjs/interceptors/set-token.interceptor.js +8 -55
  10. package/cjs/interfaces/auth-email-provider.interface.js +1 -1
  11. package/cjs/modules/auth.module.js +63 -129
  12. package/cjs/services/auth-config.service.js +6 -29
  13. package/cjs/services/auth-datasource.provider.js +8 -20
  14. package/cjs/services/auth-email.service.js +72 -87
  15. package/cjs/services/authentication.service.js +211 -355
  16. package/cjs/services/branch.service.js +9 -5
  17. package/cjs/services/user-permission.service.js +43 -71
  18. package/cjs/services/user.service.js +18 -47
  19. package/cjs/strategies/jwt.strategy.js +44 -44
  20. package/controllers/authentication.controller.d.ts +5 -3
  21. package/controllers/user-permission.controller.d.ts +5 -4
  22. package/dtos/authentication.dto.d.ts +0 -4
  23. package/dtos/index.d.ts +0 -1
  24. package/entities/index.d.ts +3 -3
  25. package/entities/user-company-permission.entity.d.ts +1 -1
  26. package/fesm/controllers/authentication.controller.js +162 -30
  27. package/fesm/controllers/user-permission.controller.js +50 -137
  28. package/fesm/docs/auth-swagger.config.js +14 -7
  29. package/fesm/dtos/authentication.dto.js +0 -30
  30. package/fesm/dtos/index.js +0 -1
  31. package/fesm/entities/user-company-permission.entity.js +3 -3
  32. package/fesm/interceptors/clear-token.interceptor.js +8 -18
  33. package/fesm/interceptors/set-token.interceptor.js +8 -55
  34. package/fesm/interfaces/auth-email-provider.interface.js +1 -1
  35. package/fesm/modules/auth.module.js +63 -129
  36. package/fesm/services/auth-config.service.js +6 -29
  37. package/fesm/services/auth-datasource.provider.js +8 -20
  38. package/fesm/services/auth-email.service.js +72 -87
  39. package/fesm/services/authentication.service.js +211 -355
  40. package/fesm/services/branch.service.js +9 -5
  41. package/fesm/services/user-permission.service.js +44 -72
  42. package/fesm/services/user.service.js +18 -47
  43. package/fesm/strategies/jwt.strategy.js +44 -44
  44. package/interceptors/clear-token.interceptor.d.ts +0 -1
  45. package/interceptors/set-token.interceptor.d.ts +1 -2
  46. package/interfaces/authentication.interface.d.ts +0 -4
  47. package/modules/auth.module.d.ts +6 -2
  48. package/package.json +3 -3
  49. package/services/auth-config.service.d.ts +2 -7
  50. package/services/auth-datasource.provider.d.ts +2 -4
  51. package/services/auth-email.service.d.ts +7 -4
  52. package/services/authentication.service.d.ts +14 -8
  53. package/services/user-permission.service.d.ts +6 -8
  54. package/services/user.service.d.ts +1 -1
  55. package/strategies/jwt.strategy.d.ts +4 -1
  56. package/cjs/dtos/user-company-permission.dto.js +0 -110
  57. package/cjs/guards/auth-throttler.guard.js +0 -53
  58. package/dtos/user-company-permission.dto.d.ts +0 -10
  59. package/fesm/dtos/user-company-permission.dto.js +0 -98
  60. package/fesm/guards/auth-throttler.guard.js +0 -43
  61. package/guards/auth-throttler.guard.d.ts +0 -7
@@ -9,14 +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");
16
17
  const _throttler = require("@nestjs/throttler");
17
18
  const _express = require("express");
19
+ const _config = require("../config");
18
20
  const _authenticationdto = require("../dtos/authentication.dto");
19
- const _dtos = require("@flusys/nestjs-shared/dtos");
20
21
  const _cleartokeninterceptor = require("../interceptors/clear-token.interceptor");
21
22
  const _settokeninterceptor = require("../interceptors/set-token.interceptor");
22
23
  const _authconfigservice = require("../services/auth-config.service");
@@ -54,8 +55,20 @@ let AuthenticationController = class AuthenticationController {
54
55
  const frontendUrl = this.authConfig?.getFrontendUrl();
55
56
  return frontendUrl ? `${frontendUrl}${path}` : `${req.protocol}://${req.get('host')}${path}`;
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
+ }
57
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
- /** Refresh access token. Browser uses HTTP-only cookie, API/Mobile uses request body. */ async refreshToken(req, refreshTokenDto) {
73
- // Get refresh token from cookie (browser) or body (API/mobile)
74
- 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
75
89
  const refreshToken = req.cookies?.[cookieName] || refreshTokenDto.refreshToken;
76
90
  if (!refreshToken) {
77
91
  throw new _common.UnauthorizedException('Refresh token is required');
@@ -96,46 +110,42 @@ let AuthenticationController = class AuthenticationController {
96
110
  };
97
111
  }
98
112
  async forgotPassword(req, dto) {
99
- if (!this.authEmailService) {
113
+ if (!this.isEmailEnabled) {
100
114
  return {
101
115
  success: false,
102
116
  message: 'Email service is not configured'
103
117
  };
104
118
  }
105
- return this.authEmailService.forgotPassword(dto.email, this.buildAuthUrl(req, '/auth/reset-password'));
119
+ return this.emailService.forgotPassword(dto.email, this.buildAuthUrl(req, '/auth/reset-password'));
106
120
  }
107
121
  async resetPassword(dto) {
108
- if (!this.authEmailService) {
122
+ if (!this.isEmailEnabled) {
109
123
  return {
110
124
  success: false,
111
125
  message: 'Email service is not configured'
112
126
  };
113
127
  }
114
- return this.authEmailService.resetPassword(dto.token, dto.newPassword);
128
+ return this.emailService.resetPassword(dto.token, dto.newPassword);
115
129
  }
116
130
  async resendVerification(req, dto) {
117
- if (!this.authEmailService) {
131
+ if (!this.isEmailEnabled) {
118
132
  return {
119
133
  success: false,
120
134
  message: 'Email service is not configured'
121
135
  };
122
136
  }
123
- return this.authEmailService.resendVerificationEmail(dto.email, this.buildAuthUrl(req, '/auth/verify-email'));
137
+ return this.emailService.resendVerificationEmail(dto.email, this.buildAuthUrl(req, '/auth/verify-email'));
124
138
  }
125
139
  /** Verify email - Verify email using token. Handles both pending registration and existing user verification. */ async verifyEmail(dto) {
126
- if (!this.authEmailService) {
140
+ if (!this.isEmailEnabled) {
127
141
  return {
128
142
  success: false,
129
143
  message: 'Email service is not configured'
130
144
  };
131
145
  }
132
- const result = await this.authEmailService.verifyEmail(dto.token);
146
+ const result = await this.emailService.verifyEmail(dto.token);
133
147
  if (result.type === 'pending') {
134
- const registrationResult = await this.authService.createUserFromPendingRegistration(result.pending);
135
- return {
136
- ...registrationResult,
137
- companyFeatureEnabled: this.authConfig?.isCompanyFeatureEnabled() ?? false
138
- };
148
+ return this.authService.createUserFromPendingRegistration(result.pending);
139
149
  }
140
150
  return {
141
151
  success: true,
@@ -167,13 +177,102 @@ _ts_decorate([
167
177
  (0, _swagger.ApiBody)({
168
178
  type: _authenticationdto.LoginDto
169
179
  }),
180
+ (0, _swagger.ApiExtraModels)(_authenticationdto.LoginResponseDto, _authenticationdto.CompanySelectionResponseDto, _authenticationdto.LoginResponseRequiresEmailVerificationDto),
170
181
  (0, _swagger.ApiResponse)({
171
182
  status: 200,
172
- type: _authenticationdto.LoginResponseDto
173
- }),
174
- (0, _swagger.ApiResponse)({
175
- status: 200,
176
- 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
+ }
177
276
  }),
178
277
  _ts_param(0, (0, _common.Body)()),
179
278
  _ts_metadata("design:type", Function),
@@ -221,10 +320,43 @@ _ts_decorate([
221
320
  }
222
321
  }),
223
322
  (0, _swagger.ApiOperation)({
224
- 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'
225
339
  }),
226
340
  (0, _swagger.ApiBody)({
227
- 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'
228
360
  }),
229
361
  _ts_param(0, (0, _common.Req)()),
230
362
  _ts_param(1, (0, _common.Body)()),
@@ -8,10 +8,11 @@ Object.defineProperty(exports, "UserPermissionController", {
8
8
  return UserPermissionController;
9
9
  }
10
10
  });
11
+ const _nestjsshared = require("@flusys/nestjs-shared");
11
12
  const _common = require("@nestjs/common");
12
13
  const _swagger = require("@nestjs/swagger");
13
- const _nestjsshared = require("@flusys/nestjs-shared");
14
14
  const _userpermissiondto = require("../dtos/user-permission.dto");
15
+ const _usercompanypermissionentity = require("../entities/user-company-permission.entity");
15
16
  const _userpermissionservice = require("../services/user-permission.service");
16
17
  function _define_property(obj, key, value) {
17
18
  if (key in obj) {
@@ -42,122 +43,66 @@ function _ts_param(paramIndex, decorator) {
42
43
  }
43
44
  let UserPermissionController = class UserPermissionController {
44
45
  async assignUserCompany(dto) {
45
- let addedCount = 0;
46
- let removedCount = 0;
47
- for (const item of dto.items){
48
- if (item.isAdd) {
49
- await this.userPermissionService.assignUserToCompany({
50
- userId: dto.userId,
51
- companyId: item.targetId
52
- });
53
- addedCount++;
54
- } else {
55
- await this.userPermissionService.revokeCompanyAccess(dto.userId, item.targetId);
56
- removedCount++;
57
- }
58
- }
59
- return {
60
- success: true,
61
- message: `Processed ${addedCount} additions and ${removedCount} removals`
62
- };
46
+ return this.processBatchPermissions(dto.userId, dto.items, _usercompanypermissionentity.PermissionType.COMPANY);
63
47
  }
64
48
  async getUserCompanies(userId) {
65
- const permissions = await this.userPermissionService.findUserCompanies(userId);
66
- const data = permissions.map((permission)=>({
67
- id: permission.id,
68
- userId: permission.userId,
69
- companyId: permission.company?.id || permission.targetId,
70
- companyName: permission.company?.name || '',
71
- companySlug: permission.company?.slug || ''
72
- }));
49
+ const permissions = await this.permissionService.findUserCompanies(userId);
73
50
  return {
74
51
  success: true,
75
52
  message: 'User companies retrieved successfully',
76
- data
53
+ data: permissions.map((p)=>({
54
+ id: p.id,
55
+ userId: p.userId,
56
+ companyId: p.company?.id || p.targetId,
57
+ companyName: p.company?.name || '',
58
+ companySlug: p.company?.slug || ''
59
+ }))
77
60
  };
78
61
  }
79
62
  async assignUserBranch(dto) {
80
- let addedCount = 0;
81
- let removedCount = 0;
82
- for (const item of dto.items){
83
- if (item.isAdd) {
84
- await this.userPermissionService.assignUserToBranch({
85
- userId: dto.userId,
86
- branchId: item.targetId
87
- });
88
- addedCount++;
89
- } else {
90
- await this.userPermissionService.revokeBranchAccess(dto.userId, item.targetId);
91
- removedCount++;
92
- }
93
- }
63
+ return this.processBatchPermissions(dto.userId, dto.items, _usercompanypermissionentity.PermissionType.BRANCH);
64
+ }
65
+ async getUserBranches(userId, companyId) {
66
+ const permissions = await this.permissionService.findUserBranches(userId, companyId);
94
67
  return {
95
68
  success: true,
96
- message: `Processed ${addedCount} additions and ${removedCount} removals`
69
+ message: 'User branches retrieved successfully',
70
+ data: permissions.map((p)=>({
71
+ id: p.id,
72
+ userId: p.userId,
73
+ branchId: p.branch?.id || p.targetId,
74
+ branchName: p.branch?.name || '',
75
+ branchSlug: p.branch?.slug || '',
76
+ companyId: p.branch?.companyId || ''
77
+ }))
97
78
  };
98
79
  }
99
- async getUserBranches(userId) {
100
- const permissions = await this.userPermissionService.findUserBranches(userId);
101
- const data = permissions.map((permission)=>({
102
- id: permission.id,
103
- userId: permission.userId,
104
- branchId: permission.branch?.id || permission.targetId,
105
- branchName: permission.branch?.name || '',
106
- branchSlug: permission.branch?.slug || '',
107
- companyId: permission.branch?.companyId || ''
108
- }));
80
+ /** Process batch permission assignments/revocations */ async processBatchPermissions(userId, items, type) {
81
+ let added = 0, removed = 0;
82
+ for (const item of items){
83
+ if (item.isAdd) {
84
+ await this.permissionService.assignPermission(userId, item.targetId, type);
85
+ added++;
86
+ } else {
87
+ await this.permissionService.revokePermission(userId, item.targetId, type);
88
+ removed++;
89
+ }
90
+ }
109
91
  return {
110
92
  success: true,
111
- message: 'User branches retrieved successfully',
112
- data
93
+ message: `Processed ${added} additions and ${removed} removals`
113
94
  };
114
95
  }
115
- constructor(userPermissionService){
116
- _define_property(this, "userPermissionService", void 0);
117
- this.userPermissionService = userPermissionService;
96
+ constructor(permissionService){
97
+ _define_property(this, "permissionService", void 0);
98
+ this.permissionService = permissionService;
118
99
  }
119
100
  };
120
101
  _ts_decorate([
121
102
  (0, _common.Post)('user-company/assign'),
122
103
  (0, _nestjsshared.RequirePermission)(_nestjsshared.USER_PERMISSIONS.UPDATE),
123
104
  (0, _swagger.ApiOperation)({
124
- summary: 'Batch assign/revoke user-company permissions',
125
- description: `
126
- Batch operation to assign or revoke user permissions to companies.
127
-
128
- **Example: Add company permissions**
129
- \`\`\`json
130
- {
131
- "userId": "user-id",
132
- "items": [
133
- { "targetId": "company-id-1", "isAdd": true },
134
- { "targetId": "company-id-2", "isAdd": true }
135
- ]
136
- }
137
- \`\`\`
138
-
139
- **Example: Remove company permissions**
140
- \`\`\`json
141
- {
142
- "userId": "user-id",
143
- "items": [
144
- { "targetId": "company-id-1", "isAdd": false },
145
- { "targetId": "company-id-2", "isAdd": false }
146
- ]
147
- }
148
- \`\`\`
149
-
150
- **Example: Mix add and remove**
151
- \`\`\`json
152
- {
153
- "userId": "user-id",
154
- "items": [
155
- { "targetId": "company-id-1", "isAdd": true },
156
- { "targetId": "company-id-2", "isAdd": false }
157
- ]
158
- }
159
- \`\`\`
160
- `
105
+ summary: 'Batch assign/revoke user-company permissions'
161
106
  }),
162
107
  (0, _swagger.ApiResponse)({
163
108
  status: 200,
@@ -177,8 +122,7 @@ _ts_decorate([
177
122
  (0, _common.Post)('get-user-company'),
178
123
  (0, _nestjsshared.RequirePermission)(_nestjsshared.USER_PERMISSIONS.READ),
179
124
  (0, _swagger.ApiOperation)({
180
- summary: 'Get user companies',
181
- description: 'Returns all companies the user has access to.'
125
+ summary: 'Get user companies'
182
126
  }),
183
127
  (0, _swagger.ApiBody)({
184
128
  schema: {
@@ -207,43 +151,7 @@ _ts_decorate([
207
151
  (0, _common.Post)('user-branch/assign'),
208
152
  (0, _nestjsshared.RequirePermission)(_nestjsshared.USER_PERMISSIONS.UPDATE),
209
153
  (0, _swagger.ApiOperation)({
210
- summary: 'Batch assign/revoke user-branch permissions',
211
- description: `
212
- Batch operation to assign or revoke user permissions to branches.
213
-
214
- **Example: Add branch permissions**
215
- \`\`\`json
216
- {
217
- "userId": "user-id",
218
- "items": [
219
- { "targetId": "branch-id-1", "isAdd": true },
220
- { "targetId": "branch-id-2", "isAdd": true }
221
- ]
222
- }
223
- \`\`\`
224
-
225
- **Example: Remove branch permissions**
226
- \`\`\`json
227
- {
228
- "userId": "user-id",
229
- "items": [
230
- { "targetId": "branch-id-1", "isAdd": false },
231
- { "targetId": "branch-id-2", "isAdd": false }
232
- ]
233
- }
234
- \`\`\`
235
-
236
- **Example: Mix add and remove**
237
- \`\`\`json
238
- {
239
- "userId": "user-id",
240
- "items": [
241
- { "targetId": "branch-id-1", "isAdd": true },
242
- { "targetId": "branch-id-2", "isAdd": false }
243
- ]
244
- }
245
- \`\`\`
246
- `
154
+ summary: 'Batch assign/revoke user-branch permissions'
247
155
  }),
248
156
  (0, _swagger.ApiResponse)({
249
157
  status: 200,
@@ -263,14 +171,17 @@ _ts_decorate([
263
171
  (0, _common.Post)('get-user-branch'),
264
172
  (0, _nestjsshared.RequirePermission)(_nestjsshared.USER_PERMISSIONS.READ),
265
173
  (0, _swagger.ApiOperation)({
266
- summary: 'Get user branches',
267
- description: 'Returns all branches the user has access to.'
174
+ summary: 'Get user branches'
268
175
  }),
269
176
  (0, _swagger.ApiBody)({
270
177
  schema: {
271
178
  properties: {
272
179
  userId: {
273
180
  type: 'string'
181
+ },
182
+ companyId: {
183
+ type: 'string',
184
+ description: 'Optional company ID to filter branches'
274
185
  }
275
186
  },
276
187
  required: [
@@ -283,8 +194,10 @@ _ts_decorate([
283
194
  type: _userpermissiondto.UserBranchesResponseDto
284
195
  }),
285
196
  _ts_param(0, (0, _common.Body)('userId')),
197
+ _ts_param(1, (0, _common.Body)('companyId')),
286
198
  _ts_metadata("design:type", Function),
287
199
  _ts_metadata("design:paramtypes", [
200
+ String,
288
201
  String
289
202
  ]),
290
203
  _ts_metadata("design:returntype", Promise)
@@ -14,6 +14,16 @@ Object.defineProperty(exports, "authSwaggerConfig", {
14
14
  'User Permissions',
15
15
  'Company Selection'
16
16
  ];
17
+ /** Examples to exclude when company feature is disabled */ const COMPANY_EXAMPLE_EXCLUSIONS = [
18
+ {
19
+ pathPattern: '/auth/login',
20
+ method: 'post',
21
+ examples: [
22
+ 'loginSuccessWithCompany',
23
+ 'companySelection'
24
+ ]
25
+ }
26
+ ];
17
27
  /**
18
28
  * Schema properties to exclude when company feature is disabled
19
29
  *
@@ -58,16 +68,14 @@ Object.defineProperty(exports, "authSwaggerConfig", {
58
68
  schemaName: 'RegistrationResponseDto',
59
69
  properties: [
60
70
  'company',
61
- 'branch',
62
- 'companyFeatureEnabled'
71
+ 'branch'
63
72
  ]
64
73
  },
65
74
  {
66
75
  schemaName: 'LoginResponseDto',
67
76
  properties: [
68
77
  'company',
69
- 'branch',
70
- 'companyFeatureEnabled'
78
+ 'branch'
71
79
  ]
72
80
  },
73
81
  {
@@ -102,7 +110,6 @@ Object.defineProperty(exports, "authSwaggerConfig", {
102
110
  'id',
103
111
  'name',
104
112
  'slug',
105
- 'isActive',
106
113
  'logoId'
107
114
  ]
108
115
  },
@@ -112,7 +119,6 @@ Object.defineProperty(exports, "authSwaggerConfig", {
112
119
  'id',
113
120
  'name',
114
121
  'slug',
115
- 'isActive',
116
122
  'logoId',
117
123
  'branches'
118
124
  ]
@@ -404,6 +410,7 @@ POST /auth/login → { accessToken, refreshToken, user }
404
410
  path: 'api/docs/auth',
405
411
  bearerAuth: true,
406
412
  excludeTags,
407
- excludeSchemaProperties: enableCompanyFeature ? undefined : COMPANY_SCHEMA_EXCLUSIONS
413
+ excludeSchemaProperties: enableCompanyFeature ? undefined : COMPANY_SCHEMA_EXCLUSIONS,
414
+ excludeExamples: enableCompanyFeature ? undefined : COMPANY_EXAMPLE_EXCLUSIONS
408
415
  };
409
416
  }
@@ -431,7 +431,6 @@ let BranchSelectionInfoDto = class BranchSelectionInfoDto {
431
431
  _define_property(this, "id", void 0);
432
432
  _define_property(this, "name", void 0);
433
433
  _define_property(this, "slug", void 0);
434
- _define_property(this, "isActive", void 0);
435
434
  _define_property(this, "logoId", void 0);
436
435
  }
437
436
  };
@@ -453,12 +452,6 @@ _ts_decorate([
453
452
  }),
454
453
  _ts_metadata("design:type", String)
455
454
  ], BranchSelectionInfoDto.prototype, "slug", void 0);
456
- _ts_decorate([
457
- (0, _swagger.ApiProperty)({
458
- example: true
459
- }),
460
- _ts_metadata("design:type", Boolean)
461
- ], BranchSelectionInfoDto.prototype, "isActive", void 0);
462
455
  _ts_decorate([
463
456
  (0, _swagger.ApiPropertyOptional)({
464
457
  example: '550e8400-e29b-41d4-a716-446655440077',
@@ -472,7 +465,6 @@ let CompanyWithBranchesDto = class CompanyWithBranchesDto {
472
465
  _define_property(this, "id", void 0);
473
466
  _define_property(this, "name", void 0);
474
467
  _define_property(this, "slug", void 0);
475
- _define_property(this, "isActive", void 0);
476
468
  _define_property(this, "logoId", void 0);
477
469
  _define_property(this, "branches", void 0);
478
470
  }
@@ -495,12 +487,6 @@ _ts_decorate([
495
487
  }),
496
488
  _ts_metadata("design:type", String)
497
489
  ], CompanyWithBranchesDto.prototype, "slug", void 0);
498
- _ts_decorate([
499
- (0, _swagger.ApiProperty)({
500
- example: true
501
- }),
502
- _ts_metadata("design:type", Boolean)
503
- ], CompanyWithBranchesDto.prototype, "isActive", void 0);
504
490
  _ts_decorate([
505
491
  (0, _swagger.ApiPropertyOptional)({
506
492
  example: '550e8400-e29b-41d4-a716-446655440088',
@@ -525,7 +511,6 @@ let LoginResponseDto = class LoginResponseDto {
525
511
  _define_property(this, "user", void 0);
526
512
  _define_property(this, "company", void 0);
527
513
  _define_property(this, "branch", void 0);
528
- _define_property(this, "companyFeatureEnabled", void 0);
529
514
  }
530
515
  };
531
516
  _ts_decorate([
@@ -561,13 +546,6 @@ _ts_decorate([
561
546
  }),
562
547
  _ts_metadata("design:type", typeof BranchInfoDto === "undefined" ? Object : BranchInfoDto)
563
548
  ], LoginResponseDto.prototype, "branch", void 0);
564
- _ts_decorate([
565
- (0, _swagger.ApiPropertyOptional)({
566
- example: true,
567
- description: 'Whether company feature is enabled'
568
- }),
569
- _ts_metadata("design:type", Boolean)
570
- ], LoginResponseDto.prototype, "companyFeatureEnabled", void 0);
571
549
  let RegistrationResponseDto = class RegistrationResponseDto {
572
550
  constructor(){
573
551
  _define_property(this, "accessToken", void 0);
@@ -575,7 +553,6 @@ let RegistrationResponseDto = class RegistrationResponseDto {
575
553
  _define_property(this, "user", void 0);
576
554
  _define_property(this, "company", void 0);
577
555
  _define_property(this, "branch", void 0);
578
- _define_property(this, "companyFeatureEnabled", void 0);
579
556
  _define_property(this, "requiresEmailVerification", void 0);
580
557
  }
581
558
  };
@@ -612,13 +589,6 @@ _ts_decorate([
612
589
  }),
613
590
  _ts_metadata("design:type", typeof BranchInfoDto === "undefined" ? Object : BranchInfoDto)
614
591
  ], RegistrationResponseDto.prototype, "branch", void 0);
615
- _ts_decorate([
616
- (0, _swagger.ApiPropertyOptional)({
617
- example: true,
618
- description: 'Whether company feature is enabled'
619
- }),
620
- _ts_metadata("design:type", Boolean)
621
- ], RegistrationResponseDto.prototype, "companyFeatureEnabled", void 0);
622
592
  _ts_decorate([
623
593
  (0, _swagger.ApiPropertyOptional)({
624
594
  example: true,
package/cjs/dtos/index.js CHANGED
@@ -5,7 +5,6 @@ Object.defineProperty(exports, "__esModule", {
5
5
  _export_star(require("./authentication.dto"), exports);
6
6
  _export_star(require("./company-branch.dto"), exports);
7
7
  _export_star(require("./company.dto"), exports);
8
- _export_star(require("./user-company-permission.dto"), exports);
9
8
  _export_star(require("./user.dto"), exports);
10
9
  _export_star(require("./user-permission.dto"), exports);
11
10
  function _export_star(from, to) {