@flusys/nestjs-auth 0.1.0-beta.3 → 1.0.0-beta

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 (38) hide show
  1. package/README.md +1 -11
  2. package/cjs/config/auth.constants.js +10 -4
  3. package/cjs/controllers/authentication.controller.js +7 -32
  4. package/cjs/controllers/branch.controller.js +3 -4
  5. package/cjs/controllers/company.controller.js +3 -4
  6. package/cjs/controllers/user-permission.controller.js +6 -18
  7. package/cjs/controllers/user.controller.js +17 -22
  8. package/cjs/interfaces/authentication.interface.js +0 -3
  9. package/cjs/services/auth-config.service.js +18 -44
  10. package/cjs/services/auth-datasource.provider.js +13 -31
  11. package/cjs/services/authentication.service.js +80 -85
  12. package/cjs/services/branch.service.js +10 -44
  13. package/cjs/services/company.service.js +7 -36
  14. package/cjs/services/user-permission.service.js +9 -27
  15. package/cjs/services/user.service.js +33 -91
  16. package/cjs/strategies/jwt.strategy.js +14 -1
  17. package/config/auth.constants.d.ts +2 -0
  18. package/fesm/config/auth.constants.js +7 -8
  19. package/fesm/controllers/authentication.controller.js +7 -32
  20. package/fesm/controllers/branch.controller.js +5 -6
  21. package/fesm/controllers/company.controller.js +5 -6
  22. package/fesm/controllers/user-permission.controller.js +6 -18
  23. package/fesm/controllers/user.controller.js +17 -22
  24. package/fesm/dtos/authentication.dto.js +17 -97
  25. package/fesm/interfaces/authentication.interface.js +1 -7
  26. package/fesm/services/auth-config.service.js +18 -44
  27. package/fesm/services/auth-datasource.provider.js +13 -31
  28. package/fesm/services/authentication.service.js +78 -83
  29. package/fesm/services/branch.service.js +11 -45
  30. package/fesm/services/company.service.js +8 -37
  31. package/fesm/services/user-permission.service.js +9 -27
  32. package/fesm/services/user.service.js +34 -92
  33. package/fesm/strategies/jwt.strategy.js +14 -1
  34. package/package.json +3 -3
  35. package/services/authentication.service.d.ts +6 -2
  36. package/services/branch.service.d.ts +2 -5
  37. package/services/company.service.d.ts +1 -4
  38. package/services/user.service.d.ts +1 -3
@@ -15,6 +15,7 @@ const _common = require("@nestjs/common");
15
15
  const _bcrypt = /*#__PURE__*/ _interop_require_wildcard(require("bcrypt"));
16
16
  const _authconfigservice = require("./auth-config.service");
17
17
  const _authdatasourceprovider = require("./auth-datasource.provider");
18
+ const _config = require("../config");
18
19
  const _enums = require("../enums");
19
20
  const _usercompanypermissionentity = require("../entities/user-company-permission.entity");
20
21
  const _userentity = require("../entities/user.entity");
@@ -87,22 +88,13 @@ function _ts_param(paramIndex, decorator) {
87
88
  };
88
89
  }
