ecrs-auth-core 1.0.81 → 1.0.83

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.
@@ -1,9 +1,11 @@
1
1
  import { Request } from 'express';
2
+ import { JwtService } from '@nestjs/jwt';
2
3
  import { AuthService } from './auth.service';
3
4
  import { LoginDto } from './dtos/login.dto';
4
5
  export declare class AuthController {
5
6
  private readonly authService;
6
- constructor(authService: AuthService);
7
+ private readonly jwtService;
8
+ constructor(authService: AuthService, jwtService: JwtService);
7
9
  login(request: Request, body: LoginDto): Promise<{
8
10
  status: boolean;
9
11
  message: string;
@@ -39,7 +41,6 @@ export declare class AuthController {
39
41
  data: {
40
42
  user: {
41
43
  id: any;
42
- email: any;
43
44
  logoutTime: string;
44
45
  };
45
46
  };
@@ -14,13 +14,15 @@ var __param = (this && this.__param) || function (paramIndex, decorator) {
14
14
  Object.defineProperty(exports, "__esModule", { value: true });
15
15
  exports.AuthController = void 0;
16
16
  const common_1 = require("@nestjs/common");
17
+ const jwt_1 = require("@nestjs/jwt");
17
18
  const auth_service_1 = require("./auth.service");
18
19
  const login_dto_1 = require("./dtos/login.dto");
19
20
  const login_response_dto_1 = require("./dtos/login-response.dto");
20
21
  const swagger_1 = require("@nestjs/swagger");
21
22
  let AuthController = class AuthController {
22
- constructor(authService) {
23
+ constructor(authService, jwtService) {
23
24
  this.authService = authService;
25
+ this.jwtService = jwtService;
24
26
  }
25
27
  async login(request, body) {
26
28
  // Get client IP from socket/request
@@ -73,36 +75,48 @@ let AuthController = class AuthController {
73
75
  return loginResponse;
74
76
  }
75
77
  async logout(request) {
76
- // Get user from JWT token (assuming JwtAuthGuard is applied)
77
- const user = request.user;
78
- if (!user || !user.id) {
79
- throw new common_1.UnauthorizedException('User not authenticated');
78
+ // Extract JWT token from Authorization header
79
+ const authHeader = request.headers.authorization;
80
+ if (!authHeader || !authHeader.startsWith('Bearer ')) {
81
+ throw new common_1.UnauthorizedException('Missing or invalid Authorization header. Required format: Bearer <token>');
80
82
  }
81
- console.log(`🚪 Logout request for user ${user.id} (${user.email})`);
83
+ const token = authHeader.substring(7); // Remove 'Bearer ' prefix
82
84
  try {
85
+ // Decode JWT token to get user ID
86
+ const payload = this.jwtService.verify(token);
87
+ const userId = payload.id;
88
+ if (!userId) {
89
+ throw new common_1.UnauthorizedException('Invalid token - no user ID found');
90
+ }
91
+ console.log(`🚪 Logout request for user ${userId}`);
83
92
  // Update logout details in both tables
84
93
  await Promise.all([
85
- this.authService.updateLastLoginLogout(user.id).catch((err) => {
94
+ this.authService.updateLastLoginLogout(userId).catch((err) => {
86
95
  console.error('❌ Error updating logout in tbl_user_last_login:', err.message);
87
96
  }),
88
- this.authService.updateLoginLogoutDetailsJson(user.id).catch((err) => {
97
+ this.authService.updateLoginLogoutDetailsJson(userId).catch((err) => {
89
98
  console.error('❌ Error updating logout in tbl_user_login_details:', err.message);
90
99
  })
91
100
  ]);
92
- console.log(`✅ User ${user.id} logged out successfully`);
101
+ console.log(`✅ User ${userId} logged out successfully`);
93
102
  return {
94
103
  status: true,
95
104
  message: 'Logout successful',
96
105
  data: {
97
106
  user: {
98
- id: user.id,
99
- email: user.email,
107
+ id: userId,
100
108
  logoutTime: new Date().toISOString()
101
109
  }
102
110
  }
103
111
  };
104
112
  }
105
113
  catch (error) {
114
+ if (error.name === 'TokenExpiredError') {
115
+ throw new common_1.UnauthorizedException('JWT token has expired');
116
+ }
117
+ if (error.name === 'JsonWebTokenError') {
118
+ throw new common_1.UnauthorizedException('Invalid JWT token');
119
+ }
106
120
  console.error('❌ Error during logout:', error?.message || error);
107
121
  throw new common_1.UnauthorizedException('Logout failed');
108
122
  }
@@ -260,16 +274,22 @@ __decorate([
260
274
  (0, common_1.HttpCode)(200),
261
275
  (0, swagger_1.ApiOperation)({
262
276
  summary: 'User logout',
263
- description: 'Logout user and update session end time'
277
+ description: 'Logout user and update session end time. Extracts user ID from JWT token in Authorization header.'
264
278
  }),
265
279
  (0, swagger_1.ApiOkResponse)({
266
280
  description: 'Logout successful',
267
281
  example: {
268
282
  status: true,
269
- message: 'Logout successful'
283
+ message: 'Logout successful',
284
+ data: {
285
+ user: {
286
+ id: 1,
287
+ logoutTime: '2026-01-28T10:30:00.000Z'
288
+ }
289
+ }
270
290
  }
271
291
  }),
272
- (0, swagger_1.ApiUnauthorizedResponse)({ description: 'Unauthorized' }),
292
+ (0, swagger_1.ApiUnauthorizedResponse)({ description: 'Unauthorized - Invalid or missing JWT token' }),
273
293
  __param(0, (0, common_1.Req)()),
274
294
  __metadata("design:type", Function),
275
295
  __metadata("design:paramtypes", [Object]),
@@ -280,5 +300,6 @@ exports.AuthController = AuthController = __decorate([
280
300
  (0, swagger_1.ApiBearerAuth)(),
281
301
  (0, swagger_1.ApiExtraModels)(login_dto_1.LoginDto, login_response_dto_1.LoginResponseDto),
282
302
  (0, common_1.Controller)('auth'),
283
- __metadata("design:paramtypes", [auth_service_1.AuthService])
303
+ __metadata("design:paramtypes", [auth_service_1.AuthService,
304
+ jwt_1.JwtService])
284
305
  ], AuthController);
@@ -72,18 +72,24 @@ let AuthService = class AuthService {
72
72
  }
73
73
  async validateUser(email, password, clientIp) {
74
74
  const user = await this.userRepo.findOne({ where: { email } });
75
- if (!user)
76
- return null;
75
+ if (!user) {
76
+ throw new common_1.UnauthorizedException('The email address is invalid or not registered.');
77
+ }
77
78
  const isValid = await bcrypt.compare(password, user.password);
78
- if (!isValid)
79
- return null;
79
+ if (!isValid) {
80
+ throw new common_1.UnauthorizedException('The password is incorrect. Please try again.');
81
+ }
82
+ ;
83
+ if (user.status !== 1) {
84
+ throw new common_1.UnauthorizedException('Your account is inactive. Please contact support.');
85
+ }
80
86
  // console.log(this.ipRestrictionsRepo);
81
87
  // Check IP restrictions if provided and repository is available
82
88
  if (clientIp && this.ipRestrictionsRepo) {
83
89
  const ipAllowed = await this.validateIpRestriction(user.id, clientIp);
84
90
  if (!ipAllowed) {
85
- // IP restriction exists but doesn't match - return null to block login
86
- return null;
91
+ // IP restriction exists but doesn't match - throw UnauthorizedException to block login
92
+ throw new common_1.UnauthorizedException('Login denied: Your IP address is not allowed.');
87
93
  }
88
94
  }
89
95
  return user;
@@ -220,7 +226,14 @@ let AuthService = class AuthService {
220
226
  console.log(`📝 Last login details saved for user ${user.id} (${loginStatus})`);
221
227
  }
222
228
  catch (error) {
223
- console.error('Error saving last login details:', error);
229
+ if (error?.message?.includes('No metadata')) {
230
+ console.error('❌ ERROR: UserLastLoginEntity is not registered in your TypeORM configuration.\n' +
231
+ 'Please see ENTITY_SETUP_GUIDE.md for setup instructions.\n' +
232
+ 'Entity must be added to TypeOrmModule.forRoot(entities: [...]) in your app.');
233
+ }
234
+ else {
235
+ console.error('Error saving last login details:', error);
236
+ }
224
237
  // Don't throw error - this shouldn't block login
225
238
  }
226
239
  }
@@ -307,7 +320,14 @@ let AuthService = class AuthService {
307
320
  }
308
321
  }
309
322
  catch (error) {
310
- console.error('Error saving login details JSON:', error);
323
+ if (error?.message?.includes('No metadata')) {
324
+ console.error('❌ ERROR: LoginDetailsEntity is not registered in your TypeORM configuration.\n' +
325
+ 'Please see ENTITY_SETUP_GUIDE.md for setup instructions.\n' +
326
+ 'Entity must be added to TypeOrmModule.forRoot(entities: [...]) in your app.');
327
+ }
328
+ else {
329
+ console.error('Error saving login details JSON:', error);
330
+ }
311
331
  // Don't throw error - this shouldn't block login
312
332
  }
313
333
  }
@@ -356,7 +376,13 @@ let AuthService = class AuthService {
356
376
  console.log(`🚪 Logout details updated for user ${userId} on ${today.toDateString()}`);
357
377
  }
358
378
  catch (error) {
359
- console.error('Error updating logout details:', error);
379
+ if (error?.message?.includes('No metadata')) {
380
+ console.error('❌ ERROR: LoginDetailsEntity is not registered in your TypeORM configuration.\n' +
381
+ 'Please see ENTITY_SETUP_GUIDE.md for setup instructions.');
382
+ }
383
+ else {
384
+ console.error('Error updating logout details:', error);
385
+ }
360
386
  // Don't throw error - this shouldn't block logout
361
387
  }
362
388
  }
@@ -383,7 +409,13 @@ let AuthService = class AuthService {
383
409
  console.log(`🚪 Last login logout time updated for user ${userId}`);
384
410
  }
385
411
  catch (error) {
386
- console.error('Error updating last login logout time:', error);
412
+ if (error?.message?.includes('No metadata')) {
413
+ console.error('❌ ERROR: UserLastLoginEntity is not registered in your TypeORM configuration.\n' +
414
+ 'Please see ENTITY_SETUP_GUIDE.md for setup instructions.');
415
+ }
416
+ else {
417
+ console.error('Error updating last login logout time:', error);
418
+ }
387
419
  // Don't throw error - this shouldn't block logout
388
420
  }
389
421
  }
@@ -462,6 +494,10 @@ let AuthService = class AuthService {
462
494
  lastLoginTime: lastLoginTime,
463
495
  is_reset_password: is_reset_password,
464
496
  };
497
+ // Generate JWT token
498
+ const accessToken = this.jwtService.sign(payload);
499
+ // Update user's apiToken in the database
500
+ await this.userRepo.update({ id: user.id }, { apiToken: accessToken });
465
501
  return {
466
502
  status: true,
467
503
  message: 'Login successful',
@@ -489,7 +525,7 @@ let AuthService = class AuthService {
489
525
  profile_photo_url: `${this.uploadPhotoDir}/${user.userImage}`,
490
526
  },
491
527
  },
492
- access_token: this.jwtService.sign(payload),
528
+ access_token: accessToken,
493
529
  };
494
530
  }
495
531
  /**
@@ -34,6 +34,10 @@ let JwtStrategy = class JwtStrategy extends (0, passport_1.PassportStrategy)(pas
34
34
  console.log(`✅ User ${user.id} has access to module ${payload.moduleId}`);
35
35
  }
36
36
  console.log(`✅ JWT validated for user ${user.id}`);
37
+ if (user.status !== 1) {
38
+ console.log(`❌ User ${user.id} is not active`);
39
+ throw new common_1.UnauthorizedException('Your account is inactive. Please contact support.');
40
+ }
37
41
  return {
38
42
  id: user.id,
39
43
  email: user.email,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ecrs-auth-core",
3
- "version": "1.0.81",
3
+ "version": "1.0.83",
4
4
  "description": "Centralized authentication and authorization module for ECRS apps",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",