@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
|
@@ -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
|
-
|
|
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
|
-
|
|
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,
|
|
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
|
-
|
|
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.
|
|
188
|
+
profilePictureId: isRaw ? entity.user_profile_picture_id : entity.profilePictureId,
|
|
230
189
|
isActive,
|
|
231
|
-
emailVerified: isRaw ? entity.
|
|
232
|
-
phoneVerified: isRaw ? entity.
|
|
233
|
-
lastLoginAt: isRaw ? entity.
|
|
234
|
-
additionalFields: isRaw ? entity.
|
|
235
|
-
createdAt: isRaw ? entity.
|
|
236
|
-
updatedAt: isRaw ? entity.
|
|
237
|
-
deletedAt: isRaw ? entity.
|
|
238
|
-
createdById: isRaw ? entity.
|
|
239
|
-
updatedById: isRaw ? entity.
|
|
240
|
-
deletedById: isRaw ? entity.
|
|
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
|
-
|
|
245
|
-
|
|
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
|
-
|
|
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
|
|
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,8 +1,7 @@
|
|
|
1
|
-
//
|
|
2
|
-
|
|
3
|
-
//
|
|
4
|
-
/**
|
|
5
|
-
//
|
|
6
|
-
|
|
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
|
-
|
|
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
|
|
30
|
-
import {
|
|
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
|
|
30
|
-
import {
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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", [
|