ecrs-auth-core 1.0.63 → 1.0.65
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/dist/auth.controller.d.ts +25 -1
- package/dist/auth.controller.js +114 -7
- package/dist/auth.module.js +0 -3
- package/dist/auth.service.d.ts +35 -1
- package/dist/auth.service.js +130 -2
- package/dist/entities/ip-access.entity.d.ts +13 -0
- package/dist/entities/ip-access.entity.js +73 -0
- package/dist/entities/user-last-login.entity.d.ts +27 -0
- package/dist/entities/user-last-login.entity.js +147 -0
- package/dist/entities/work-profile.entity.d.ts +48 -0
- package/dist/entities/work-profile.entity.js +165 -0
- package/dist/guards/api-key.guard.d.ts +1 -3
- package/dist/guards/api-key.guard.js +4 -17
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -2
- package/dist/interfaces/auth-core-options.interface.d.ts +4 -0
- package/package.json +1 -1
- package/dist/services/encryption.service.d.ts +0 -16
- package/dist/services/encryption.service.js +0 -70
|
@@ -1,9 +1,10 @@
|
|
|
1
|
+
import { Request } from 'express';
|
|
1
2
|
import { AuthService } from './auth.service';
|
|
2
3
|
import { LoginDto } from './dtos/login.dto';
|
|
3
4
|
export declare class AuthController {
|
|
4
5
|
private readonly authService;
|
|
5
6
|
constructor(authService: AuthService);
|
|
6
|
-
login(body: LoginDto): Promise<{
|
|
7
|
+
login(request: Request, body: LoginDto): Promise<{
|
|
7
8
|
status: boolean;
|
|
8
9
|
message: string;
|
|
9
10
|
data: {
|
|
@@ -21,8 +22,31 @@ export declare class AuthController {
|
|
|
21
22
|
employeeId: number;
|
|
22
23
|
parentId: number;
|
|
23
24
|
referenceId: number;
|
|
25
|
+
branchId: any;
|
|
26
|
+
dispatchId: any;
|
|
27
|
+
departmentId: any;
|
|
28
|
+
designationId: any;
|
|
29
|
+
profile_photo_url: string;
|
|
24
30
|
};
|
|
25
31
|
};
|
|
26
32
|
access_token: string;
|
|
27
33
|
}>;
|
|
34
|
+
/**
|
|
35
|
+
* Extract additional client data from request and user-agent
|
|
36
|
+
*/
|
|
37
|
+
private extractClientData;
|
|
38
|
+
/**
|
|
39
|
+
* Parse user-agent string to extract browser, OS, and device type
|
|
40
|
+
*/
|
|
41
|
+
private parseUserAgent;
|
|
42
|
+
/**
|
|
43
|
+
* Extract client IP from request
|
|
44
|
+
* Priority:
|
|
45
|
+
* 1. X-Forwarded-For header (proxy)
|
|
46
|
+
* 2. X-Real-IP header (nginx)
|
|
47
|
+
* 3. CF-Connecting-IP (Cloudflare)
|
|
48
|
+
* 4. request.ip (Express native)
|
|
49
|
+
* 5. socket.remoteAddress (direct connection)
|
|
50
|
+
*/
|
|
51
|
+
private getClientIp;
|
|
28
52
|
}
|
package/dist/auth.controller.js
CHANGED
|
@@ -22,10 +22,19 @@ let AuthController = class AuthController {
|
|
|
22
22
|
constructor(authService) {
|
|
23
23
|
this.authService = authService;
|
|
24
24
|
}
|
|
25
|
-
async login(body) {
|
|
26
|
-
|
|
25
|
+
async login(request, body) {
|
|
26
|
+
// Get client IP from socket/request
|
|
27
|
+
const clientIp = this.getClientIp(request);
|
|
28
|
+
const userAgent = request.get('user-agent') || 'Unknown';
|
|
29
|
+
// Extract additional client data
|
|
30
|
+
const additionalData = this.extractClientData(request, userAgent);
|
|
31
|
+
console.log(`📍 Login attempt from IP: ${clientIp}, User-Agent: ${userAgent}`);
|
|
32
|
+
// Validate user with IP restriction check
|
|
33
|
+
const user = await this.authService.validateUser(body.email, body.password, clientIp);
|
|
27
34
|
if (!user) {
|
|
28
|
-
|
|
35
|
+
// Save failed login attempt
|
|
36
|
+
await this.authService.saveLastLogin({ email: body.email }, clientIp, 'failed', 'Invalid credentials or IP not allowed', additionalData).catch(() => { }); // Ignore errors
|
|
37
|
+
throw new common_1.UnauthorizedException('Login failed: email or password not matched or IP not allowed');
|
|
29
38
|
}
|
|
30
39
|
const requestedModuleId = Number(body.moduleId);
|
|
31
40
|
if (!Number.isFinite(requestedModuleId)) {
|
|
@@ -39,7 +48,104 @@ let AuthController = class AuthController {
|
|
|
39
48
|
if (!Array.isArray(perms.modules) || !perms.modules.includes(requestedModuleId)) {
|
|
40
49
|
throw new common_1.UnauthorizedException('You are not authorized to access this module');
|
|
41
50
|
}
|
|
42
|
-
|
|
51
|
+
const loginResponse = await this.authService.login(user, requestedModuleId);
|
|
52
|
+
// Save successful login details with additional client data
|
|
53
|
+
await this.authService.saveLastLogin(user, clientIp, 'success', undefined, {
|
|
54
|
+
...additionalData,
|
|
55
|
+
moduleId: requestedModuleId,
|
|
56
|
+
}).catch(() => { }); // Ignore errors - don't block login
|
|
57
|
+
return loginResponse;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Extract additional client data from request and user-agent
|
|
61
|
+
*/
|
|
62
|
+
extractClientData(request, userAgent) {
|
|
63
|
+
const { browser, os, deviceType } = this.parseUserAgent(userAgent);
|
|
64
|
+
const ipAddressName = request.get('x-forwarded-host') || request.get('host') || 'Unknown';
|
|
65
|
+
const location = request.get('cf-ipcountry') || 'Unknown'; // Cloudflare header
|
|
66
|
+
return {
|
|
67
|
+
browser,
|
|
68
|
+
deviceType,
|
|
69
|
+
operatingSystem: os,
|
|
70
|
+
userAgent,
|
|
71
|
+
location,
|
|
72
|
+
ipAddressName,
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Parse user-agent string to extract browser, OS, and device type
|
|
77
|
+
*/
|
|
78
|
+
parseUserAgent(userAgent) {
|
|
79
|
+
const ua = userAgent.toLowerCase();
|
|
80
|
+
// Detect browser
|
|
81
|
+
let browser = 'Unknown';
|
|
82
|
+
if (ua.includes('chrome'))
|
|
83
|
+
browser = 'Chrome';
|
|
84
|
+
else if (ua.includes('firefox'))
|
|
85
|
+
browser = 'Firefox';
|
|
86
|
+
else if (ua.includes('safari'))
|
|
87
|
+
browser = 'Safari';
|
|
88
|
+
else if (ua.includes('edg/'))
|
|
89
|
+
browser = 'Edge';
|
|
90
|
+
else if (ua.includes('opera') || ua.includes('opr/'))
|
|
91
|
+
browser = 'Opera';
|
|
92
|
+
else if (ua.includes('trident'))
|
|
93
|
+
browser = 'Internet Explorer';
|
|
94
|
+
// Detect OS
|
|
95
|
+
let os = 'Unknown';
|
|
96
|
+
if (ua.includes('windows'))
|
|
97
|
+
os = 'Windows';
|
|
98
|
+
else if (ua.includes('mac'))
|
|
99
|
+
os = 'macOS';
|
|
100
|
+
else if (ua.includes('linux'))
|
|
101
|
+
os = 'Linux';
|
|
102
|
+
else if (ua.includes('iphone') || ua.includes('ipad'))
|
|
103
|
+
os = 'iOS';
|
|
104
|
+
else if (ua.includes('android'))
|
|
105
|
+
os = 'Android';
|
|
106
|
+
// Detect device type
|
|
107
|
+
let deviceType = 'Desktop';
|
|
108
|
+
if (ua.includes('mobile') || ua.includes('android') || ua.includes('iphone'))
|
|
109
|
+
deviceType = 'Mobile';
|
|
110
|
+
else if (ua.includes('tablet') || ua.includes('ipad'))
|
|
111
|
+
deviceType = 'Tablet';
|
|
112
|
+
return { browser, os, deviceType };
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Extract client IP from request
|
|
116
|
+
* Priority:
|
|
117
|
+
* 1. X-Forwarded-For header (proxy)
|
|
118
|
+
* 2. X-Real-IP header (nginx)
|
|
119
|
+
* 3. CF-Connecting-IP (Cloudflare)
|
|
120
|
+
* 4. request.ip (Express native)
|
|
121
|
+
* 5. socket.remoteAddress (direct connection)
|
|
122
|
+
*/
|
|
123
|
+
getClientIp(request) {
|
|
124
|
+
// Check X-Forwarded-For header (most common with proxies)
|
|
125
|
+
const xForwardedFor = request.headers['x-forwarded-for'];
|
|
126
|
+
if (xForwardedFor) {
|
|
127
|
+
const ips = Array.isArray(xForwardedFor)
|
|
128
|
+
? xForwardedFor
|
|
129
|
+
: xForwardedFor.split(',');
|
|
130
|
+
return ips[0].trim();
|
|
131
|
+
}
|
|
132
|
+
// Check X-Real-IP header (nginx)
|
|
133
|
+
const xRealIp = request.headers['x-real-ip'];
|
|
134
|
+
if (xRealIp) {
|
|
135
|
+
return Array.isArray(xRealIp) ? xRealIp[0] : xRealIp;
|
|
136
|
+
}
|
|
137
|
+
// Check CF-Connecting-IP (Cloudflare)
|
|
138
|
+
const cfIp = request.headers['cf-connecting-ip'];
|
|
139
|
+
if (cfIp) {
|
|
140
|
+
return Array.isArray(cfIp) ? cfIp[0] : cfIp;
|
|
141
|
+
}
|
|
142
|
+
// Use Express native request.ip (handles proxies if trust proxy is set)
|
|
143
|
+
if (request.ip) {
|
|
144
|
+
return request.ip;
|
|
145
|
+
}
|
|
146
|
+
// Fallback to socket remote address
|
|
147
|
+
const socketIp = (request.socket.remoteAddress || '').replace(/^.*:/, '');
|
|
148
|
+
return socketIp || 'unknown';
|
|
43
149
|
}
|
|
44
150
|
};
|
|
45
151
|
exports.AuthController = AuthController;
|
|
@@ -84,10 +190,11 @@ __decorate([
|
|
|
84
190
|
}
|
|
85
191
|
}
|
|
86
192
|
}),
|
|
87
|
-
(0, swagger_1.ApiUnauthorizedResponse)({ description: 'Invalid credentials' }),
|
|
88
|
-
__param(0, (0, common_1.
|
|
193
|
+
(0, swagger_1.ApiUnauthorizedResponse)({ description: 'Invalid credentials or IP not allowed' }),
|
|
194
|
+
__param(0, (0, common_1.Req)()),
|
|
195
|
+
__param(1, (0, common_1.Body)()),
|
|
89
196
|
__metadata("design:type", Function),
|
|
90
|
-
__metadata("design:paramtypes", [login_dto_1.LoginDto]),
|
|
197
|
+
__metadata("design:paramtypes", [Object, login_dto_1.LoginDto]),
|
|
91
198
|
__metadata("design:returntype", Promise)
|
|
92
199
|
], AuthController.prototype, "login", null);
|
|
93
200
|
exports.AuthController = AuthController = __decorate([
|
package/dist/auth.module.js
CHANGED
|
@@ -20,7 +20,6 @@ const feature_guard_1 = require("./guards/feature.guard");
|
|
|
20
20
|
const route_guard_1 = require("./guards/route.guard");
|
|
21
21
|
const permission_guard_1 = require("./guards/permission.guard");
|
|
22
22
|
const api_key_guard_1 = require("./guards/api-key.guard");
|
|
23
|
-
const encryption_service_1 = require("./services/encryption.service");
|
|
24
23
|
exports.AUTH_CORE_OPTIONS = 'AUTH_CORE_OPTIONS';
|
|
25
24
|
// @Global()
|
|
26
25
|
// @Module({})
|
|
@@ -116,7 +115,6 @@ let AuthCoreModule = AuthCoreModule_1 = class AuthCoreModule {
|
|
|
116
115
|
useFactory: (opts) => opts.repositories?.apiKeyRepo || null,
|
|
117
116
|
inject: [exports.AUTH_CORE_OPTIONS],
|
|
118
117
|
},
|
|
119
|
-
encryption_service_1.EncryptionService,
|
|
120
118
|
auth_service_1.AuthService,
|
|
121
119
|
jwt_strategy_1.JwtStrategy,
|
|
122
120
|
jwt_guard_1.JwtAuthGuard,
|
|
@@ -135,7 +133,6 @@ let AuthCoreModule = AuthCoreModule_1 = class AuthCoreModule {
|
|
|
135
133
|
'API_KEY_REPOSITORY',
|
|
136
134
|
jwt_1.JwtModule,
|
|
137
135
|
auth_service_1.AuthService,
|
|
138
|
-
encryption_service_1.EncryptionService,
|
|
139
136
|
jwt_strategy_1.JwtStrategy,
|
|
140
137
|
jwt_guard_1.JwtAuthGuard,
|
|
141
138
|
module_guard_1.ModuleGuard,
|
package/dist/auth.service.d.ts
CHANGED
|
@@ -25,10 +25,39 @@ export declare class AuthService {
|
|
|
25
25
|
private readonly featureAccessRepo;
|
|
26
26
|
private readonly moduleAccessRepo;
|
|
27
27
|
private readonly screenPermissionRepo;
|
|
28
|
+
private readonly ipRestrictionsRepo;
|
|
29
|
+
private readonly userLastLoginRepo;
|
|
30
|
+
private readonly employeeWorkProfileRepo;
|
|
31
|
+
private uploadPhotoDir;
|
|
28
32
|
constructor(jwtService: JwtService, options: AuthCoreOptions);
|
|
29
|
-
validateUser(email: string, password: string): Promise<User | null>;
|
|
33
|
+
validateUser(email: string, password: string, clientIp?: string): Promise<User | null>;
|
|
34
|
+
/**
|
|
35
|
+
* Validate IP restriction for a user
|
|
36
|
+
*
|
|
37
|
+
* Logic:
|
|
38
|
+
* 1. Check if user has any IP restrictions (is_active = 1)
|
|
39
|
+
* 2. If NO restrictions exist → Allow login (return true)
|
|
40
|
+
* 3. If restrictions exist → Check if requestIp matches any allowed IP
|
|
41
|
+
* 4. If match found → Allow login (return true)
|
|
42
|
+
* 5. If NO match → Deny login (return false)
|
|
43
|
+
*/
|
|
44
|
+
private validateIpRestriction;
|
|
30
45
|
hasModuleAccess(userId: number, moduleId: number): Promise<boolean>;
|
|
31
46
|
getPermissions(userId: number): Promise<PermissionsTree>;
|
|
47
|
+
/**
|
|
48
|
+
* Save user last login details
|
|
49
|
+
* Updates the tbl_user_last_login table with latest login info
|
|
50
|
+
*/
|
|
51
|
+
saveLastLogin(user: User, clientIp: string, loginStatus?: 'success' | 'failed' | 'blocked', failureReason?: string, additionalData?: {
|
|
52
|
+
browser?: string;
|
|
53
|
+
deviceType?: string;
|
|
54
|
+
operatingSystem?: string;
|
|
55
|
+
userAgent?: string;
|
|
56
|
+
location?: string;
|
|
57
|
+
moduleId?: number;
|
|
58
|
+
ipAddressName?: string;
|
|
59
|
+
metadata?: Record<string, any>;
|
|
60
|
+
}): Promise<void>;
|
|
32
61
|
login(user: User, selectedModuleId?: number): Promise<{
|
|
33
62
|
status: boolean;
|
|
34
63
|
message: string;
|
|
@@ -47,6 +76,11 @@ export declare class AuthService {
|
|
|
47
76
|
employeeId: number;
|
|
48
77
|
parentId: number;
|
|
49
78
|
referenceId: number;
|
|
79
|
+
branchId: any;
|
|
80
|
+
dispatchId: any;
|
|
81
|
+
departmentId: any;
|
|
82
|
+
designationId: any;
|
|
83
|
+
profile_photo_url: string;
|
|
50
84
|
};
|
|
51
85
|
};
|
|
52
86
|
access_token: string;
|
package/dist/auth.service.js
CHANGED
|
@@ -54,6 +54,7 @@ let AuthService = class AuthService {
|
|
|
54
54
|
constructor(jwtService, options) {
|
|
55
55
|
this.jwtService = jwtService;
|
|
56
56
|
this.options = options;
|
|
57
|
+
this.uploadPhotoDir = './uploads/organization/photos';
|
|
57
58
|
const { repositories } = options;
|
|
58
59
|
this.userRepo = repositories.userRepo;
|
|
59
60
|
this.roleRepo = repositories.roleRepo;
|
|
@@ -63,13 +64,76 @@ let AuthService = class AuthService {
|
|
|
63
64
|
this.featureAccessRepo = repositories.featureAccessRepo;
|
|
64
65
|
this.moduleAccessRepo = repositories.moduleAccessRepo;
|
|
65
66
|
this.screenPermissionRepo = repositories.screenPermissionRepo;
|
|
67
|
+
// Optional repositories
|
|
68
|
+
this.ipRestrictionsRepo = repositories.ipRestrictionsRepo || null;
|
|
69
|
+
this.userLastLoginRepo = repositories.userLastLoginRepo || null;
|
|
70
|
+
this.employeeWorkProfileRepo = repositories.employeeWorkProfileRepo || null;
|
|
66
71
|
}
|
|
67
|
-
async validateUser(email, password) {
|
|
72
|
+
async validateUser(email, password, clientIp) {
|
|
68
73
|
const user = await this.userRepo.findOne({ where: { email } });
|
|
69
74
|
if (!user)
|
|
70
75
|
return null;
|
|
71
76
|
const isValid = await bcrypt.compare(password, user.password);
|
|
72
|
-
|
|
77
|
+
if (!isValid)
|
|
78
|
+
return null;
|
|
79
|
+
// Check IP restrictions if provided and repository is available
|
|
80
|
+
if (clientIp && this.ipRestrictionsRepo) {
|
|
81
|
+
const ipAllowed = await this.validateIpRestriction(user.id, clientIp);
|
|
82
|
+
if (!ipAllowed) {
|
|
83
|
+
// IP restriction exists but doesn't match - return null to block login
|
|
84
|
+
return null;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
return user;
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Validate IP restriction for a user
|
|
91
|
+
*
|
|
92
|
+
* Logic:
|
|
93
|
+
* 1. Check if user has any IP restrictions (is_active = 1)
|
|
94
|
+
* 2. If NO restrictions exist → Allow login (return true)
|
|
95
|
+
* 3. If restrictions exist → Check if requestIp matches any allowed IP
|
|
96
|
+
* 4. If match found → Allow login (return true)
|
|
97
|
+
* 5. If NO match → Deny login (return false)
|
|
98
|
+
*/
|
|
99
|
+
async validateIpRestriction(userId, requestIp) {
|
|
100
|
+
if (!this.ipRestrictionsRepo) {
|
|
101
|
+
// No IP restrictions repository configured - allow login
|
|
102
|
+
return true;
|
|
103
|
+
}
|
|
104
|
+
try {
|
|
105
|
+
// Get all active IP restrictions for this user
|
|
106
|
+
const restrictions = await this.ipRestrictionsRepo.find({
|
|
107
|
+
where: {
|
|
108
|
+
user_id: userId,
|
|
109
|
+
},
|
|
110
|
+
});
|
|
111
|
+
// If no restrictions exist, allow login
|
|
112
|
+
if (!restrictions || restrictions.length === 0) {
|
|
113
|
+
console.log(`✅ User ${userId}: No IP restrictions configured - Allow login`);
|
|
114
|
+
return true;
|
|
115
|
+
}
|
|
116
|
+
// Check if request IP matches any allowed IP
|
|
117
|
+
const ipMatches = restrictions.some((restriction) => {
|
|
118
|
+
// Handle both property name variations
|
|
119
|
+
const allowedIp = restriction.allowed_ip_address || restriction.ip_address;
|
|
120
|
+
return allowedIp === requestIp;
|
|
121
|
+
});
|
|
122
|
+
if (ipMatches) {
|
|
123
|
+
console.log(`✅ User ${userId}: IP ${requestIp} matches allowed IP - Allow login`);
|
|
124
|
+
return true;
|
|
125
|
+
}
|
|
126
|
+
// IP doesn't match any allowed IP
|
|
127
|
+
const allowedIps = restrictions.map((r) => r.allowed_ip_address || r.ip_address).join(', ');
|
|
128
|
+
console.log(`❌ User ${userId}: IP ${requestIp} does not match allowed IPs - Deny login`);
|
|
129
|
+
console.log(` Allowed IPs: ${allowedIps}`);
|
|
130
|
+
return false;
|
|
131
|
+
}
|
|
132
|
+
catch (error) {
|
|
133
|
+
console.error('Error validating IP restriction:', error);
|
|
134
|
+
// On error, allow login (fail open)
|
|
135
|
+
return true;
|
|
136
|
+
}
|
|
73
137
|
}
|
|
74
138
|
async hasModuleAccess(userId, moduleId) {
|
|
75
139
|
if (!Number.isFinite(moduleId))
|
|
@@ -82,11 +146,66 @@ let AuthService = class AuthService {
|
|
|
82
146
|
async getPermissions(userId) {
|
|
83
147
|
return this.loadPermissions(userId);
|
|
84
148
|
}
|
|
149
|
+
/**
|
|
150
|
+
* Save user last login details
|
|
151
|
+
* Updates the tbl_user_last_login table with latest login info
|
|
152
|
+
*/
|
|
153
|
+
async saveLastLogin(user, clientIp, loginStatus = 'success', failureReason, additionalData) {
|
|
154
|
+
if (!this.userLastLoginRepo) {
|
|
155
|
+
// Last login tracking not configured
|
|
156
|
+
return;
|
|
157
|
+
}
|
|
158
|
+
try {
|
|
159
|
+
const lastLoginData = {
|
|
160
|
+
user_id: user.id,
|
|
161
|
+
email: user.email,
|
|
162
|
+
first_name: user.firstName,
|
|
163
|
+
last_name: user.lastName,
|
|
164
|
+
ip_address: clientIp,
|
|
165
|
+
login_status: loginStatus,
|
|
166
|
+
failure_reason: failureReason,
|
|
167
|
+
login_time: new Date(),
|
|
168
|
+
...additionalData,
|
|
169
|
+
};
|
|
170
|
+
// Upsert: Update if exists, insert if not
|
|
171
|
+
await this.userLastLoginRepo.upsert(lastLoginData, {
|
|
172
|
+
conflictPaths: ['user_id'],
|
|
173
|
+
skipUpdateIfNoValuesChanged: true,
|
|
174
|
+
});
|
|
175
|
+
console.log(`📝 Last login details saved for user ${user.id} (${loginStatus})`);
|
|
176
|
+
}
|
|
177
|
+
catch (error) {
|
|
178
|
+
console.error('Error saving last login details:', error);
|
|
179
|
+
// Don't throw error - this shouldn't block login
|
|
180
|
+
}
|
|
181
|
+
}
|
|
85
182
|
async login(user, selectedModuleId) {
|
|
86
183
|
const permissionTree = await this.loadPermissions(user.id);
|
|
87
184
|
const role = await this.roleRepo.findOne({ where: { id: user.roleId } });
|
|
88
185
|
const roleName = role?.roleName || null;
|
|
89
186
|
const effectiveModuleId = Number.isFinite(selectedModuleId) ? selectedModuleId : user.moduleId ?? null;
|
|
187
|
+
// Fetch workprofile/employee details from EmployeeWorkProfileEntity
|
|
188
|
+
let branchId = null;
|
|
189
|
+
let dispatchId = null;
|
|
190
|
+
let departmentId = null;
|
|
191
|
+
let designationId = null;
|
|
192
|
+
if (this.employeeWorkProfileRepo) {
|
|
193
|
+
try {
|
|
194
|
+
const workProfile = await this.employeeWorkProfileRepo.findOne({
|
|
195
|
+
where: { employee_id: user.referenceId },
|
|
196
|
+
});
|
|
197
|
+
if (workProfile) {
|
|
198
|
+
branchId = workProfile?.branch_id || null;
|
|
199
|
+
dispatchId = workProfile?.dispatch_id || null;
|
|
200
|
+
departmentId = workProfile?.department_id || null;
|
|
201
|
+
designationId = workProfile?.designation_id || null;
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
catch (error) {
|
|
205
|
+
console.error('Error fetching work profile:', error);
|
|
206
|
+
// Continue with null values if fetch fails
|
|
207
|
+
}
|
|
208
|
+
}
|
|
90
209
|
const payload = {
|
|
91
210
|
id: user.id,
|
|
92
211
|
email: user.email,
|
|
@@ -102,6 +221,10 @@ let AuthService = class AuthService {
|
|
|
102
221
|
permissions: permissionTree,
|
|
103
222
|
parentId: user.parentId,
|
|
104
223
|
referenceId: user.referenceId,
|
|
224
|
+
branchId,
|
|
225
|
+
dispatchId,
|
|
226
|
+
departmentId,
|
|
227
|
+
designationId,
|
|
105
228
|
};
|
|
106
229
|
return {
|
|
107
230
|
status: true,
|
|
@@ -121,6 +244,11 @@ let AuthService = class AuthService {
|
|
|
121
244
|
employeeId: user.referenceId,
|
|
122
245
|
parentId: user.parentId,
|
|
123
246
|
referenceId: user.referenceId,
|
|
247
|
+
branchId,
|
|
248
|
+
dispatchId,
|
|
249
|
+
departmentId,
|
|
250
|
+
designationId,
|
|
251
|
+
profile_photo_url: `${this.uploadPhotoDir}`,
|
|
124
252
|
},
|
|
125
253
|
},
|
|
126
254
|
access_token: this.jwtService.sign(payload),
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export declare class EmployeeIPAccessEntity {
|
|
2
|
+
id: number;
|
|
3
|
+
user_id: number;
|
|
4
|
+
employee_id: number;
|
|
5
|
+
ip_address: string;
|
|
6
|
+
ip_address_name?: string;
|
|
7
|
+
created_at: Date;
|
|
8
|
+
created_by: number;
|
|
9
|
+
updated_at: Date;
|
|
10
|
+
updated_by: number;
|
|
11
|
+
deleted_by: number;
|
|
12
|
+
deleted_at: Date;
|
|
13
|
+
}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
9
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.EmployeeIPAccessEntity = void 0;
|
|
13
|
+
const typeorm_1 = require("typeorm");
|
|
14
|
+
let EmployeeIPAccessEntity = class EmployeeIPAccessEntity {
|
|
15
|
+
};
|
|
16
|
+
exports.EmployeeIPAccessEntity = EmployeeIPAccessEntity;
|
|
17
|
+
__decorate([
|
|
18
|
+
(0, typeorm_1.PrimaryGeneratedColumn)(),
|
|
19
|
+
__metadata("design:type", Number)
|
|
20
|
+
], EmployeeIPAccessEntity.prototype, "id", void 0);
|
|
21
|
+
__decorate([
|
|
22
|
+
(0, typeorm_1.Column)({ name: 'user_id', type: 'int' }),
|
|
23
|
+
__metadata("design:type", Number)
|
|
24
|
+
], EmployeeIPAccessEntity.prototype, "user_id", void 0);
|
|
25
|
+
__decorate([
|
|
26
|
+
(0, typeorm_1.Column)({ name: 'employee_id', type: 'int' }),
|
|
27
|
+
__metadata("design:type", Number)
|
|
28
|
+
], EmployeeIPAccessEntity.prototype, "employee_id", void 0);
|
|
29
|
+
__decorate([
|
|
30
|
+
(0, typeorm_1.Column)({
|
|
31
|
+
name: 'ip_address',
|
|
32
|
+
type: 'inet',
|
|
33
|
+
nullable: false,
|
|
34
|
+
comment: 'IPv4 / IPv6 / CIDR notation',
|
|
35
|
+
}),
|
|
36
|
+
__metadata("design:type", String)
|
|
37
|
+
], EmployeeIPAccessEntity.prototype, "ip_address", void 0);
|
|
38
|
+
__decorate([
|
|
39
|
+
(0, typeorm_1.Column)({
|
|
40
|
+
name: 'ip_address_name',
|
|
41
|
+
type: 'varchar',
|
|
42
|
+
length: 255,
|
|
43
|
+
nullable: true,
|
|
44
|
+
}),
|
|
45
|
+
__metadata("design:type", String)
|
|
46
|
+
], EmployeeIPAccessEntity.prototype, "ip_address_name", void 0);
|
|
47
|
+
__decorate([
|
|
48
|
+
(0, typeorm_1.CreateDateColumn)({ type: 'timestamp' }),
|
|
49
|
+
__metadata("design:type", Date)
|
|
50
|
+
], EmployeeIPAccessEntity.prototype, "created_at", void 0);
|
|
51
|
+
__decorate([
|
|
52
|
+
(0, typeorm_1.Column)({ type: 'int', nullable: true }),
|
|
53
|
+
__metadata("design:type", Number)
|
|
54
|
+
], EmployeeIPAccessEntity.prototype, "created_by", void 0);
|
|
55
|
+
__decorate([
|
|
56
|
+
(0, typeorm_1.UpdateDateColumn)({ type: 'timestamp', nullable: true }),
|
|
57
|
+
__metadata("design:type", Date)
|
|
58
|
+
], EmployeeIPAccessEntity.prototype, "updated_at", void 0);
|
|
59
|
+
__decorate([
|
|
60
|
+
(0, typeorm_1.Column)({ type: 'int', nullable: true }),
|
|
61
|
+
__metadata("design:type", Number)
|
|
62
|
+
], EmployeeIPAccessEntity.prototype, "updated_by", void 0);
|
|
63
|
+
__decorate([
|
|
64
|
+
(0, typeorm_1.Column)({ type: 'int', nullable: true }),
|
|
65
|
+
__metadata("design:type", Number)
|
|
66
|
+
], EmployeeIPAccessEntity.prototype, "deleted_by", void 0);
|
|
67
|
+
__decorate([
|
|
68
|
+
(0, typeorm_1.DeleteDateColumn)({ type: 'timestamp', nullable: true }),
|
|
69
|
+
__metadata("design:type", Date)
|
|
70
|
+
], EmployeeIPAccessEntity.prototype, "deleted_at", void 0);
|
|
71
|
+
exports.EmployeeIPAccessEntity = EmployeeIPAccessEntity = __decorate([
|
|
72
|
+
(0, typeorm_1.Entity)('tbl_hr_user_ip_access')
|
|
73
|
+
], EmployeeIPAccessEntity);
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
export declare class UserLastLoginEntity {
|
|
2
|
+
id: number;
|
|
3
|
+
user_id: number;
|
|
4
|
+
email: string;
|
|
5
|
+
first_name: string;
|
|
6
|
+
last_name: string;
|
|
7
|
+
ip_address: string;
|
|
8
|
+
ip_address_name?: string;
|
|
9
|
+
browser: string;
|
|
10
|
+
device_type: string;
|
|
11
|
+
operating_system: string;
|
|
12
|
+
user_agent: string;
|
|
13
|
+
location: string;
|
|
14
|
+
module_id: number;
|
|
15
|
+
login_status: 'success' | 'failed' | 'blocked';
|
|
16
|
+
failure_reason: string;
|
|
17
|
+
session_duration_ms: number;
|
|
18
|
+
metadata: Record<string, any>;
|
|
19
|
+
login_time: Date;
|
|
20
|
+
logout_time: Date;
|
|
21
|
+
created_at: Date;
|
|
22
|
+
created_by: number;
|
|
23
|
+
updated_at: Date;
|
|
24
|
+
updated_by: number;
|
|
25
|
+
deleted_by: number;
|
|
26
|
+
deleted_at: Date;
|
|
27
|
+
}
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
9
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.UserLastLoginEntity = void 0;
|
|
13
|
+
const typeorm_1 = require("typeorm");
|
|
14
|
+
let UserLastLoginEntity = class UserLastLoginEntity {
|
|
15
|
+
};
|
|
16
|
+
exports.UserLastLoginEntity = UserLastLoginEntity;
|
|
17
|
+
__decorate([
|
|
18
|
+
(0, typeorm_1.PrimaryGeneratedColumn)(),
|
|
19
|
+
__metadata("design:type", Number)
|
|
20
|
+
], UserLastLoginEntity.prototype, "id", void 0);
|
|
21
|
+
__decorate([
|
|
22
|
+
(0, typeorm_1.Column)({ type: 'int', nullable: false }),
|
|
23
|
+
__metadata("design:type", Number)
|
|
24
|
+
], UserLastLoginEntity.prototype, "user_id", void 0);
|
|
25
|
+
__decorate([
|
|
26
|
+
(0, typeorm_1.Column)({ length: 250, nullable: true }),
|
|
27
|
+
__metadata("design:type", String)
|
|
28
|
+
], UserLastLoginEntity.prototype, "email", void 0);
|
|
29
|
+
__decorate([
|
|
30
|
+
(0, typeorm_1.Column)({ length: 100, nullable: true }),
|
|
31
|
+
__metadata("design:type", String)
|
|
32
|
+
], UserLastLoginEntity.prototype, "first_name", void 0);
|
|
33
|
+
__decorate([
|
|
34
|
+
(0, typeorm_1.Column)({ length: 100, nullable: true }),
|
|
35
|
+
__metadata("design:type", String)
|
|
36
|
+
], UserLastLoginEntity.prototype, "last_name", void 0);
|
|
37
|
+
__decorate([
|
|
38
|
+
(0, typeorm_1.Column)({
|
|
39
|
+
name: 'ip_address',
|
|
40
|
+
type: 'varchar',
|
|
41
|
+
length: 45,
|
|
42
|
+
nullable: true,
|
|
43
|
+
comment: 'IPv4 or IPv6',
|
|
44
|
+
}),
|
|
45
|
+
__metadata("design:type", String)
|
|
46
|
+
], UserLastLoginEntity.prototype, "ip_address", void 0);
|
|
47
|
+
__decorate([
|
|
48
|
+
(0, typeorm_1.Column)({
|
|
49
|
+
name: 'ip_address_name',
|
|
50
|
+
type: 'varchar',
|
|
51
|
+
length: 255,
|
|
52
|
+
nullable: true,
|
|
53
|
+
comment: 'Location/Name of IP (e.g., Office, Home)',
|
|
54
|
+
}),
|
|
55
|
+
__metadata("design:type", String)
|
|
56
|
+
], UserLastLoginEntity.prototype, "ip_address_name", void 0);
|
|
57
|
+
__decorate([
|
|
58
|
+
(0, typeorm_1.Column)({ length: 100, nullable: true }),
|
|
59
|
+
__metadata("design:type", String)
|
|
60
|
+
], UserLastLoginEntity.prototype, "browser", void 0);
|
|
61
|
+
__decorate([
|
|
62
|
+
(0, typeorm_1.Column)({ length: 100, nullable: true }),
|
|
63
|
+
__metadata("design:type", String)
|
|
64
|
+
], UserLastLoginEntity.prototype, "device_type", void 0);
|
|
65
|
+
__decorate([
|
|
66
|
+
(0, typeorm_1.Column)({ length: 100, nullable: true }),
|
|
67
|
+
__metadata("design:type", String)
|
|
68
|
+
], UserLastLoginEntity.prototype, "operating_system", void 0);
|
|
69
|
+
__decorate([
|
|
70
|
+
(0, typeorm_1.Column)({ type: 'text', nullable: true }),
|
|
71
|
+
__metadata("design:type", String)
|
|
72
|
+
], UserLastLoginEntity.prototype, "user_agent", void 0);
|
|
73
|
+
__decorate([
|
|
74
|
+
(0, typeorm_1.Column)({ length: 255, nullable: true }),
|
|
75
|
+
__metadata("design:type", String)
|
|
76
|
+
], UserLastLoginEntity.prototype, "location", void 0);
|
|
77
|
+
__decorate([
|
|
78
|
+
(0, typeorm_1.Column)({
|
|
79
|
+
name: 'module_id',
|
|
80
|
+
type: 'int',
|
|
81
|
+
nullable: true,
|
|
82
|
+
}),
|
|
83
|
+
__metadata("design:type", Number)
|
|
84
|
+
], UserLastLoginEntity.prototype, "module_id", void 0);
|
|
85
|
+
__decorate([
|
|
86
|
+
(0, typeorm_1.Column)({
|
|
87
|
+
name: 'login_status',
|
|
88
|
+
type: 'enum',
|
|
89
|
+
enum: ['success', 'failed', 'blocked'],
|
|
90
|
+
default: 'success',
|
|
91
|
+
}),
|
|
92
|
+
__metadata("design:type", String)
|
|
93
|
+
], UserLastLoginEntity.prototype, "login_status", void 0);
|
|
94
|
+
__decorate([
|
|
95
|
+
(0, typeorm_1.Column)({
|
|
96
|
+
type: 'text',
|
|
97
|
+
nullable: true,
|
|
98
|
+
comment: 'Reason for failure or blocking (e.g., IP not whitelisted, wrong password)',
|
|
99
|
+
}),
|
|
100
|
+
__metadata("design:type", String)
|
|
101
|
+
], UserLastLoginEntity.prototype, "failure_reason", void 0);
|
|
102
|
+
__decorate([
|
|
103
|
+
(0, typeorm_1.Column)({ type: 'bigint', nullable: true }),
|
|
104
|
+
__metadata("design:type", Number)
|
|
105
|
+
], UserLastLoginEntity.prototype, "session_duration_ms", void 0);
|
|
106
|
+
__decorate([
|
|
107
|
+
(0, typeorm_1.Column)({ type: 'json', nullable: true }),
|
|
108
|
+
__metadata("design:type", Object)
|
|
109
|
+
], UserLastLoginEntity.prototype, "metadata", void 0);
|
|
110
|
+
__decorate([
|
|
111
|
+
(0, typeorm_1.Column)({ type: 'timestamp', nullable: true }),
|
|
112
|
+
__metadata("design:type", Date)
|
|
113
|
+
], UserLastLoginEntity.prototype, "login_time", void 0);
|
|
114
|
+
__decorate([
|
|
115
|
+
(0, typeorm_1.Column)({ type: 'timestamp', nullable: true }),
|
|
116
|
+
__metadata("design:type", Date)
|
|
117
|
+
], UserLastLoginEntity.prototype, "logout_time", void 0);
|
|
118
|
+
__decorate([
|
|
119
|
+
(0, typeorm_1.CreateDateColumn)({ type: 'timestamp' }),
|
|
120
|
+
__metadata("design:type", Date)
|
|
121
|
+
], UserLastLoginEntity.prototype, "created_at", void 0);
|
|
122
|
+
__decorate([
|
|
123
|
+
(0, typeorm_1.Column)({ type: 'int', nullable: true }),
|
|
124
|
+
__metadata("design:type", Number)
|
|
125
|
+
], UserLastLoginEntity.prototype, "created_by", void 0);
|
|
126
|
+
__decorate([
|
|
127
|
+
(0, typeorm_1.UpdateDateColumn)({ type: 'timestamp', nullable: true }),
|
|
128
|
+
__metadata("design:type", Date)
|
|
129
|
+
], UserLastLoginEntity.prototype, "updated_at", void 0);
|
|
130
|
+
__decorate([
|
|
131
|
+
(0, typeorm_1.Column)({ type: 'int', nullable: true }),
|
|
132
|
+
__metadata("design:type", Number)
|
|
133
|
+
], UserLastLoginEntity.prototype, "updated_by", void 0);
|
|
134
|
+
__decorate([
|
|
135
|
+
(0, typeorm_1.Column)({ type: 'int', nullable: true }),
|
|
136
|
+
__metadata("design:type", Number)
|
|
137
|
+
], UserLastLoginEntity.prototype, "deleted_by", void 0);
|
|
138
|
+
__decorate([
|
|
139
|
+
(0, typeorm_1.DeleteDateColumn)({ type: 'timestamp', nullable: true }),
|
|
140
|
+
__metadata("design:type", Date)
|
|
141
|
+
], UserLastLoginEntity.prototype, "deleted_at", void 0);
|
|
142
|
+
exports.UserLastLoginEntity = UserLastLoginEntity = __decorate([
|
|
143
|
+
(0, typeorm_1.Entity)('tbl_user_last_login'),
|
|
144
|
+
(0, typeorm_1.Index)(['user_id']),
|
|
145
|
+
(0, typeorm_1.Index)(['login_time']),
|
|
146
|
+
(0, typeorm_1.Unique)(['user_id'])
|
|
147
|
+
], UserLastLoginEntity);
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
export declare enum EmployeeType {
|
|
2
|
+
PERMANENT = "PERMANENT",
|
|
3
|
+
CONTRACT = "CONTRACT",
|
|
4
|
+
INTERN = "INTERN",
|
|
5
|
+
CONSULTANT = "CONSULTANT"
|
|
6
|
+
}
|
|
7
|
+
export declare enum EmployeeStatus {
|
|
8
|
+
ACTIVE = "ACTIVE",
|
|
9
|
+
INACTIVE = "INACTIVE",
|
|
10
|
+
ON_LEAVE = "ON_LEAVE"
|
|
11
|
+
}
|
|
12
|
+
export declare enum WeekOffType {
|
|
13
|
+
FIXED = "FIXED",
|
|
14
|
+
ROTATIONAL = "ROTATIONAL",
|
|
15
|
+
FLEXIBLE = "FLEXIBLE"
|
|
16
|
+
}
|
|
17
|
+
export declare enum WeekOffBasedOn {
|
|
18
|
+
WORK_LOCATION = "WORK_LOCATION",
|
|
19
|
+
SHIFT = "SHIFT"
|
|
20
|
+
}
|
|
21
|
+
export declare class EmployeeWorkProfileEntity {
|
|
22
|
+
id: number;
|
|
23
|
+
employee_id: number;
|
|
24
|
+
department_id: number;
|
|
25
|
+
designation_id: number;
|
|
26
|
+
employee_type: EmployeeType;
|
|
27
|
+
employee_status?: EmployeeStatus;
|
|
28
|
+
shift_id: number;
|
|
29
|
+
role_id: number;
|
|
30
|
+
agency?: string;
|
|
31
|
+
reporting_manager_id?: number | null;
|
|
32
|
+
l2_manager_id?: number | null;
|
|
33
|
+
joining_date: Date;
|
|
34
|
+
resignation_date?: Date;
|
|
35
|
+
branch_id: number;
|
|
36
|
+
dispatch_center_id: number;
|
|
37
|
+
cost_center_id: number;
|
|
38
|
+
week_off_type: WeekOffType;
|
|
39
|
+
week_off_based_on: WeekOffBasedOn;
|
|
40
|
+
bioMetricCode: string;
|
|
41
|
+
linkedInProfile: string;
|
|
42
|
+
created_at: Date;
|
|
43
|
+
created_by?: number;
|
|
44
|
+
updated_at?: Date;
|
|
45
|
+
updated_by?: number;
|
|
46
|
+
deleted_by?: number;
|
|
47
|
+
deleted_at?: Date;
|
|
48
|
+
}
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
9
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.EmployeeWorkProfileEntity = exports.WeekOffBasedOn = exports.WeekOffType = exports.EmployeeStatus = exports.EmployeeType = void 0;
|
|
13
|
+
const typeorm_1 = require("typeorm");
|
|
14
|
+
var EmployeeType;
|
|
15
|
+
(function (EmployeeType) {
|
|
16
|
+
EmployeeType["PERMANENT"] = "PERMANENT";
|
|
17
|
+
EmployeeType["CONTRACT"] = "CONTRACT";
|
|
18
|
+
EmployeeType["INTERN"] = "INTERN";
|
|
19
|
+
EmployeeType["CONSULTANT"] = "CONSULTANT";
|
|
20
|
+
})(EmployeeType || (exports.EmployeeType = EmployeeType = {}));
|
|
21
|
+
var EmployeeStatus;
|
|
22
|
+
(function (EmployeeStatus) {
|
|
23
|
+
EmployeeStatus["ACTIVE"] = "ACTIVE";
|
|
24
|
+
EmployeeStatus["INACTIVE"] = "INACTIVE";
|
|
25
|
+
EmployeeStatus["ON_LEAVE"] = "ON_LEAVE";
|
|
26
|
+
})(EmployeeStatus || (exports.EmployeeStatus = EmployeeStatus = {}));
|
|
27
|
+
// export enum WorkngShift {
|
|
28
|
+
// DAY = 'DAY',
|
|
29
|
+
// NIGHT = 'NIGHT',
|
|
30
|
+
// }
|
|
31
|
+
var WeekOffType;
|
|
32
|
+
(function (WeekOffType) {
|
|
33
|
+
WeekOffType["FIXED"] = "FIXED";
|
|
34
|
+
WeekOffType["ROTATIONAL"] = "ROTATIONAL";
|
|
35
|
+
WeekOffType["FLEXIBLE"] = "FLEXIBLE";
|
|
36
|
+
})(WeekOffType || (exports.WeekOffType = WeekOffType = {}));
|
|
37
|
+
var WeekOffBasedOn;
|
|
38
|
+
(function (WeekOffBasedOn) {
|
|
39
|
+
WeekOffBasedOn["WORK_LOCATION"] = "WORK_LOCATION";
|
|
40
|
+
WeekOffBasedOn["SHIFT"] = "SHIFT";
|
|
41
|
+
})(WeekOffBasedOn || (exports.WeekOffBasedOn = WeekOffBasedOn = {}));
|
|
42
|
+
let EmployeeWorkProfileEntity = class EmployeeWorkProfileEntity {
|
|
43
|
+
};
|
|
44
|
+
exports.EmployeeWorkProfileEntity = EmployeeWorkProfileEntity;
|
|
45
|
+
__decorate([
|
|
46
|
+
(0, typeorm_1.PrimaryGeneratedColumn)(),
|
|
47
|
+
__metadata("design:type", Number)
|
|
48
|
+
], EmployeeWorkProfileEntity.prototype, "id", void 0);
|
|
49
|
+
__decorate([
|
|
50
|
+
(0, typeorm_1.Column)({ name: 'employee_id', type: 'int' }),
|
|
51
|
+
__metadata("design:type", Number)
|
|
52
|
+
], EmployeeWorkProfileEntity.prototype, "employee_id", void 0);
|
|
53
|
+
__decorate([
|
|
54
|
+
(0, typeorm_1.Column)({ name: 'department_id', type: 'int' }),
|
|
55
|
+
__metadata("design:type", Number)
|
|
56
|
+
], EmployeeWorkProfileEntity.prototype, "department_id", void 0);
|
|
57
|
+
__decorate([
|
|
58
|
+
(0, typeorm_1.Column)({ name: 'designation_id', type: 'int' }),
|
|
59
|
+
__metadata("design:type", Number)
|
|
60
|
+
], EmployeeWorkProfileEntity.prototype, "designation_id", void 0);
|
|
61
|
+
__decorate([
|
|
62
|
+
(0, typeorm_1.Column)({ type: 'enum', enum: EmployeeType, nullable: false }),
|
|
63
|
+
__metadata("design:type", String)
|
|
64
|
+
], EmployeeWorkProfileEntity.prototype, "employee_type", void 0);
|
|
65
|
+
__decorate([
|
|
66
|
+
(0, typeorm_1.Column)({
|
|
67
|
+
type: 'enum',
|
|
68
|
+
enum: EmployeeStatus,
|
|
69
|
+
default: EmployeeStatus.ACTIVE,
|
|
70
|
+
nullable: true,
|
|
71
|
+
}),
|
|
72
|
+
__metadata("design:type", String)
|
|
73
|
+
], EmployeeWorkProfileEntity.prototype, "employee_status", void 0);
|
|
74
|
+
__decorate([
|
|
75
|
+
(0, typeorm_1.Column)({ name: 'shift_id', type: 'int', nullable: true }),
|
|
76
|
+
__metadata("design:type", Number)
|
|
77
|
+
], EmployeeWorkProfileEntity.prototype, "shift_id", void 0);
|
|
78
|
+
__decorate([
|
|
79
|
+
(0, typeorm_1.Column)({ name: 'role_id', type: 'int' }),
|
|
80
|
+
__metadata("design:type", Number)
|
|
81
|
+
], EmployeeWorkProfileEntity.prototype, "role_id", void 0);
|
|
82
|
+
__decorate([
|
|
83
|
+
(0, typeorm_1.Column)({ name: 'agency', type: 'varchar', nullable: true }),
|
|
84
|
+
__metadata("design:type", String)
|
|
85
|
+
], EmployeeWorkProfileEntity.prototype, "agency", void 0);
|
|
86
|
+
__decorate([
|
|
87
|
+
(0, typeorm_1.Column)({ name: 'reporting_manager_id', type: 'int', nullable: true }),
|
|
88
|
+
__metadata("design:type", Object)
|
|
89
|
+
], EmployeeWorkProfileEntity.prototype, "reporting_manager_id", void 0);
|
|
90
|
+
__decorate([
|
|
91
|
+
(0, typeorm_1.Column)({ name: 'l2_manager_id', type: 'int', nullable: true }),
|
|
92
|
+
__metadata("design:type", Object)
|
|
93
|
+
], EmployeeWorkProfileEntity.prototype, "l2_manager_id", void 0);
|
|
94
|
+
__decorate([
|
|
95
|
+
(0, typeorm_1.Column)({ type: 'date', nullable: false }),
|
|
96
|
+
__metadata("design:type", Date)
|
|
97
|
+
], EmployeeWorkProfileEntity.prototype, "joining_date", void 0);
|
|
98
|
+
__decorate([
|
|
99
|
+
(0, typeorm_1.Column)({ type: 'date', nullable: true }),
|
|
100
|
+
__metadata("design:type", Date)
|
|
101
|
+
], EmployeeWorkProfileEntity.prototype, "resignation_date", void 0);
|
|
102
|
+
__decorate([
|
|
103
|
+
(0, typeorm_1.Column)({ name: 'branch_id', type: 'int', nullable: true }),
|
|
104
|
+
__metadata("design:type", Number)
|
|
105
|
+
], EmployeeWorkProfileEntity.prototype, "branch_id", void 0);
|
|
106
|
+
__decorate([
|
|
107
|
+
(0, typeorm_1.Column)({ name: 'dispatch_center_id', type: 'int', nullable: true }),
|
|
108
|
+
__metadata("design:type", Number)
|
|
109
|
+
], EmployeeWorkProfileEntity.prototype, "dispatch_center_id", void 0);
|
|
110
|
+
__decorate([
|
|
111
|
+
(0, typeorm_1.Column)({ name: 'cost_center_id', type: 'int' }),
|
|
112
|
+
__metadata("design:type", Number)
|
|
113
|
+
], EmployeeWorkProfileEntity.prototype, "cost_center_id", void 0);
|
|
114
|
+
__decorate([
|
|
115
|
+
(0, typeorm_1.Column)({
|
|
116
|
+
type: 'enum',
|
|
117
|
+
enum: WeekOffType,
|
|
118
|
+
nullable: false,
|
|
119
|
+
}),
|
|
120
|
+
__metadata("design:type", String)
|
|
121
|
+
], EmployeeWorkProfileEntity.prototype, "week_off_type", void 0);
|
|
122
|
+
__decorate([
|
|
123
|
+
(0, typeorm_1.Column)({
|
|
124
|
+
type: 'enum',
|
|
125
|
+
enum: WeekOffBasedOn,
|
|
126
|
+
nullable: false,
|
|
127
|
+
}),
|
|
128
|
+
__metadata("design:type", String)
|
|
129
|
+
], EmployeeWorkProfileEntity.prototype, "week_off_based_on", void 0);
|
|
130
|
+
__decorate([
|
|
131
|
+
(0, typeorm_1.Column)({ length: 50, nullable: true }),
|
|
132
|
+
__metadata("design:type", String)
|
|
133
|
+
], EmployeeWorkProfileEntity.prototype, "bioMetricCode", void 0);
|
|
134
|
+
__decorate([
|
|
135
|
+
(0, typeorm_1.Column)({ length: 255, nullable: true }),
|
|
136
|
+
__metadata("design:type", String)
|
|
137
|
+
], EmployeeWorkProfileEntity.prototype, "linkedInProfile", void 0);
|
|
138
|
+
__decorate([
|
|
139
|
+
(0, typeorm_1.CreateDateColumn)({ type: 'timestamp' }),
|
|
140
|
+
__metadata("design:type", Date)
|
|
141
|
+
], EmployeeWorkProfileEntity.prototype, "created_at", void 0);
|
|
142
|
+
__decorate([
|
|
143
|
+
(0, typeorm_1.Column)({ type: 'int', nullable: true }),
|
|
144
|
+
__metadata("design:type", Number)
|
|
145
|
+
], EmployeeWorkProfileEntity.prototype, "created_by", void 0);
|
|
146
|
+
__decorate([
|
|
147
|
+
(0, typeorm_1.UpdateDateColumn)({ type: 'timestamp' }),
|
|
148
|
+
__metadata("design:type", Date)
|
|
149
|
+
], EmployeeWorkProfileEntity.prototype, "updated_at", void 0);
|
|
150
|
+
__decorate([
|
|
151
|
+
(0, typeorm_1.Column)({ type: 'int', nullable: true }),
|
|
152
|
+
__metadata("design:type", Number)
|
|
153
|
+
], EmployeeWorkProfileEntity.prototype, "updated_by", void 0);
|
|
154
|
+
__decorate([
|
|
155
|
+
(0, typeorm_1.Column)({ type: 'int', nullable: true }),
|
|
156
|
+
__metadata("design:type", Number)
|
|
157
|
+
], EmployeeWorkProfileEntity.prototype, "deleted_by", void 0);
|
|
158
|
+
__decorate([
|
|
159
|
+
(0, typeorm_1.DeleteDateColumn)({ type: 'timestamp', nullable: true }),
|
|
160
|
+
__metadata("design:type", Date)
|
|
161
|
+
], EmployeeWorkProfileEntity.prototype, "deleted_at", void 0);
|
|
162
|
+
exports.EmployeeWorkProfileEntity = EmployeeWorkProfileEntity = __decorate([
|
|
163
|
+
(0, typeorm_1.Entity)('tbl_hr_employee_work_profile'),
|
|
164
|
+
(0, typeorm_1.Unique)(['employee_id'])
|
|
165
|
+
], EmployeeWorkProfileEntity);
|
|
@@ -2,13 +2,11 @@ import { CanActivate, ExecutionContext } from '@nestjs/common';
|
|
|
2
2
|
import { Reflector } from '@nestjs/core';
|
|
3
3
|
import { Repository } from 'typeorm';
|
|
4
4
|
import { ApiKeyEntity } from '../entities/api-key.entity';
|
|
5
|
-
import { EncryptionService } from '../services/encryption.service';
|
|
6
5
|
export declare class ApiKeyGuard implements CanActivate {
|
|
7
6
|
private readonly reflector;
|
|
8
|
-
private readonly encryptionService;
|
|
9
7
|
private apiKeyRepo;
|
|
10
8
|
private rateLimitMap;
|
|
11
|
-
constructor(reflector: Reflector,
|
|
9
|
+
constructor(reflector: Reflector, apiKeyRepository?: Repository<ApiKeyEntity>);
|
|
12
10
|
canActivate(context: ExecutionContext): Promise<boolean>;
|
|
13
11
|
private extractApiKey;
|
|
14
12
|
private validateApiKey;
|
|
@@ -16,11 +16,9 @@ exports.ApiKeyGuard = void 0;
|
|
|
16
16
|
const common_1 = require("@nestjs/common");
|
|
17
17
|
const core_1 = require("@nestjs/core");
|
|
18
18
|
const typeorm_1 = require("typeorm");
|
|
19
|
-
const encryption_service_1 = require("../services/encryption.service");
|
|
20
19
|
let ApiKeyGuard = class ApiKeyGuard {
|
|
21
|
-
constructor(reflector,
|
|
20
|
+
constructor(reflector, apiKeyRepository) {
|
|
22
21
|
this.reflector = reflector;
|
|
23
|
-
this.encryptionService = encryptionService;
|
|
24
22
|
this.rateLimitMap = new Map();
|
|
25
23
|
if (apiKeyRepository) {
|
|
26
24
|
this.apiKeyRepo = apiKeyRepository;
|
|
@@ -72,19 +70,9 @@ let ApiKeyGuard = class ApiKeyGuard {
|
|
|
72
70
|
if (!this.apiKeyRepo) {
|
|
73
71
|
return { valid: false, message: 'API key validation not configured' };
|
|
74
72
|
}
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
where: { isActive: true },
|
|
73
|
+
const record = await this.apiKeyRepo.findOne({
|
|
74
|
+
where: { key: apiKey, isActive: true },
|
|
78
75
|
});
|
|
79
|
-
let record = null;
|
|
80
|
-
// Compare incoming key with hashed keys in database
|
|
81
|
-
for (const dbRecord of records) {
|
|
82
|
-
const isMatch = await this.encryptionService.compareKey(apiKey, dbRecord.key);
|
|
83
|
-
if (isMatch) {
|
|
84
|
-
record = dbRecord;
|
|
85
|
-
break;
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
76
|
if (!record) {
|
|
89
77
|
return { valid: false, message: 'API key not found or inactive' };
|
|
90
78
|
}
|
|
@@ -188,8 +176,7 @@ let ApiKeyGuard = class ApiKeyGuard {
|
|
|
188
176
|
exports.ApiKeyGuard = ApiKeyGuard;
|
|
189
177
|
exports.ApiKeyGuard = ApiKeyGuard = __decorate([
|
|
190
178
|
(0, common_1.Injectable)(),
|
|
191
|
-
__param(
|
|
179
|
+
__param(1, (0, common_1.Inject)('API_KEY_REPOSITORY')),
|
|
192
180
|
__metadata("design:paramtypes", [core_1.Reflector,
|
|
193
|
-
encryption_service_1.EncryptionService,
|
|
194
181
|
typeorm_1.Repository])
|
|
195
182
|
], ApiKeyGuard);
|
package/dist/index.d.ts
CHANGED
|
@@ -16,7 +16,6 @@ export * from './guards/permission.guard';
|
|
|
16
16
|
export * from './guards/api-key.guard';
|
|
17
17
|
export * from './jwt/jwt.guard';
|
|
18
18
|
export * from './jwt/jwt.strategy';
|
|
19
|
-
export * from './services/encryption.service';
|
|
20
19
|
export * from './interfaces/auth-core-options.interface';
|
|
21
20
|
export * from './entities/user.entity';
|
|
22
21
|
export * from './entities/role.entity';
|
|
@@ -27,3 +26,4 @@ export * from './entities/user-feature-access.entity';
|
|
|
27
26
|
export * from './entities/user-module-access.entity';
|
|
28
27
|
export * from './entities/module-screen-permission.entity';
|
|
29
28
|
export * from './entities/api-key.entity';
|
|
29
|
+
export * from './entities/user-last-login.entity';
|
package/dist/index.js
CHANGED
|
@@ -37,8 +37,6 @@ __exportStar(require("./guards/api-key.guard"), exports);
|
|
|
37
37
|
// JWT
|
|
38
38
|
__exportStar(require("./jwt/jwt.guard"), exports);
|
|
39
39
|
__exportStar(require("./jwt/jwt.strategy"), exports);
|
|
40
|
-
// Services
|
|
41
|
-
__exportStar(require("./services/encryption.service"), exports);
|
|
42
40
|
// Interfaces
|
|
43
41
|
__exportStar(require("./interfaces/auth-core-options.interface"), exports);
|
|
44
42
|
// ✅ Entities
|
|
@@ -51,3 +49,4 @@ __exportStar(require("./entities/user-feature-access.entity"), exports);
|
|
|
51
49
|
__exportStar(require("./entities/user-module-access.entity"), exports);
|
|
52
50
|
__exportStar(require("./entities/module-screen-permission.entity"), exports);
|
|
53
51
|
__exportStar(require("./entities/api-key.entity"), exports);
|
|
52
|
+
__exportStar(require("./entities/user-last-login.entity"), exports);
|
|
@@ -8,6 +8,7 @@ import { UserFeatureAccess } from '../entities/user-feature-access.entity';
|
|
|
8
8
|
import { UserModuleAccess } from '../entities/user-module-access.entity';
|
|
9
9
|
import { ModuleScreenPermission } from '../entities/module-screen-permission.entity';
|
|
10
10
|
import { ApiKeyEntity } from '../entities/api-key.entity';
|
|
11
|
+
import { UserLastLoginEntity } from '../entities/user-last-login.entity';
|
|
11
12
|
export interface Repositories {
|
|
12
13
|
userRepo: Repository<User>;
|
|
13
14
|
roleRepo: Repository<Role>;
|
|
@@ -18,6 +19,9 @@ export interface Repositories {
|
|
|
18
19
|
routeRepo: Repository<ModuleRoute>;
|
|
19
20
|
moduleAccessRepo: Repository<UserModuleAccess>;
|
|
20
21
|
apiKeyRepo?: Repository<ApiKeyEntity>;
|
|
22
|
+
ipRestrictionsRepo?: Repository<any>;
|
|
23
|
+
userLastLoginRepo?: Repository<UserLastLoginEntity>;
|
|
24
|
+
employeeWorkProfileRepo?: Repository<any>;
|
|
21
25
|
}
|
|
22
26
|
export interface AuthModuleConfig {
|
|
23
27
|
enable2FA?: boolean;
|
package/package.json
CHANGED
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
export declare class EncryptionService {
|
|
2
|
-
private readonly saltRounds;
|
|
3
|
-
/**
|
|
4
|
-
* Hash an API key using bcrypt
|
|
5
|
-
* @param plainKey - The plain text API key
|
|
6
|
-
* @returns Hashed key
|
|
7
|
-
*/
|
|
8
|
-
hashKey(plainKey: string): Promise<string>;
|
|
9
|
-
/**
|
|
10
|
-
* Compare plain key with hashed key
|
|
11
|
-
* @param plainKey - The plain text API key
|
|
12
|
-
* @param hashedKey - The hashed key from database
|
|
13
|
-
* @returns True if keys match, false otherwise
|
|
14
|
-
*/
|
|
15
|
-
compareKey(plainKey: string, hashedKey: string): Promise<boolean>;
|
|
16
|
-
}
|
|
@@ -1,70 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
-
if (k2 === undefined) k2 = k;
|
|
4
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
-
}
|
|
8
|
-
Object.defineProperty(o, k2, desc);
|
|
9
|
-
}) : (function(o, m, k, k2) {
|
|
10
|
-
if (k2 === undefined) k2 = k;
|
|
11
|
-
o[k2] = m[k];
|
|
12
|
-
}));
|
|
13
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
-
}) : function(o, v) {
|
|
16
|
-
o["default"] = v;
|
|
17
|
-
});
|
|
18
|
-
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
19
|
-
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
20
|
-
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
21
|
-
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
22
|
-
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
23
|
-
};
|
|
24
|
-
var __importStar = (this && this.__importStar) || (function () {
|
|
25
|
-
var ownKeys = function(o) {
|
|
26
|
-
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
27
|
-
var ar = [];
|
|
28
|
-
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
29
|
-
return ar;
|
|
30
|
-
};
|
|
31
|
-
return ownKeys(o);
|
|
32
|
-
};
|
|
33
|
-
return function (mod) {
|
|
34
|
-
if (mod && mod.__esModule) return mod;
|
|
35
|
-
var result = {};
|
|
36
|
-
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
37
|
-
__setModuleDefault(result, mod);
|
|
38
|
-
return result;
|
|
39
|
-
};
|
|
40
|
-
})();
|
|
41
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
42
|
-
exports.EncryptionService = void 0;
|
|
43
|
-
const common_1 = require("@nestjs/common");
|
|
44
|
-
const bcrypt = __importStar(require("bcrypt"));
|
|
45
|
-
let EncryptionService = class EncryptionService {
|
|
46
|
-
constructor() {
|
|
47
|
-
this.saltRounds = 10;
|
|
48
|
-
}
|
|
49
|
-
/**
|
|
50
|
-
* Hash an API key using bcrypt
|
|
51
|
-
* @param plainKey - The plain text API key
|
|
52
|
-
* @returns Hashed key
|
|
53
|
-
*/
|
|
54
|
-
async hashKey(plainKey) {
|
|
55
|
-
return bcrypt.hash(plainKey, this.saltRounds);
|
|
56
|
-
}
|
|
57
|
-
/**
|
|
58
|
-
* Compare plain key with hashed key
|
|
59
|
-
* @param plainKey - The plain text API key
|
|
60
|
-
* @param hashedKey - The hashed key from database
|
|
61
|
-
* @returns True if keys match, false otherwise
|
|
62
|
-
*/
|
|
63
|
-
async compareKey(plainKey, hashedKey) {
|
|
64
|
-
return bcrypt.compare(plainKey, hashedKey);
|
|
65
|
-
}
|
|
66
|
-
};
|
|
67
|
-
exports.EncryptionService = EncryptionService;
|
|
68
|
-
exports.EncryptionService = EncryptionService = __decorate([
|
|
69
|
-
(0, common_1.Injectable)()
|
|
70
|
-
], EncryptionService);
|