@flusys/nestjs-auth 0.1.0-beta.2 → 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.
- package/README.md +1 -11
- package/cjs/config/auth.constants.js +10 -4
- package/cjs/controllers/authentication.controller.js +7 -32
- package/cjs/controllers/branch.controller.js +3 -4
- package/cjs/controllers/company.controller.js +3 -4
- package/cjs/controllers/user-permission.controller.js +6 -18
- package/cjs/controllers/user.controller.js +17 -22
- package/cjs/interfaces/authentication.interface.js +0 -3
- package/cjs/services/auth-config.service.js +18 -44
- package/cjs/services/auth-datasource.provider.js +13 -31
- package/cjs/services/authentication.service.js +80 -85
- package/cjs/services/branch.service.js +10 -44
- package/cjs/services/company.service.js +7 -36
- package/cjs/services/user-permission.service.js +9 -27
- package/cjs/services/user.service.js +33 -91
- package/cjs/strategies/jwt.strategy.js +14 -1
- package/config/auth.constants.d.ts +2 -0
- package/fesm/config/auth.constants.js +7 -8
- package/fesm/controllers/authentication.controller.js +7 -32
- package/fesm/controllers/branch.controller.js +5 -6
- package/fesm/controllers/company.controller.js +5 -6
- package/fesm/controllers/user-permission.controller.js +6 -18
- package/fesm/controllers/user.controller.js +17 -22
- package/fesm/dtos/authentication.dto.js +17 -97
- package/fesm/interfaces/authentication.interface.js +1 -7
- package/fesm/services/auth-config.service.js +18 -44
- package/fesm/services/auth-datasource.provider.js +13 -31
- package/fesm/services/authentication.service.js +78 -83
- package/fesm/services/branch.service.js +11 -45
- package/fesm/services/company.service.js +8 -37
- package/fesm/services/user-permission.service.js +9 -27
- package/fesm/services/user.service.js +34 -92
- package/fesm/strategies/jwt.strategy.js +14 -1
- package/package.json +4 -4
- package/services/authentication.service.d.ts +6 -2
- package/services/branch.service.d.ts +2 -5
- package/services/company.service.d.ts +1 -4
- package/services/user.service.d.ts +1 -3
|
@@ -17,6 +17,8 @@ const _utils = require("@flusys/nestjs-shared/utils");
|
|
|
17
17
|
const _authconfigservice = require("./auth-config.service");
|
|
18
18
|
const _authdatasourceprovider = require("./auth-datasource.provider");
|
|
19
19
|
const _enums = require("../enums");
|
|
20
|
+
const _config = require("../config");
|
|
21
|
+
const _classes = require("@flusys/nestjs-shared/classes");
|
|
20
22
|
const _companybranchentity = require("../entities/company-branch.entity");
|
|
21
23
|
const _companyentity = require("../entities/company.entity");
|
|
22
24
|
const _usercompanypermissionentity = require("../entities/user-company-permission.entity");
|
|
@@ -90,12 +92,8 @@ function _ts_param(paramIndex, decorator) {
|
|
|
90
92
|
decorator(target, key, paramIndex);
|
|
91
93
|
};
|
|
92
94
|
}
|
|
93
|
-
// Password hashing configuration
|
|
94
|
-
const BCRYPT_SALT_ROUNDS = 12; // Increased from 10 for better security
|
|
95
95
|
let AuthenticationService = class AuthenticationService {
|
|
96
|
-
//
|
|
97
|
-
// REPOSITORY GETTERS
|
|
98
|
-
// ==========================================================================
|
|
96
|
+
// Repository Getters
|
|
99
97
|
async getUserRepository() {
|
|
100
98
|
if (this.dataSourceProvider) {
|
|
101
99
|
return this.dataSourceProvider.getRepository(_userentity.User);
|
|
@@ -126,13 +124,8 @@ let AuthenticationService = class AuthenticationService {
|
|
|
126
124
|
}
|
|
127
125
|
return this.injectedBranchRepository ?? null;
|
|
128
126
|
}
|
|
129
|
-
//
|
|
130
|
-
|
|
131
|
-
// ==========================================================================
|
|
132
|
-
/**
|
|
133
|
-
* Login with email and password
|
|
134
|
-
* Returns either tokens directly or requires company/branch selection
|
|
135
|
-
*/ async login(email, password) {
|
|
127
|
+
// Login
|
|
128
|
+
/** Login with email and password. Returns tokens or requires company/branch selection. */ async login(email, password) {
|
|
136
129
|
const user = await this.validateUser(email, password);
|
|
137
130
|
if (!user.isActive) {
|
|
138
131
|
throw new _common.UnauthorizedException('User account is deactivated');
|
|
@@ -143,9 +136,7 @@ let AuthenticationService = class AuthenticationService {
|
|
|
143
136
|
}
|
|
144
137
|
return this.handleCompanyBasedLogin(user);
|
|
145
138
|
}
|
|
146
|
-
/**
|
|
147
|
-
* Handle login when company feature is enabled
|
|
148
|
-
*/ async handleCompanyBasedLogin(user) {
|
|
139
|
+
/** Handle login when company feature is enabled */ async handleCompanyBasedLogin(user) {
|
|
149
140
|
const permissionRepository = await this.getPermissionRepository();
|
|
150
141
|
const branchRepository = await this.getBranchRepository();
|
|
151
142
|
if (!permissionRepository || !branchRepository) {
|
|
@@ -195,13 +186,8 @@ let AuthenticationService = class AuthenticationService {
|
|
|
195
186
|
// Returns all companies with their branches for frontend to display
|
|
196
187
|
return await this.generateCompanySelectionResponse(user, companies, branches);
|
|
197
188
|
}
|
|
198
|
-
//
|
|
199
|
-
|
|
200
|
-
// ==========================================================================
|
|
201
|
-
/**
|
|
202
|
-
* Register a new user
|
|
203
|
-
* If company feature enabled, optionally join/create company
|
|
204
|
-
*/ async register(dto) {
|
|
189
|
+
// Registration
|
|
190
|
+
/** Register a new user. If company feature enabled, optionally join/create company. */ async register(dto) {
|
|
205
191
|
const userRepository = await this.getUserRepository();
|
|
206
192
|
// Check if user exists
|
|
207
193
|
// Note: Generic error message to prevent email enumeration attacks
|
|
@@ -214,7 +200,7 @@ let AuthenticationService = class AuthenticationService {
|
|
|
214
200
|
throw new _common.BadRequestException('Registration failed. Please try again or contact support.');
|
|
215
201
|
}
|
|
216
202
|
// Create user
|
|
217
|
-
const hashedPassword = await _bcrypt.hash(dto.password, BCRYPT_SALT_ROUNDS);
|
|
203
|
+
const hashedPassword = await _bcrypt.hash(dto.password, _config.BCRYPT_SALT_ROUNDS);
|
|
218
204
|
const user = userRepository.create({
|
|
219
205
|
name: dto.name,
|
|
220
206
|
email: dto.email,
|
|
@@ -232,9 +218,7 @@ let AuthenticationService = class AuthenticationService {
|
|
|
232
218
|
// Handle company feature
|
|
233
219
|
return this.handleCompanyRegistration(user, dto);
|
|
234
220
|
}
|
|
235
|
-
/**
|
|
236
|
-
* Handle company-related registration logic
|
|
237
|
-
*/ async handleCompanyRegistration(user, dto) {
|
|
221
|
+
/** Handle company-related registration logic */ async handleCompanyRegistration(user, dto) {
|
|
238
222
|
const companyRepository = await this.getCompanyRepository();
|
|
239
223
|
const branchRepository = await this.getBranchRepository();
|
|
240
224
|
const permissionRepository = await this.getPermissionRepository();
|
|
@@ -331,18 +315,11 @@ let AuthenticationService = class AuthenticationService {
|
|
|
331
315
|
// No company assigned
|
|
332
316
|
return this.generateLoginResponse(user, true);
|
|
333
317
|
}
|
|
334
|
-
/**
|
|
335
|
-
* Generate URL-friendly slug from name
|
|
336
|
-
*/ generateSlug(name) {
|
|
318
|
+
/** Generate URL-friendly slug from name */ generateSlug(name) {
|
|
337
319
|
return name.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-+|-+$/g, '').substring(0, 100);
|
|
338
320
|
}
|
|
339
|
-
//
|
|
340
|
-
|
|
341
|
-
// ==========================================================================
|
|
342
|
-
/**
|
|
343
|
-
* Select company and branch (step 2 of login)
|
|
344
|
-
* Frontend receives all options and user selects both together
|
|
345
|
-
*/ async select(sessionId, companyId, branchId) {
|
|
321
|
+
// Company/Branch Selection
|
|
322
|
+
/** Select company and branch (step 2 of login). Frontend receives all options and user selects both. */ async select(sessionId, companyId, branchId) {
|
|
346
323
|
this.ensureCompanyFeatureEnabled();
|
|
347
324
|
if (!this.sessionService) {
|
|
348
325
|
throw new _common.BadRequestException('Session service not available');
|
|
@@ -409,9 +386,7 @@ let AuthenticationService = class AuthenticationService {
|
|
|
409
386
|
}
|
|
410
387
|
return this.generateLoginResponseWithCompany(user, company, branch);
|
|
411
388
|
}
|
|
412
|
-
/**
|
|
413
|
-
* Switch company/branch after login
|
|
414
|
-
*/ async switchCompany(userId, companyId, branchId) {
|
|
389
|
+
/** Switch company/branch after login */ async switchCompany(userId, companyId, branchId) {
|
|
415
390
|
this.ensureCompanyFeatureEnabled();
|
|
416
391
|
const userRepository = await this.getUserRepository();
|
|
417
392
|
const user = await userRepository.findOne({
|
|
@@ -470,13 +445,8 @@ let AuthenticationService = class AuthenticationService {
|
|
|
470
445
|
}
|
|
471
446
|
return this.generateLoginResponseWithCompany(user, company, branch);
|
|
472
447
|
}
|
|
473
|
-
//
|
|
474
|
-
|
|
475
|
-
// ==========================================================================
|
|
476
|
-
/**
|
|
477
|
-
* Refresh access token (with token rotation)
|
|
478
|
-
* Returns new access token and new refresh token
|
|
479
|
-
*/ async refreshToken(refreshToken) {
|
|
448
|
+
// Token Management
|
|
449
|
+
/** Refresh access token (with token rotation). Returns new access token and new refresh token. */ async refreshToken(refreshToken) {
|
|
480
450
|
try {
|
|
481
451
|
const payload = this.jwtService.verify(refreshToken, {
|
|
482
452
|
secret: this.authConfig.getRefreshTokenSecret()
|
|
@@ -542,9 +512,7 @@ let AuthenticationService = class AuthenticationService {
|
|
|
542
512
|
throw new _common.UnauthorizedException('Invalid or expired refresh token');
|
|
543
513
|
}
|
|
544
514
|
}
|
|
545
|
-
/**
|
|
546
|
-
* Change password
|
|
547
|
-
*/ async changePassword(userId, currentPassword, newPassword) {
|
|
515
|
+
/** Change password */ async changePassword(userId, currentPassword, newPassword) {
|
|
548
516
|
const userRepository = await this.getUserRepository();
|
|
549
517
|
const user = await userRepository.findOne({
|
|
550
518
|
where: {
|
|
@@ -558,18 +526,53 @@ let AuthenticationService = class AuthenticationService {
|
|
|
558
526
|
if (!isPasswordValid) {
|
|
559
527
|
throw new _common.UnauthorizedException('Current password is incorrect');
|
|
560
528
|
}
|
|
561
|
-
user.password = await _bcrypt.hash(newPassword, BCRYPT_SALT_ROUNDS);
|
|
529
|
+
user.password = await _bcrypt.hash(newPassword, _config.BCRYPT_SALT_ROUNDS);
|
|
562
530
|
await userRepository.save(user);
|
|
563
531
|
}
|
|
564
|
-
/**
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
532
|
+
/** Logout - Revokes all tokens. Stores revocation timestamp in cache. */ async logout(userId) {
|
|
533
|
+
if (!this.cacheManager) {
|
|
534
|
+
// Cache not available - graceful degradation (client-side logout only)
|
|
535
|
+
return;
|
|
536
|
+
}
|
|
537
|
+
const revokedAt = Math.floor(Date.now() / 1000); // Unix timestamp in seconds
|
|
538
|
+
const cacheKey = `${_config.TOKEN_REVOKED_PREFIX}:${userId}`;
|
|
539
|
+
// TTL matches refresh token expiry (tokens older than this are already expired)
|
|
540
|
+
const refreshTokenExpiry = this.authConfig.getRefreshTokenExpiration();
|
|
541
|
+
const ttlMs = this.parseExpiryToMs(refreshTokenExpiry);
|
|
542
|
+
await this.cacheManager.set(cacheKey, revokedAt, ttlMs);
|
|
543
|
+
}
|
|
544
|
+
/** Check if a token is revoked (issued before user's revocation timestamp) */ async isTokenRevoked(userId, tokenIssuedAt) {
|
|
545
|
+
if (!this.cacheManager || !tokenIssuedAt) {
|
|
546
|
+
return false;
|
|
547
|
+
}
|
|
548
|
+
const cacheKey = `${_config.TOKEN_REVOKED_PREFIX}:${userId}`;
|
|
549
|
+
const revokedAt = await this.cacheManager.get(cacheKey);
|
|
550
|
+
if (!revokedAt) {
|
|
551
|
+
return false;
|
|
552
|
+
}
|
|
553
|
+
// Token is revoked if it was issued before the revocation timestamp
|
|
554
|
+
return tokenIssuedAt < revokedAt;
|
|
555
|
+
}
|
|
556
|
+
/** Parse JWT expiry string to milliseconds */ parseExpiryToMs(expiry) {
|
|
557
|
+
const match = expiry.match(/^(\d+)([smhd])$/);
|
|
558
|
+
if (!match) return 7 * 24 * 60 * 60 * 1000; // Default 7 days
|
|
559
|
+
const value = parseInt(match[1], 10);
|
|
560
|
+
const unit = match[2];
|
|
561
|
+
switch(unit){
|
|
562
|
+
case 's':
|
|
563
|
+
return value * 1000;
|
|
564
|
+
case 'm':
|
|
565
|
+
return value * 60 * 1000;
|
|
566
|
+
case 'h':
|
|
567
|
+
return value * 60 * 60 * 1000;
|
|
568
|
+
case 'd':
|
|
569
|
+
return value * 24 * 60 * 60 * 1000;
|
|
570
|
+
default:
|
|
571
|
+
return 7 * 24 * 60 * 60 * 1000;
|
|
572
|
+
}
|
|
573
|
+
}
|
|
574
|
+
// Query Methods
|
|
575
|
+
/** Get user's companies */ async getUserCompanies(userId) {
|
|
573
576
|
this.ensureCompanyFeatureEnabled();
|
|
574
577
|
const permissionRepository = await this.getPermissionRepository();
|
|
575
578
|
const companyRepository = await this.getCompanyRepository();
|
|
@@ -590,9 +593,7 @@ let AuthenticationService = class AuthenticationService {
|
|
|
590
593
|
active: true
|
|
591
594
|
}).orderBy('c.name', 'ASC').getMany();
|
|
592
595
|
}
|
|
593
|
-
/**
|
|
594
|
-
* Get branches for a company that user has access to
|
|
595
|
-
*/ async getUserBranches(userId, companyId) {
|
|
596
|
+
/** Get branches for a company that user has access to */ async getUserBranches(userId, companyId) {
|
|
596
597
|
this.ensureCompanyFeatureEnabled();
|
|
597
598
|
const permissionRepository = await this.getPermissionRepository();
|
|
598
599
|
const branchRepository = await this.getBranchRepository();
|
|
@@ -627,9 +628,7 @@ let AuthenticationService = class AuthenticationService {
|
|
|
627
628
|
active: true
|
|
628
629
|
}).orderBy('b.serial', 'ASC').addOrderBy('b.name', 'ASC').getMany();
|
|
629
630
|
}
|
|
630
|
-
/**
|
|
631
|
-
* Get company by ID
|
|
632
|
-
*/ async getCompanyById(companyId) {
|
|
631
|
+
/** Get company by ID */ async getCompanyById(companyId) {
|
|
633
632
|
const companyRepository = await this.getCompanyRepository();
|
|
634
633
|
if (!companyRepository) {
|
|
635
634
|
return null;
|
|
@@ -640,9 +639,7 @@ let AuthenticationService = class AuthenticationService {
|
|
|
640
639
|
}
|
|
641
640
|
});
|
|
642
641
|
}
|
|
643
|
-
/**
|
|
644
|
-
* Get branch by ID
|
|
645
|
-
*/ async getBranchById(branchId) {
|
|
642
|
+
/** Get branch by ID */ async getBranchById(branchId) {
|
|
646
643
|
const branchRepository = await this.getBranchRepository();
|
|
647
644
|
if (!branchRepository) {
|
|
648
645
|
return null;
|
|
@@ -653,10 +650,7 @@ let AuthenticationService = class AuthenticationService {
|
|
|
653
650
|
}
|
|
654
651
|
});
|
|
655
652
|
}
|
|
656
|
-
/**
|
|
657
|
-
* Get user info for /auth/me endpoint
|
|
658
|
-
* Returns only user, company, and branch information (no tokens)
|
|
659
|
-
*/ async getUserInfo(userId, companyId, branchId) {
|
|
653
|
+
/** Get user info for /auth/me endpoint. Returns user, company, and branch info (no tokens). */ async getUserInfo(userId, companyId, branchId) {
|
|
660
654
|
const userRepository = await this.getUserRepository();
|
|
661
655
|
const user = await userRepository.findOne({
|
|
662
656
|
where: {
|
|
@@ -707,9 +701,7 @@ let AuthenticationService = class AuthenticationService {
|
|
|
707
701
|
}
|
|
708
702
|
return response;
|
|
709
703
|
}
|
|
710
|
-
//
|
|
711
|
-
// HELPER METHODS
|
|
712
|
-
// ==========================================================================
|
|
704
|
+
// Helper Methods
|
|
713
705
|
ensureCompanyFeatureEnabled() {
|
|
714
706
|
if (!this.authConfig.isCompanyFeatureEnabled()) {
|
|
715
707
|
throw new _common.BadRequestException('Company feature is not enabled');
|
|
@@ -733,9 +725,7 @@ let AuthenticationService = class AuthenticationService {
|
|
|
733
725
|
await userRepository.save(user);
|
|
734
726
|
return user;
|
|
735
727
|
}
|
|
736
|
-
//
|
|
737
|
-
// RESPONSE GENERATORS
|
|
738
|
-
// ==========================================================================
|
|
728
|
+
// Response Generators
|
|
739
729
|
generateLoginResponse(user, companyFeatureEnabled = false) {
|
|
740
730
|
const payload = {
|
|
741
731
|
id: user.id,
|
|
@@ -848,9 +838,10 @@ let AuthenticationService = class AuthenticationService {
|
|
|
848
838
|
};
|
|
849
839
|
}
|
|
850
840
|
// NOTE: @Inject() required for bundled code - type metadata may be lost during esbuild
|
|
851
|
-
constructor(jwtService, authConfig, dataSourceProvider, sessionService, injectedUserRepository, injectedPermissionRepository, injectedCompanyRepository, injectedBranchRepository){
|
|
841
|
+
constructor(jwtService, authConfig, cacheManager, dataSourceProvider, sessionService, injectedUserRepository, injectedPermissionRepository, injectedCompanyRepository, injectedBranchRepository){
|
|
852
842
|
_define_property(this, "jwtService", void 0);
|
|
853
843
|
_define_property(this, "authConfig", void 0);
|
|
844
|
+
_define_property(this, "cacheManager", void 0);
|
|
854
845
|
_define_property(this, "dataSourceProvider", void 0);
|
|
855
846
|
_define_property(this, "sessionService", void 0);
|
|
856
847
|
_define_property(this, "injectedUserRepository", void 0);
|
|
@@ -860,6 +851,7 @@ let AuthenticationService = class AuthenticationService {
|
|
|
860
851
|
_define_property(this, "logger", void 0);
|
|
861
852
|
this.jwtService = jwtService;
|
|
862
853
|
this.authConfig = authConfig;
|
|
854
|
+
this.cacheManager = cacheManager;
|
|
863
855
|
this.dataSourceProvider = dataSourceProvider;
|
|
864
856
|
this.sessionService = sessionService;
|
|
865
857
|
this.injectedUserRepository = injectedUserRepository;
|
|
@@ -876,21 +868,24 @@ AuthenticationService = _ts_decorate([
|
|
|
876
868
|
_ts_param(0, (0, _common.Inject)(_jwt.JwtService)),
|
|
877
869
|
_ts_param(1, (0, _common.Inject)(_authconfigservice.AuthConfigService)),
|
|
878
870
|
_ts_param(2, (0, _common.Optional)()),
|
|
879
|
-
_ts_param(2, (0, _common.Inject)(
|
|
871
|
+
_ts_param(2, (0, _common.Inject)('CACHE_INSTANCE')),
|
|
880
872
|
_ts_param(3, (0, _common.Optional)()),
|
|
881
|
-
_ts_param(3, (0, _common.Inject)(
|
|
873
|
+
_ts_param(3, (0, _common.Inject)(_authdatasourceprovider.AuthDataSourceProvider)),
|
|
882
874
|
_ts_param(4, (0, _common.Optional)()),
|
|
883
|
-
_ts_param(4, (0,
|
|
875
|
+
_ts_param(4, (0, _common.Inject)(_companyselectionsessionservice.CompanySelectionSessionService)),
|
|
884
876
|
_ts_param(5, (0, _common.Optional)()),
|
|
885
|
-
_ts_param(5, (0, _typeorm.InjectRepository)(
|
|
877
|
+
_ts_param(5, (0, _typeorm.InjectRepository)(_userentity.User)),
|
|
886
878
|
_ts_param(6, (0, _common.Optional)()),
|
|
887
|
-
_ts_param(6, (0, _typeorm.InjectRepository)(
|
|
879
|
+
_ts_param(6, (0, _typeorm.InjectRepository)(_usercompanypermissionentity.UserCompanyPermission)),
|
|
888
880
|
_ts_param(7, (0, _common.Optional)()),
|
|
889
|
-
_ts_param(7, (0, _typeorm.InjectRepository)(
|
|
881
|
+
_ts_param(7, (0, _typeorm.InjectRepository)(_companyentity.Company)),
|
|
882
|
+
_ts_param(8, (0, _common.Optional)()),
|
|
883
|
+
_ts_param(8, (0, _typeorm.InjectRepository)(_companybranchentity.CompanyBranch)),
|
|
890
884
|
_ts_metadata("design:type", Function),
|
|
891
885
|
_ts_metadata("design:paramtypes", [
|
|
892
886
|
typeof _jwt.JwtService === "undefined" ? Object : _jwt.JwtService,
|
|
893
887
|
typeof _authconfigservice.AuthConfigService === "undefined" ? Object : _authconfigservice.AuthConfigService,
|
|
888
|
+
typeof _classes.HybridCache === "undefined" ? Object : _classes.HybridCache,
|
|
894
889
|
typeof _authdatasourceprovider.AuthDataSourceProvider === "undefined" ? Object : _authdatasourceprovider.AuthDataSourceProvider,
|
|
895
890
|
typeof _companyselectionsessionservice.CompanySelectionSessionService === "undefined" ? Object : _companyselectionsessionservice.CompanySelectionSessionService,
|
|
896
891
|
typeof _typeorm1.Repository === "undefined" ? Object : _typeorm1.Repository,
|
|
@@ -42,41 +42,15 @@ function _ts_param(paramIndex, decorator) {
|
|
|
42
42
|
};
|
|
43
43
|
}
|
|
44
44
|
let BranchService = class BranchService extends _classes.RequestScopedApiService {
|
|
45
|
-
|
|
46
|
-
* Resolve entity class for this service
|
|
47
|
-
* @returns CompanyBranch entity class
|
|
48
|
-
*/ resolveEntity() {
|
|
45
|
+
resolveEntity() {
|
|
49
46
|
return _companybranchentity.CompanyBranch;
|
|
50
47
|
}
|
|
51
|
-
|
|
52
|
-
* Get DataSource provider for this service
|
|
53
|
-
* @returns AuthDataSourceProvider instance
|
|
54
|
-
*/ getDataSourceProvider() {
|
|
48
|
+
getDataSourceProvider() {
|
|
55
49
|
return this.dataSourceProvider;
|
|
56
50
|
}
|
|
57
|
-
//
|
|
58
|
-
async convertSingleDtoToEntity(dto, _user) {
|
|
59
|
-
// Repository initialization is handled automatically by RequestScopedApiService
|
|
60
|
-
let branch = new _companybranchentity.CompanyBranch();
|
|
61
|
-
if ('id' in dto && dto.id && typeof dto.id === 'string') {
|
|
62
|
-
const dbData = await this.repository.findOne({
|
|
63
|
-
where: {
|
|
64
|
-
id: dto.id
|
|
65
|
-
}
|
|
66
|
-
});
|
|
67
|
-
if (!dbData) {
|
|
68
|
-
throw new _common.NotFoundException('Branch not found');
|
|
69
|
-
}
|
|
70
|
-
branch = dbData;
|
|
71
|
-
}
|
|
72
|
-
return {
|
|
73
|
-
...branch,
|
|
74
|
-
...dto
|
|
75
|
-
};
|
|
76
|
-
}
|
|
51
|
+
// Query Customization
|
|
77
52
|
async getSelectQuery(query, _user, select) {
|
|
78
|
-
|
|
79
|
-
if (!select || !select.length) {
|
|
53
|
+
if (!select?.length) {
|
|
80
54
|
select = [
|
|
81
55
|
'id',
|
|
82
56
|
'name',
|
|
@@ -85,14 +59,13 @@ let BranchService = class BranchService extends _classes.RequestScopedApiService
|
|
|
85
59
|
'createdAt'
|
|
86
60
|
];
|
|
87
61
|
}
|
|
88
|
-
|
|
89
|
-
query.select(selectFields);
|
|
62
|
+
query.select(select.map((f)=>`${this.entityName}.${f}`));
|
|
90
63
|
return {
|
|
91
64
|
query,
|
|
92
65
|
isRaw: false
|
|
93
66
|
};
|
|
94
67
|
}
|
|
95
|
-
async getGlobalSearchQuery(query, search
|
|
68
|
+
async getGlobalSearchQuery(query, search) {
|
|
96
69
|
query.andWhere('(company_branch.name LIKE :search OR company_branch.slug LIKE :search OR company_branch.email LIKE :search)', {
|
|
97
70
|
search: `%${search}%`
|
|
98
71
|
});
|
|
@@ -101,24 +74,17 @@ let BranchService = class BranchService extends _classes.RequestScopedApiService
|
|
|
101
74
|
isRaw: false
|
|
102
75
|
};
|
|
103
76
|
}
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
*/ async getExtraManipulateQuery(query, _filterAndPaginationDto, user) {
|
|
108
|
-
const result = await super.getExtraManipulateQuery(query, _filterAndPaginationDto, user);
|
|
109
|
-
// Only apply company filtering if company feature is enabled and user has company context
|
|
110
|
-
const isCompanyFeatureEnabled = this.authConfig.isCompanyFeatureEnabled();
|
|
111
|
-
if (isCompanyFeatureEnabled && user?.companyId) {
|
|
77
|
+
async getExtraManipulateQuery(query, filterDto, user) {
|
|
78
|
+
const result = await super.getExtraManipulateQuery(query, filterDto, user);
|
|
79
|
+
if (this.authConfig.isCompanyFeatureEnabled() && user?.companyId) {
|
|
112
80
|
query.andWhere('company_branch.company_id = :companyId', {
|
|
113
81
|
companyId: user.companyId
|
|
114
82
|
});
|
|
115
83
|
}
|
|
116
84
|
return result;
|
|
117
85
|
}
|
|
118
|
-
// NOTE: @Inject() required for bundled code - type metadata may be lost during esbuild
|
|
119
86
|
constructor(cacheManager, utilsService, dataSourceProvider, authConfig){
|
|
120
|
-
|
|
121
|
-
super('company_branch', null, cacheManager, utilsService, BranchService.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), this.cacheManager = cacheManager, this.utilsService = utilsService, this.dataSourceProvider = dataSourceProvider, this.authConfig = authConfig, this.logger = new _common.Logger(BranchService.name);
|
|
87
|
+
super('company_branch', null, cacheManager, utilsService, BranchService.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), this.cacheManager = cacheManager, this.utilsService = utilsService, this.dataSourceProvider = dataSourceProvider, this.authConfig = authConfig;
|
|
122
88
|
}
|
|
123
89
|
};
|
|
124
90
|
BranchService = _ts_decorate([
|
|
@@ -41,41 +41,15 @@ function _ts_param(paramIndex, decorator) {
|
|
|
41
41
|
};
|
|
42
42
|
}
|
|
43
43
|
let CompanyService = class CompanyService extends _classes.RequestScopedApiService {
|
|
44
|
-
|
|
45
|
-
* Resolve entity class for this service
|
|
46
|
-
* @returns Company entity class
|
|
47
|
-
*/ resolveEntity() {
|
|
44
|
+
resolveEntity() {
|
|
48
45
|
return _companyentity.Company;
|
|
49
46
|
}
|
|
50
|
-
|
|
51
|
-
* Get DataSource provider for this service
|
|
52
|
-
* @returns AuthDataSourceProvider instance
|
|
53
|
-
*/ getDataSourceProvider() {
|
|
47
|
+
getDataSourceProvider() {
|
|
54
48
|
return this.dataSourceProvider;
|
|
55
49
|
}
|
|
56
|
-
//
|
|
57
|
-
async convertSingleDtoToEntity(dto, _user) {
|
|
58
|
-
// Repository initialization is handled automatically by RequestScopedApiService
|
|
59
|
-
let company = new _companyentity.Company();
|
|
60
|
-
if ('id' in dto && dto.id && typeof dto.id === 'string') {
|
|
61
|
-
const dbData = await this.repository.findOne({
|
|
62
|
-
where: {
|
|
63
|
-
id: dto.id
|
|
64
|
-
}
|
|
65
|
-
});
|
|
66
|
-
if (!dbData) {
|
|
67
|
-
throw new _common.NotFoundException('Company not found');
|
|
68
|
-
}
|
|
69
|
-
company = dbData;
|
|
70
|
-
}
|
|
71
|
-
return {
|
|
72
|
-
...company,
|
|
73
|
-
...dto
|
|
74
|
-
};
|
|
75
|
-
}
|
|
50
|
+
// Query Customization
|
|
76
51
|
async getSelectQuery(query, _user, select) {
|
|
77
|
-
|
|
78
|
-
if (!select || !select.length) {
|
|
52
|
+
if (!select?.length) {
|
|
79
53
|
select = [
|
|
80
54
|
'id',
|
|
81
55
|
'name',
|
|
@@ -84,14 +58,13 @@ let CompanyService = class CompanyService extends _classes.RequestScopedApiServi
|
|
|
84
58
|
'createdAt'
|
|
85
59
|
];
|
|
86
60
|
}
|
|
87
|
-
|
|
88
|
-
query.select(selectFields);
|
|
61
|
+
query.select(select.map((f)=>`${this.entityName}.${f}`));
|
|
89
62
|
return {
|
|
90
63
|
query,
|
|
91
64
|
isRaw: false
|
|
92
65
|
};
|
|
93
66
|
}
|
|
94
|
-
async getGlobalSearchQuery(query, search
|
|
67
|
+
async getGlobalSearchQuery(query, search) {
|
|
95
68
|
query.andWhere('(company.name LIKE :search OR company.slug LIKE :search OR company.email LIKE :search)', {
|
|
96
69
|
search: `%${search}%`
|
|
97
70
|
});
|
|
@@ -100,10 +73,8 @@ let CompanyService = class CompanyService extends _classes.RequestScopedApiServi
|
|
|
100
73
|
isRaw: false
|
|
101
74
|
};
|
|
102
75
|
}
|
|
103
|
-
// NOTE: @Inject() required for bundled code - type metadata may be lost during esbuild
|
|
104
76
|
constructor(cacheManager, utilsService, dataSourceProvider){
|
|
105
|
-
|
|
106
|
-
super('company', null, cacheManager, utilsService, CompanyService.name, true), _define_property(this, "cacheManager", void 0), _define_property(this, "utilsService", void 0), _define_property(this, "dataSourceProvider", void 0), _define_property(this, "logger", void 0), this.cacheManager = cacheManager, this.utilsService = utilsService, this.dataSourceProvider = dataSourceProvider, this.logger = new _common.Logger(CompanyService.name);
|
|
77
|
+
super('company', null, cacheManager, utilsService, CompanyService.name, true), _define_property(this, "cacheManager", void 0), _define_property(this, "utilsService", void 0), _define_property(this, "dataSourceProvider", void 0), this.cacheManager = cacheManager, this.utilsService = utilsService, this.dataSourceProvider = dataSourceProvider;
|
|
107
78
|
}
|
|
108
79
|
};
|
|
109
80
|
CompanyService = _ts_decorate([
|
|
@@ -39,20 +39,14 @@ function _ts_param(paramIndex, decorator) {
|
|
|
39
39
|
};
|
|
40
40
|
}
|
|
41
41
|
let UserPermissionService = class UserPermissionService {
|
|
42
|
-
/**
|
|
43
|
-
* Get repository lazily - initialized on first access
|
|
44
|
-
*/ async getRepository() {
|
|
42
|
+
/** Get repository lazily - initialized on first access */ async getRepository() {
|
|
45
43
|
if (!this._repository) {
|
|
46
44
|
this._repository = await this.dataSourceProvider.getRepository(_usercompanypermissionentity.UserCompanyPermission);
|
|
47
45
|
}
|
|
48
46
|
return this._repository;
|
|
49
47
|
}
|
|
50
|
-
//
|
|
51
|
-
|
|
52
|
-
// ==========================================================================
|
|
53
|
-
/**
|
|
54
|
-
* Find all companies a user has access to
|
|
55
|
-
*/ async findUserCompanies(userId) {
|
|
48
|
+
// Company Permissions
|
|
49
|
+
/** Find all companies a user has access to */ async findUserCompanies(userId) {
|
|
56
50
|
const repository = await this.getRepository();
|
|
57
51
|
return repository.find({
|
|
58
52
|
where: {
|
|
@@ -67,9 +61,7 @@ let UserPermissionService = class UserPermissionService {
|
|
|
67
61
|
}
|
|
68
62
|
});
|
|
69
63
|
}
|
|
70
|
-
/**
|
|
71
|
-
* Assign user to a company
|
|
72
|
-
*/ async assignUserToCompany(dto) {
|
|
64
|
+
/** Assign user to a company */ async assignUserToCompany(dto) {
|
|
73
65
|
const repository = await this.getRepository();
|
|
74
66
|
// Check if already exists
|
|
75
67
|
const existing = await repository.findOne({
|
|
@@ -90,9 +82,7 @@ let UserPermissionService = class UserPermissionService {
|
|
|
90
82
|
});
|
|
91
83
|
await repository.save(permission);
|
|
92
84
|
}
|
|
93
|
-
/**
|
|
94
|
-
* Revoke user access to a company
|
|
95
|
-
*/ async revokeCompanyAccess(userId, companyId) {
|
|
85
|
+
/** Revoke user access to a company */ async revokeCompanyAccess(userId, companyId) {
|
|
96
86
|
const repository = await this.getRepository();
|
|
97
87
|
const permission = await repository.findOne({
|
|
98
88
|
where: {
|
|
@@ -106,12 +96,8 @@ let UserPermissionService = class UserPermissionService {
|
|
|
106
96
|
}
|
|
107
97
|
await repository.remove(permission);
|
|
108
98
|
}
|
|
109
|
-
//
|
|
110
|
-
|
|
111
|
-
// ==========================================================================
|
|
112
|
-
/**
|
|
113
|
-
* Find all branches a user has access to
|
|
114
|
-
*/ async findUserBranches(userId) {
|
|
99
|
+
// Branch Permissions
|
|
100
|
+
/** Find all branches a user has access to */ async findUserBranches(userId) {
|
|
115
101
|
const repository = await this.getRepository();
|
|
116
102
|
return repository.find({
|
|
117
103
|
where: {
|
|
@@ -126,9 +112,7 @@ let UserPermissionService = class UserPermissionService {
|
|
|
126
112
|
}
|
|
127
113
|
});
|
|
128
114
|
}
|
|
129
|
-
/**
|
|
130
|
-
* Assign user to a branch
|
|
131
|
-
*/ async assignUserToBranch(dto) {
|
|
115
|
+
/** Assign user to a branch */ async assignUserToBranch(dto) {
|
|
132
116
|
const repository = await this.getRepository();
|
|
133
117
|
// Check if already exists
|
|
134
118
|
const existing = await repository.findOne({
|
|
@@ -149,9 +133,7 @@ let UserPermissionService = class UserPermissionService {
|
|
|
149
133
|
});
|
|
150
134
|
await repository.save(permission);
|
|
151
135
|
}
|
|
152
|
-
/**
|
|
153
|
-
* Revoke user access to a branch
|
|
154
|
-
*/ async revokeBranchAccess(userId, branchId) {
|
|
136
|
+
/** Revoke user access to a branch */ async revokeBranchAccess(userId, branchId) {
|
|
155
137
|
const repository = await this.getRepository();
|
|
156
138
|
const permission = await repository.findOne({
|
|
157
139
|
where: {
|