89
90
  let UserService = class UserService extends _classes.RequestScopedApiService {
90
- /**
91
- * Resolve entity class for this service
92
- * @returns User entity class
93
- */ resolveEntity() {
91
+ resolveEntity() {
94
92
  return _userentity.User;
95
93
  }
96
- /**
97
- * Get DataSource provider for this service
98
- * @returns AuthDataSourceProvider instance
99
- */ getDataSourceProvider() {
94
+ getDataSourceProvider() {
100
95
  return this.dataSourceProvider;
101
96
  }
102
- /**
103
- * Override ensureRepositoryInitialized to also initialize permission repository and dataSource
104
- * CRITICAL: Also initializes permissionRepository and dataSource for company feature support
105
- */ async ensureRepositoryInitialized() {
97
+ async ensureRepositoryInitialized() {
106
98
  await super.ensureRepositoryInitialized();
107
99
  // Initialize permission repository if company feature is enabled
108
100
  const isCompanyFeatureEnabled = this.authConfig.isCompanyFeatureEnabled();
@@ -116,26 +108,8 @@ let UserService = class UserService extends _classes.RequestScopedApiService {
116
108
  this.dataSource = await this.getDataSourceForService();
117
109
  }
118
110
  }
119
- // ==========================================================================
120
- // CUSTOM METHODS (Beyond RequestScopedApiService)
121
- // ==========================================================================
122
- /**
123
- * Update last login timestamp
124
- */ async updateLastLogin(id) {
125
- // Ensure repository is initialized for custom method
126
- await this.ensureRepositoryInitialized();
127
- await this.repository.update(id, {
128
- lastLoginAt: new Date()
129
- });
130
- await this.clearCacheForId([
131
- {
132
- id
133
- }
134
- ]);
135
- }
136
- /**
137
- * Verify email
138
- */ async verifyEmail(id) {
111
+ // Custom Methods
112
+ /** Verify email */ async verifyEmail(id) {
139
113
  // Ensure repository is initialized for custom method
140
114
  await this.ensureRepositoryInitialized();
141
115
  await this.repository.update(id, {
@@ -148,9 +122,7 @@ let UserService = class UserService extends _classes.RequestScopedApiService {
148
122
  }
149
123
  ]);
150
124
  }
151
- /**
152
- * Verify phone
153
- */ async verifyPhone(id) {
125
+ /** Verify phone */ async verifyPhone(id) {
154
126
  // Ensure repository is initialized for custom method
155
127
  await this.ensureRepositoryInitialized();
156
128
  await this.repository.update(id, {
@@ -163,12 +135,7 @@ let UserService = class UserService extends _classes.RequestScopedApiService {
163
135
  }
164
136
  ]);
165
137
  }
166
- /**
167
- * Update user status
168
- *
169
- * When company feature is disabled: Updates User.isActive directly
170
- * When company feature is enabled: Updates UserCompanyPermission.isActive for the logged user's company
171
- */ async updateStatus(id, isActive, user) {
138
+ /** Update user status. When company feature enabled, updates permission isActive for logged user's company. */ async updateStatus(id, isActive, user) {
172
139
  // Ensure repository is initialized for custom method
173
140
  await this.ensureRepositoryInitialized();
174
141
  const isCompanyFeatureEnabled = this.authConfig.isCompanyFeatureEnabled();
@@ -199,50 +166,43 @@ let UserService = class UserService extends _classes.RequestScopedApiService {
199
166
  }
200
167
  ]);
201
168
  }
202
- // ==========================================================================
203
- // APISERVICE OVERRIDES (Customize behavior)
204
- // ==========================================================================
205
- /**
206
- * Override: Convert DTO to entity (hash password before saving)
207
- */ async convertSingleDtoToEntity(dto, user) {
169
+ // ApiService Overrides
170
+ /** Convert DTO to entity (hash password before saving) */ async convertSingleDtoToEntity(dto, user) {
208
171
  // Repository initialization is handled automatically by RequestScopedApiService
209
172
  const entity = await super.convertSingleDtoToEntity(dto, user);
210
173
  // Hash password if provided
211
174
  if (dto.password) {
212
- entity.password = await _bcrypt.hash(dto.password, 10);
175
+ entity.password = await _bcrypt.hash(dto.password, _config.BCRYPT_SALT_ROUNDS);
213
176
  }
214
177
  return entity;
215
178
  }
216
- /**
217
- * Override: Convert entity to response DTO (remove password!)
218
- *
219
- * When company feature is enabled and raw mode is used, isActive comes from
220
- * the permission table (user_companyIsActive). Otherwise, it comes from User entity.
221
- */ convertEntityToResponseDto(entity, isRaw) {
179
+ /** Convert entity to response DTO (removes password). In raw mode with company feature, isActive comes from permission table. */ convertEntityToResponseDto(entity, isRaw) {
222
180
  // When raw mode is used with company feature, isActive comes from computed field
223
- const isActive = isRaw && entity.user_companyIsActive !== undefined ? Boolean(entity.user_companyIsActive) : entity.isActive;
181
+ // Raw mode uses snake_case column names (due to SnakeNamingStrategy)
182
+ const isActive = isRaw && entity.user_companyIsActive !== undefined ? Boolean(entity.user_companyIsActive) : isRaw ? entity.user_is_active : entity.isActive;
224
183
  return {
225
184
  id: isRaw ? entity.user_id : entity.id,
226
185
  name: isRaw ? entity.user_name : entity.name,
227
186
  phone: isRaw ? entity.user_phone : entity.phone,
228
187
  email: isRaw ? entity.user_email : entity.email,
229
- profilePictureId: isRaw ? entity.user_profilePictureId : entity.profilePictureId,
188
+ profilePictureId: isRaw ? entity.user_profile_picture_id : entity.profilePictureId,
230
189
  isActive,
231
- emailVerified: isRaw ? entity.user_emailVerified : entity.emailVerified,
232
- phoneVerified: isRaw ? entity.user_phoneVerified : entity.phoneVerified,
233
- lastLoginAt: isRaw ? entity.user_lastLoginAt : entity.lastLoginAt,
234
- additionalFields: isRaw ? entity.user_additionalFields : entity.additionalFields,
235
- createdAt: isRaw ? entity.user_createdAt : entity.createdAt,
236
- updatedAt: isRaw ? entity.user_updatedAt : entity.updatedAt,
237
- deletedAt: isRaw ? entity.user_deletedAt : entity.deletedAt,
238
- createdById: isRaw ? entity.user_createdById : entity.createdById,
239
- updatedById: isRaw ? entity.user_updatedById : entity.updatedById,
240
- deletedById: isRaw ? entity.user_deletedById : entity.deletedById
190
+ emailVerified: isRaw ? entity.user_email_verified : entity.emailVerified,
191
+ phoneVerified: isRaw ? entity.user_phone_verified : entity.phoneVerified,
192
+ lastLoginAt: isRaw ? entity.user_last_login_at : entity.lastLoginAt,
193
+ additionalFields: isRaw ? entity.user_additional_fields : entity.additionalFields,
194
+ createdAt: isRaw ? entity.user_created_at : entity.createdAt,
195
+ updatedAt: isRaw ? entity.user_updated_at : entity.updatedAt,
196
+ deletedAt: isRaw ? entity.user_deleted_at : entity.deletedAt,
197
+ createdById: isRaw ? entity.user_created_by_id : entity.createdById,
198
+ updatedById: isRaw ? entity.user_updated_by_id : entity.updatedById,
199
+ deletedById: isRaw ? entity.user_deleted_by_id : entity.deletedById
241
200
  };
242
201
  }
243
- /**
244
- * Override: Global search - search by name, email, or phone
245
- */ async getGlobalSearchQuery(query, search, _user) {
202
+ /** Convert entity list to response DTO list */ convertEntityListToResponseListDto(entities, isRaw) {
203
+ return entities.map((entity)=>this.convertEntityToResponseDto(entity, isRaw));
204
+ }
205
+ /** Global search - search by name, email, or phone */ async getGlobalSearchQuery(query, search, _user) {
246
206
  query.andWhere('(user.name LIKE :search OR user.email LIKE :search OR user.phone LIKE :search)', {
247
207
  search: `%${search}%`
248
208
  });
@@ -251,16 +211,7 @@ let UserService = class UserService extends _classes.RequestScopedApiService {
251
211
  isRaw: false
252
212
  };
253
213
  }
254
- /**
255
- * Override: getExtraManipulateQuery - Add company permission-based isActive check when company feature enabled
256
- *
257
- * Note: When company feature is disabled at bootstrap, this method returns without modifications.
258
- * All company-related filtering is skipped, and users are returned normally with isActive from User entity.
259
- *
260
- * When company feature is enabled:
261
- * - isActive is computed from UserCompanyPermission table
262
- * - Returns isRaw: true to use raw query results
263
- */ async getExtraManipulateQuery(query, filterAndPaginationDto, user) {
214
+ /** Add company permission-based isActive check when company feature enabled. Returns isRaw: true for computed fields. */ async getExtraManipulateQuery(query, filterAndPaginationDto, user) {
264
215
  // Repository initialization is handled automatically by RequestScopedApiService
265
216
  const result = await super.getExtraManipulateQuery(query, filterAndPaginationDto, user);
266
217
  // Only apply company filtering if:
@@ -315,12 +266,7 @@ let UserService = class UserService extends _classes.RequestScopedApiService {
315
266
  }
316
267
  return result;
317
268
  }
318
- /**
319
- * Override: insert - Create company permission when company feature is enabled
320
- *
321
- * Note: When company feature is disabled at bootstrap, this method falls back to parent implementation.
322
- * No company permissions are created, and user is inserted normally.
323
- */ async insert(dto, user) {
269
+ /** Insert user. Creates company permission when company feature is enabled. */ async insert(dto, user) {
324
270
  // Repository initialization is handled automatically by RequestScopedApiService
325
271
  // Check if company feature is enabled
326
272
  const isCompanyFeatureEnabled = this.authConfig.isCompanyFeatureEnabled();
@@ -387,9 +333,7 @@ let UserService = class UserService extends _classes.RequestScopedApiService {
387
333
  await queryRunner.release();
388
334
  }
389
335
  }
390
- /**
391
- * Update user profile with password handling
392
- */ async profile(dto, user) {
336
+ /** Update user profile with password handling */ async profile(dto, user) {
393
337
  // Repository initialization is handled automatically by RequestScopedApiService
394
338
  if (!this.dataSource) {
395
339
  throw new _common.BadRequestException('DataSource not available');
@@ -436,10 +380,8 @@ let UserService = class UserService extends _classes.RequestScopedApiService {
436
380
  await queryRunner.release();
437
381
  }
438
382
  }
439
- // NOTE: @Inject() required for bundled code - type metadata may be lost during esbuild
440
383
  constructor(cacheManager, utilsService, dataSourceProvider, authConfig){
441
- // Repository will be set asynchronously by RequestScopedApiService
442
- super('user', null, cacheManager, utilsService, UserService.name, true), _define_property(this, "cacheManager", void 0), _define_property(this, "utilsService", void 0), _define_property(this, "dataSourceProvider", void 0), _define_property(this, "authConfig", void 0), _define_property(this, "logger", void 0), _define_property(this, "permissionRepository", void 0), _define_property(this, "dataSource", void 0), this.cacheManager = cacheManager, this.utilsService = utilsService, this.dataSourceProvider = dataSourceProvider, this.authConfig = authConfig, this.logger = new _common.Logger(UserService.name);
384
+ super('user', null, cacheManager, utilsService, UserService.name, true), _define_property(this, "cacheManager", void 0), _define_property(this, "utilsService", void 0), _define_property(this, "dataSourceProvider", void 0), _define_property(this, "authConfig", void 0), _define_property(this, "permissionRepository", void 0), _define_property(this, "dataSource", void 0), this.cacheManager = cacheManager, this.utilsService = utilsService, this.dataSourceProvider = dataSourceProvider, this.authConfig = authConfig;
443
385
  }
444
386
  };
445
387
  UserService = _ts_decorate([
@@ -14,6 +14,7 @@ const _passport = require("@nestjs/passport");
14
14
  const _passportjwt = require("passport-jwt");
15
15
  const _authconfigservice = require("../services/auth-config.service");
16
16
  const _authdatasourceprovider = require("../services/auth-datasource.provider");
17
+ const _authenticationservice = require("../services/authentication.service");
17
18
  const _userentity = require("../entities/user.entity");
18
19
  function _define_property(obj, key, value) {
19
20
  if (key in obj) {
@@ -44,8 +45,9 @@ function _ts_metadata(k, v) {
44
45
  }
45
46
  let JwtStrategy = class JwtStrategy extends (0, _passport.PassportStrategy)(_passportjwt.Strategy, 'jwt') {
46
47
  async validate(_req, payload) {
47
- // Resolve request-scoped AuthDataSourceProvider for this request
48
+ // Resolve request-scoped services for this request
48
49
  let userRepository = null;
50
+ let authService = null;
49
51
  try {
50
52
  const dataSourceProvider = await this.moduleRef.resolve(_authdatasourceprovider.AuthDataSourceProvider, undefined, {
51
53
  strict: false
@@ -53,12 +55,23 @@ let JwtStrategy = class JwtStrategy extends (0, _passport.PassportStrategy)(_pas
53
55
  if (dataSourceProvider) {
54
56
  userRepository = await dataSourceProvider.getRepository(_userentity.User);
55
57
  }
58
+ // Resolve AuthenticationService for token revocation check
59
+ authService = await this.moduleRef.resolve(_authenticationservice.AuthenticationService, undefined, {
60
+ strict: false
61
+ });
56
62
  } catch (error) {
57
63
  throw new _common.UnauthorizedException('Unable to access user data');
58
64
  }
59
65
  if (!userRepository) {
60
66
  throw new _common.UnauthorizedException('User repository not available');
61
67
  }
68
+ // Check if token is revoked (logged out)
69
+ if (authService && payload.iat) {
70
+ const isRevoked = await authService.isTokenRevoked(payload.id, payload.iat);
71
+ if (isRevoked) {
72
+ throw new _common.UnauthorizedException('Token has been revoked');
73
+ }
74
+ }
62
75
  // Find user and check if active
63
76
  const user = await userRepository.findOne({
64
77
  where: {
@@ -1,2 +1,4 @@
1
1
  export declare const AUTH_MODULE_OPTIONS = "AUTH_MODULE_OPTIONS";
2
+ export declare const BCRYPT_SALT_ROUNDS = 12;
2
3
  export declare const SESSION_CACHE_PREFIX = "auth:session";
4
+ export declare const TOKEN_REVOKED_PREFIX = "auth:revoked";
@@ -1,8 +1,7 @@
1
- // =============================================================================
2
- // INJECTION TOKENS
3
- // =============================================================================
4
- /** Injection token for auth module options */ export const AUTH_MODULE_OPTIONS = 'AUTH_MODULE_OPTIONS';
5
- // =============================================================================
6
- // CACHE KEY PREFIXES (Auth-specific)
7
- // =============================================================================
8
- /** Cache key prefix for authentication sessions */ export const SESSION_CACHE_PREFIX = 'auth:session';
1
+ // Injection Tokens
2
+ export const AUTH_MODULE_OPTIONS = 'AUTH_MODULE_OPTIONS';
3
+ // Security Configuration
4
+ /** Bcrypt salt rounds (12 = ~250ms hashing time) */ export const BCRYPT_SALT_ROUNDS = 12;
5
+ // Cache Key Prefixes
6
+ export const SESSION_CACHE_PREFIX = 'auth:session';
7
+ export const TOKEN_REVOKED_PREFIX = 'auth:revoked';
@@ -37,37 +37,22 @@ import { SetToken } from '../interceptors/set-token.interceptor';
37
37
  import { AuthConfigService } from '../services/auth-config.service';
38
38
  import { AuthenticationService } from '../services/authentication.service';
39
39
  export class AuthenticationController {
40
- // ==========================================================================
41
- // CORE ENDPOINTS (Always available)
42
- // ==========================================================================
43
- /**
44
- * Login
45
- * Returns either tokens directly or company/branch selection requirement
46
- * Browser: refreshToken set in HTTP-only cookie, not in response body
47
- * API/Mobile: refreshToken included in response body
48
- */ async login(loginDto) {
40
+ // Core Endpoints
41
+ /** Login - Returns tokens or company/branch selection requirement */ async login(loginDto) {
49
42
  const result = await this.authService.login(loginDto.email, loginDto.password);
50
43
  if ('requiresSelection' in result) {
51
44
  return result;
52
45
  }
53
46
  return result;
54
47
  }
55
- /**
56
- * Register new user
57
- * If company feature enabled, can optionally join/create company
58
- * Browser: refreshToken set in HTTP-only cookie
59
- */ async register(registrationDto) {
48
+ /** Register new user. If company feature enabled, can join/create company. */ async register(registrationDto) {
60
49
  const result = await this.authService.register(registrationDto);
61
50
  return {
62
51
  ...result,
63
52
  companyFeatureEnabled: this.authConfig?.isCompanyFeatureEnabled() ?? false
64
53
  };
65
54
  }
66
- /**
67
- * Refresh access token
68
- * Browser: Gets refreshToken from HTTP-only cookie
69
- * API/Mobile: Gets refreshToken from request body
70
- */ async refreshToken(req, refreshTokenDto) {
55
+ /** Refresh access token. Browser uses HTTP-only cookie, API/Mobile uses request body. */ async refreshToken(req, refreshTokenDto) {
71
56
  // Get refresh token from cookie (browser) or body (API/mobile)
72
57
  const cookieName = this.authConfig?.getRefreshTokenCookieName() ?? 'fsn_refresh_token';
73
58
  const refreshToken = req.cookies?.[cookieName] || refreshTokenDto.refreshToken;
@@ -76,26 +61,16 @@ export class AuthenticationController {
76
61
  }
77
62
  return this.authService.refreshToken(refreshToken);
78
63
  }
79
- /**
80
- * Get current user info
81
- * Returns only user, company, and branch data (no tokens)
82
- * Uses existing access token from Authorization header
83
- * Company/branch fields are automatically excluded from Swagger when company feature is disabled
84
- */ async getCurrentUser(user) {
64
+ /** Get current user info. Returns user, company, and branch data (no tokens). */ async getCurrentUser(user) {
85
65
  return this.authService.getUserInfo(user.id, user.companyId, user.branchId);
86
66
  }
87
- /**
88
- * Logout
89
- * Clears refresh token cookie for browsers
90
- */ async logout(userId) {
67
+ /** Logout - Clears refresh token cookie for browsers */ async logout(userId) {
91
68
  await this.authService.logout(userId);
92
69
  return {
93
70
  message: 'Logged out successfully'
94
71
  };
95
72
  }
96
- /**
97
- * Change password
98
- */ async changePassword(userId, dto) {
73
+ /** Change password */ async changePassword(userId, dto) {
99
74
  await this.authService.changePassword(userId, dto.currentPassword, dto.newPassword);
100
75
  return {
101
76
  message: 'Password changed successfully'
@@ -26,21 +26,20 @@ function _ts_param(paramIndex, decorator) {
26
26
  };
27
27
  }
28
28
  import { createApiController } from '@flusys/nestjs-shared/classes';
29
- import { Controller, Inject, UseGuards } from '@nestjs/common';
30
- import { ApiBearerAuth, ApiTags } from '@nestjs/swagger';
29
+ import { Controller, Inject } from '@nestjs/common';
30
+ import { ApiTags } from '@nestjs/swagger';
31
31
  import { CompanyBranchResponseDto, CreateCompanyBranchDto, UpdateCompanyBranchDto } from '../dtos/company-branch.dto';
32
- import { JwtAuthGuard } from '@flusys/nestjs-shared/guards';
33
32
  import { BranchService } from '../services/branch.service';
34
- export class BranchController extends createApiController(CreateCompanyBranchDto, UpdateCompanyBranchDto, CompanyBranchResponseDto) {
33
+ export class BranchController extends createApiController(CreateCompanyBranchDto, UpdateCompanyBranchDto, CompanyBranchResponseDto, {
34
+ security: 'jwt'
35
+ }) {
35
36
  constructor(branchService){
36
37
  super(branchService), _define_property(this, "branchService", void 0), this.branchService = branchService;
37
38
  }
38
39
  }
39
40
  BranchController = _ts_decorate([
40
41
  ApiTags('Branches'),
41
- ApiBearerAuth(),
42
42
  Controller('administration/branch'),
43
- UseGuards(JwtAuthGuard),
44
43
  _ts_param(0, Inject(BranchService)),
45
44
  _ts_metadata("design:type", Function),
46
45
  _ts_metadata("design:paramtypes", [
@@ -26,21 +26,20 @@ function _ts_param(paramIndex, decorator) {
26
26
  };
27
27
  }
28
28
  import { createApiController } from '@flusys/nestjs-shared/classes';
29
- import { Controller, Inject, UseGuards } from '@nestjs/common';
30
- import { ApiBearerAuth, ApiTags } from '@nestjs/swagger';
29
+ import { Controller, Inject } from '@nestjs/common';
30
+ import { ApiTags } from '@nestjs/swagger';
31
31
  import { CompanyResponseDto, CreateCompanyDto, UpdateCompanyDto } from '../dtos/company.dto';
32
- import { JwtAuthGuard } from '@flusys/nestjs-shared/guards';
33
32
  import { CompanyService } from '../services/company.service';
34
- export class CompanyController extends createApiController(CreateCompanyDto, UpdateCompanyDto, CompanyResponseDto) {
33
+ export class CompanyController extends createApiController(CreateCompanyDto, UpdateCompanyDto, CompanyResponseDto, {
34
+ security: 'jwt'
35
+ }) {
35
36
  constructor(companyService){
36
37
  super(companyService), _define_property(this, "companyService", void 0), this.companyService = companyService;
37
38
  }
38
39
  }
39
40
  CompanyController = _ts_decorate([
40
41
  ApiTags('Companies'),
41
- ApiBearerAuth(),
42
42
  Controller('administration/company'),
43
- UseGuards(JwtAuthGuard),
44
43
  _ts_param(0, Inject(CompanyService)),
45
44
  _ts_metadata("design:type", Function),
46
45
  _ts_metadata("design:paramtypes", [
@@ -31,12 +31,8 @@ import { JwtAuthGuard } from '@flusys/nestjs-shared/guards';
31
31
  import { AssignUserCompanyDto, AssignUserBranchDto, UserCompaniesResponseDto, UserBranchesResponseDto } from '../dtos/user-permission.dto';
32
32
  import { UserPermissionService } from '../services/user-permission.service';
33
33
  export class UserPermissionController {
34
- // ========================================================================
35
- // USER-COMPANY PERMISSIONS
36
- // ========================================================================
37
- /**
38
- * Batch assign/revoke user-company permissions
39
- */ async assignUserCompany(dto) {
34
+ // User-Company Permissions
35
+ /** Batch assign/revoke user-company permissions */ async assignUserCompany(dto) {
40
36
  let addedCount = 0;
41
37
  let removedCount = 0;
42
38
  for (const item of dto.items){
@@ -56,9 +52,7 @@ export class UserPermissionController {
56
52
  message: `Processed ${addedCount} additions and ${removedCount} removals`
57
53
  };
58
54
  }
59
- /**
60
- * Get user's companies
61
- */ async getUserCompanies(userId) {
55
+ /** Get user's companies */ async getUserCompanies(userId) {
62
56
  const permissions = await this.userPermissionService.findUserCompanies(userId);
63
57
  // Map to DTO format with populated company details
64
58
  const data = permissions.map((permission)=>({
@@ -72,12 +66,8 @@ export class UserPermissionController {
72
66
  data
73
67
  };
74
68
  }
75
- // ========================================================================
76
- // USER-BRANCH PERMISSIONS
77
- // ========================================================================
78
- /**
79
- * Batch assign/revoke user-branch permissions
80
- */ async assignUserBranch(dto) {
69
+ // User-Branch Permissions
70
+ /** Batch assign/revoke user-branch permissions */ async assignUserBranch(dto) {
81
71
  let addedCount = 0;
82
72
  let removedCount = 0;
83
73
  for (const item of dto.items){
@@ -97,9 +87,7 @@ export class UserPermissionController {
97
87
  message: `Processed ${addedCount} additions and ${removedCount} removals`
98
88
  };
99
89
  }
100
- /**
101
- * Get user's branches
102
- */ async getUserBranches(userId) {
90
+ /** Get user's branches */ async getUserBranches(userId) {
103
91
  const permissions = await this.userPermissionService.findUserBranches(userId);
104
92
  // Map to DTO format with populated branch details
105
93
  const data = permissions.map((permission)=>({
@@ -27,46 +27,35 @@ function _ts_param(paramIndex, decorator) {
27
27
  }
28
28
  import { createApiController } from '@flusys/nestjs-shared/classes';
29
29
  import { CurrentUser } from '@flusys/nestjs-shared/decorators';
30
+ import { JwtAuthGuard } from '@flusys/nestjs-shared/guards';
30
31
  import { ILoggedUserInfo } from '@flusys/nestjs-shared/interfaces';
31
32
  import { Body, Controller, Inject, Param, Post, Put, UseGuards } from '@nestjs/common';
32
33
  import { ApiBearerAuth, ApiBody, ApiOperation, ApiParam, ApiTags } from '@nestjs/swagger';
33
34
  import { CreateUserDto, UpdateUserDto, UserResponseDto } from '../dtos/user.dto';
34
- import { JwtAuthGuard } from '@flusys/nestjs-shared/guards';
35
35
  import { UserService } from '../services/user.service';
36
- export class UserController extends createApiController(CreateUserDto, UpdateUserDto, UserResponseDto) {
37
- // ==========================================================================
38
- // CUSTOM ENDPOINTS (Beyond standard CRUD)
39
- // ==========================================================================
40
- /**
41
- * Verify user email
42
- */ async verifyEmail(id) {
36
+ export class UserController extends createApiController(CreateUserDto, UpdateUserDto, UserResponseDto, {
37
+ security: 'jwt'
38
+ }) {
39
+ // Custom Endpoints
40
+ /** Verify user email */ async verifyEmail(id) {
43
41
  await this.service.verifyEmail(id);
44
42
  return {
45
43
  message: 'Email verified successfully'
46
44
  };
47
45
  }
48
- /**
49
- * Verify user phone
50
- */ async verifyPhone(id) {
46
+ /** Verify user phone */ async verifyPhone(id) {
51
47
  await this.service.verifyPhone(id);
52
48
  return {
53
49
  message: 'Phone verified successfully'
54
50
  };
55
51
  }
56
- /**
57
- * Update user active status
58
- *
59
- * When company feature is disabled: Updates User.isActive directly
60
- * When company feature is enabled: Updates UserCompanyPermission.isActive for logged user's company
61
- */ async updateStatus(id, isActive, user) {
52
+ /** Update user active status. When company feature enabled, updates permission isActive for logged user's company. */ async updateStatus(id, isActive, user) {
62
53
  await this.service.updateStatus(id, isActive, user);
63
54
  return {
64
55
  message: 'Status updated successfully'
65
56
  };
66
57
  }
67
- /**
68
- * Update user profile
69
- */ async profile(dto, user) {
58
+ /** Update user profile */ async profile(dto, user) {
70
59
  const data = await this.service.profile(dto, user);
71
60
  return {
72
61
  message: 'Profile updated successfully',
@@ -79,6 +68,8 @@ export class UserController extends createApiController(CreateUserDto, UpdateUse
79
68
  }
80
69
  _ts_decorate([
81
70
  Post(':id/verify-email'),
71
+ UseGuards(JwtAuthGuard),
72
+ ApiBearerAuth(),
82
73
  ApiOperation({
83
74
  summary: 'Verify user email'
84
75
  }),
@@ -95,6 +86,8 @@ _ts_decorate([
95
86
  ], UserController.prototype, "verifyEmail", null);
96
87
  _ts_decorate([
97
88
  Post(':id/verify-phone'),
89
+ UseGuards(JwtAuthGuard),
90
+ ApiBearerAuth(),
98
91
  ApiOperation({
99
92
  summary: 'Verify user phone'
100
93
  }),
@@ -111,6 +104,8 @@ _ts_decorate([
111
104
  ], UserController.prototype, "verifyPhone", null);
112
105
  _ts_decorate([
113
106
  Put(':id/status'),
107
+ UseGuards(JwtAuthGuard),
108
+ ApiBearerAuth(),
114
109
  ApiOperation({
115
110
  summary: 'Update user active status',
116
111
  description: 'Updates user active status. When company feature is enabled, updates the status for the current company context.'
@@ -139,6 +134,8 @@ _ts_decorate([
139
134
  ], UserController.prototype, "updateStatus", null);
140
135
  _ts_decorate([
141
136
  Post('profile'),
137
+ UseGuards(JwtAuthGuard),
138
+ ApiBearerAuth(),
142
139
  ApiOperation({
143
140
  summary: 'Update user profile'
144
141
  }),
@@ -156,9 +153,7 @@ _ts_decorate([
156
153
  ], UserController.prototype, "profile", null);
157
154
  UserController = _ts_decorate([
158
155
  ApiTags('Users'),
159
- ApiBearerAuth(),
160
156
  Controller('administration/users'),
161
- UseGuards(JwtAuthGuard),
162
157
  _ts_param(0, Inject(UserService)),
163
158
  _ts_metadata("design:type", Function),
164
159
  _ts_metadata("design:paramtypes", [