@tomei/sso 0.34.2 → 0.34.6

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,1617 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.User = void 0;
13
+ const general_1 = require("@tomei/general");
14
+ const user_repository_1 = require("./user.repository");
15
+ const system_repository_1 = require("../system/system.repository");
16
+ const login_history_repository_1 = require("../login-history/login-history.repository");
17
+ const password_hash_service_1 = require("../password-hash/password-hash.service");
18
+ const user_group_repository_1 = require("../user-group/user-group.repository");
19
+ const staff_entity_1 = require("../../models/staff.entity");
20
+ const system_privilege_entity_1 = require("../../models/system-privilege.entity");
21
+ const yn_enum_1 = require("../../enum/yn.enum");
22
+ const enum_1 = require("../../enum");
23
+ const config_1 = require("@tomei/config");
24
+ const sequelize_1 = require("sequelize");
25
+ const activity_history_1 = require("@tomei/activity-history");
26
+ const user_entity_1 = require("../../models/user.entity");
27
+ const group_entity_1 = require("../../models/group.entity");
28
+ const group_system_access_repository_1 = require("../group-system-access/group-system-access.repository");
29
+ const group_repository_1 = require("../group/group.repository");
30
+ const system_entity_1 = require("../../models/system.entity");
31
+ const user_system_access_repository_1 = require("../user-system-access/user-system-access.repository");
32
+ const group_system_access_entity_1 = require("../../models/group-system-access.entity");
33
+ const user_privilege_repository_1 = require("../user-privilege/user-privilege.repository");
34
+ const user_object_privilege_repository_1 = require("../user-object-privilege/user-object-privilege.repository");
35
+ const group_privilege_entity_1 = require("../../models/group-privilege.entity");
36
+ const group_object_privilege_repository_1 = require("../group-object-privilege/group-object-privilege.repository");
37
+ const speakeasy = require("speakeasy");
38
+ const login_status_enum_1 = require("../../enum/login-status.enum");
39
+ const redis_service_1 = require("../../redis-client/redis.service");
40
+ const login_user_1 = require("./login-user");
41
+ class User extends general_1.UserBase {
42
+ get SessionService() {
43
+ return this._SessionService;
44
+ }
45
+ get UserId() {
46
+ return parseInt(this.ObjectId);
47
+ }
48
+ set UserId(value) {
49
+ this.ObjectId = value.toString();
50
+ }
51
+ get Password() {
52
+ return this._Password;
53
+ }
54
+ set Password(value) {
55
+ this._Password = value;
56
+ }
57
+ get Status() {
58
+ return this._Status;
59
+ }
60
+ set Status(value) {
61
+ this._Status = value;
62
+ }
63
+ get UserName() {
64
+ return this._UserName;
65
+ }
66
+ set UserName(value) {
67
+ this._UserName = value;
68
+ }
69
+ get DefaultPasswordChangedYN() {
70
+ return this._DefaultPasswordChangedYN;
71
+ }
72
+ set DefaultPasswordChangedYN(value) {
73
+ this._DefaultPasswordChangedYN = value;
74
+ }
75
+ get FirstLoginAt() {
76
+ return this._FirstLoginAt;
77
+ }
78
+ set FirstLoginAt(value) {
79
+ this._FirstLoginAt = value;
80
+ }
81
+ get LastLoginAt() {
82
+ return this._LastLoginAt;
83
+ }
84
+ set LastLoginAt(value) {
85
+ this._LastLoginAt = value;
86
+ }
87
+ get MFAEnabled() {
88
+ return this._MFAEnabled;
89
+ }
90
+ set MFAEnabled(value) {
91
+ this._MFAEnabled = value;
92
+ }
93
+ get MFAConfig() {
94
+ return this._MFAConfig;
95
+ }
96
+ set MFAConfig(value) {
97
+ this._MFAConfig = value;
98
+ }
99
+ get RecoveryEmail() {
100
+ return this._RecoveryEmail;
101
+ }
102
+ set RecoveryEmail(value) {
103
+ this._RecoveryEmail = value;
104
+ }
105
+ get FailedLoginAttemptCount() {
106
+ return this._FailedLoginAttemptCount;
107
+ }
108
+ set FailedLoginAttemptCount(value) {
109
+ this._FailedLoginAttemptCount = value;
110
+ }
111
+ get LastFailedLoginAt() {
112
+ return this._LastFailedLoginAt;
113
+ }
114
+ set LastFailedLoginAt(value) {
115
+ this._LastFailedLoginAt = value;
116
+ }
117
+ get LastPasswordChangedAt() {
118
+ return this._LastPasswordChangedAt;
119
+ }
120
+ set LastPasswordChangedAt(value) {
121
+ this._LastPasswordChangedAt = value;
122
+ }
123
+ get NeedToChangePasswordYN() {
124
+ return this._NeedToChangePasswordYN;
125
+ }
126
+ set NeedToChangePasswordYN(value) {
127
+ this._NeedToChangePasswordYN = value;
128
+ }
129
+ get CreatedById() {
130
+ return this._CreatedById;
131
+ }
132
+ set CreatedById(value) {
133
+ this._CreatedById = value;
134
+ }
135
+ get CreatedAt() {
136
+ return this._CreatedAt;
137
+ }
138
+ set CreatedAt(value) {
139
+ this._CreatedAt = value;
140
+ }
141
+ get UpdatedById() {
142
+ return this._UpdatedById;
143
+ }
144
+ set UpdatedById(value) {
145
+ this._UpdatedById = value;
146
+ }
147
+ get UpdatedAt() {
148
+ return this._UpdatedAt;
149
+ }
150
+ set UpdatedAt(value) {
151
+ this._UpdatedAt = value;
152
+ }
153
+ getDetails() {
154
+ return __awaiter(this, void 0, void 0, function* () {
155
+ return {
156
+ FullName: this.FullName,
157
+ UserName: this.UserName,
158
+ IDNo: this.IDNo,
159
+ IDType: this.IDType,
160
+ Email: this.Email,
161
+ ContactNo: this.ContactNo,
162
+ };
163
+ });
164
+ }
165
+ constructor(sessionService, dbTransaction, userInfo) {
166
+ super();
167
+ this.ObjectName = 'User';
168
+ this.TableName = 'sso_Users';
169
+ this.ObjectType = 'User';
170
+ this._SessionService = sessionService;
171
+ if (dbTransaction) {
172
+ this._dbTransaction = dbTransaction;
173
+ }
174
+ if (userInfo) {
175
+ this.UserId = userInfo.UserId;
176
+ this.UserName = userInfo.FullName;
177
+ this.FullName = userInfo.FullName;
178
+ this.IDNo = userInfo.IDNo;
179
+ this.Email = userInfo.Email;
180
+ this.ContactNo = userInfo.ContactNo;
181
+ this.Password = userInfo.Password;
182
+ this.staffs = userInfo.staffs;
183
+ this.Status = userInfo.Status;
184
+ this.DefaultPasswordChangedYN = userInfo.DefaultPasswordChangedYN;
185
+ this.FirstLoginAt = userInfo.FirstLoginAt;
186
+ this.LastLoginAt = userInfo.LastLoginAt;
187
+ this.MFAEnabled = userInfo.MFAEnabled;
188
+ this.MFAConfig = userInfo.MFAConfig;
189
+ this.RecoveryEmail = userInfo.RecoveryEmail;
190
+ this.FailedLoginAttemptCount = userInfo.FailedLoginAttemptCount;
191
+ this.LastFailedLoginAt = userInfo.LastFailedLoginAt;
192
+ this.LastPasswordChangedAt = userInfo.LastPasswordChangedAt;
193
+ this.NeedToChangePasswordYN = userInfo.NeedToChangePasswordYN;
194
+ this.CreatedById = userInfo.CreatedById;
195
+ this.CreatedAt = userInfo.CreatedAt;
196
+ this.UpdatedById = userInfo.UpdatedById;
197
+ this.UpdatedAt = userInfo.UpdatedAt;
198
+ }
199
+ }
200
+ static init(sessionService, userId, dbTransaction = null) {
201
+ var _a, _b, _c;
202
+ return __awaiter(this, void 0, void 0, function* () {
203
+ User._RedisService = yield redis_service_1.RedisService.init();
204
+ if (userId) {
205
+ if (dbTransaction) {
206
+ User._Repository = new user_repository_1.UserRepository();
207
+ }
208
+ const user = yield User._Repository.findOne({
209
+ where: {
210
+ UserId: userId,
211
+ },
212
+ include: [
213
+ {
214
+ model: staff_entity_1.default,
215
+ },
216
+ ],
217
+ transaction: dbTransaction,
218
+ });
219
+ if (!user) {
220
+ throw new Error('Invalid credentials.');
221
+ }
222
+ if (user) {
223
+ const userAttr = {
224
+ UserId: user.UserId,
225
+ UserName: user.UserName,
226
+ FullName: (_a = user === null || user === void 0 ? void 0 : user.Staff) === null || _a === void 0 ? void 0 : _a.FullName,
227
+ IDNo: (_b = user === null || user === void 0 ? void 0 : user.Staff) === null || _b === void 0 ? void 0 : _b.IdNo,
228
+ ContactNo: (_c = user === null || user === void 0 ? void 0 : user.Staff) === null || _c === void 0 ? void 0 : _c.Mobile,
229
+ Email: user.Email,
230
+ Password: user.Password,
231
+ Status: user.Status,
232
+ DefaultPasswordChangedYN: user.DefaultPasswordChangedYN,
233
+ FirstLoginAt: user.FirstLoginAt,
234
+ LastLoginAt: user.LastLoginAt,
235
+ MFAEnabled: user.MFAEnabled,
236
+ MFAConfig: user.MFAConfig,
237
+ RecoveryEmail: user.RecoveryEmail,
238
+ FailedLoginAttemptCount: user.FailedLoginAttemptCount,
239
+ LastFailedLoginAt: user.LastFailedLoginAt,
240
+ LastPasswordChangedAt: user.LastPasswordChangedAt,
241
+ NeedToChangePasswordYN: user.NeedToChangePasswordYN,
242
+ CreatedById: user.CreatedById,
243
+ CreatedAt: user.CreatedAt,
244
+ UpdatedById: user.UpdatedById,
245
+ UpdatedAt: user.UpdatedAt,
246
+ staffs: user === null || user === void 0 ? void 0 : user.Staff,
247
+ };
248
+ return new User(sessionService, dbTransaction, userAttr);
249
+ }
250
+ else {
251
+ throw new Error('User not found');
252
+ }
253
+ }
254
+ return new User(sessionService, dbTransaction);
255
+ });
256
+ }
257
+ setEmail(email, dbTransaction) {
258
+ return __awaiter(this, void 0, void 0, function* () {
259
+ try {
260
+ if (this.Email === email) {
261
+ return;
262
+ }
263
+ const user = yield User._Repository.findOne({
264
+ where: {
265
+ Email: email,
266
+ },
267
+ transaction: dbTransaction,
268
+ });
269
+ if (user) {
270
+ throw new general_1.ClassError('LoginUser', 'LoginUserErrMsg0X', 'Email already exists');
271
+ }
272
+ this.Email = email;
273
+ }
274
+ catch (error) {
275
+ throw error;
276
+ }
277
+ });
278
+ }
279
+ login(systemCode, email, password, ipAddress, dbTransaction) {
280
+ var _a, _b, _c;
281
+ return __awaiter(this, void 0, void 0, function* () {
282
+ try {
283
+ if (!this.ObjectId) {
284
+ const user = yield User._Repository.findOne({
285
+ transaction: dbTransaction,
286
+ where: {
287
+ Email: email,
288
+ Status: {
289
+ [sequelize_1.Op.or]: [enum_1.UserStatus.ACTIVE, enum_1.UserStatus.LOCKED],
290
+ },
291
+ },
292
+ include: [
293
+ {
294
+ model: staff_entity_1.default,
295
+ },
296
+ ],
297
+ });
298
+ if (user) {
299
+ const userAttr = {
300
+ UserId: user.UserId,
301
+ UserName: user.UserName,
302
+ FullName: ((_a = user === null || user === void 0 ? void 0 : user.Staff) === null || _a === void 0 ? void 0 : _a.FullName) || null,
303
+ IDNo: ((_b = user === null || user === void 0 ? void 0 : user.Staff) === null || _b === void 0 ? void 0 : _b.IdNo) || null,
304
+ ContactNo: ((_c = user === null || user === void 0 ? void 0 : user.Staff) === null || _c === void 0 ? void 0 : _c.Mobile) || null,
305
+ Email: user.Email,
306
+ Password: user.Password,
307
+ Status: user.Status,
308
+ DefaultPasswordChangedYN: user.DefaultPasswordChangedYN,
309
+ FirstLoginAt: user.FirstLoginAt,
310
+ LastLoginAt: user.LastLoginAt,
311
+ MFAEnabled: user.MFAEnabled,
312
+ MFAConfig: user.MFAConfig,
313
+ RecoveryEmail: user.RecoveryEmail,
314
+ FailedLoginAttemptCount: user.FailedLoginAttemptCount,
315
+ LastFailedLoginAt: user.LastFailedLoginAt,
316
+ LastPasswordChangedAt: user.LastPasswordChangedAt,
317
+ NeedToChangePasswordYN: user.NeedToChangePasswordYN,
318
+ CreatedById: user.CreatedById,
319
+ CreatedAt: user.CreatedAt,
320
+ UpdatedById: user.UpdatedById,
321
+ UpdatedAt: user.UpdatedAt,
322
+ staffs: (user === null || user === void 0 ? void 0 : user.Staff) || null,
323
+ };
324
+ this.UserId = userAttr.UserId;
325
+ this.FullName = userAttr.FullName;
326
+ this.IDNo = userAttr.IDNo;
327
+ this.Email = userAttr.Email;
328
+ this.ContactNo = userAttr.ContactNo;
329
+ this.Password = userAttr.Password;
330
+ this.Status = userAttr.Status;
331
+ this.DefaultPasswordChangedYN = userAttr.DefaultPasswordChangedYN;
332
+ this.FirstLoginAt = userAttr.FirstLoginAt;
333
+ this.LastLoginAt = userAttr.LastLoginAt;
334
+ this.MFAEnabled = userAttr.MFAEnabled;
335
+ this.MFAConfig = userAttr.MFAConfig;
336
+ this.RecoveryEmail = userAttr.RecoveryEmail;
337
+ this.FailedLoginAttemptCount = userAttr.FailedLoginAttemptCount;
338
+ this.LastFailedLoginAt = userAttr.LastFailedLoginAt;
339
+ this.LastPasswordChangedAt = userAttr.LastPasswordChangedAt;
340
+ this.NeedToChangePasswordYN = userAttr.NeedToChangePasswordYN;
341
+ this.CreatedById = userAttr.CreatedById;
342
+ this.CreatedAt = userAttr.CreatedAt;
343
+ this.UpdatedById = userAttr.UpdatedById;
344
+ this.UpdatedAt = userAttr.UpdatedAt;
345
+ this.staffs = userAttr.staffs;
346
+ }
347
+ else {
348
+ throw new general_1.ClassError('User', 'UserErrMsg0X', 'Invalid Credentials');
349
+ }
350
+ }
351
+ if (this.ObjectId && this.Email !== email) {
352
+ throw new Error('Invalid credentials.');
353
+ }
354
+ const check2FA = yield User.check2FA(this, dbTransaction);
355
+ try {
356
+ const system = yield User._SystemRepository.findOne({
357
+ where: {
358
+ SystemCode: systemCode,
359
+ Status: 'Active',
360
+ },
361
+ });
362
+ if (!system) {
363
+ throw new Error('Invalid credentials.');
364
+ }
365
+ const passwordHashService = new password_hash_service_1.PasswordHashService();
366
+ const isPasswordValid = yield passwordHashService.verify(password, this.Password);
367
+ if (!isPasswordValid) {
368
+ throw new Error('Invalid credentials.');
369
+ }
370
+ yield this.checkSystemAccess(this.UserId, system.SystemCode, dbTransaction);
371
+ if (this.Status === enum_1.UserStatus.LOCKED) {
372
+ const isReleaseLock = User.shouldReleaseLock(this.LastFailedLoginAt);
373
+ if (isReleaseLock) {
374
+ yield User.releaseLock(this.UserId, dbTransaction);
375
+ this.Status = enum_1.UserStatus.ACTIVE;
376
+ }
377
+ else {
378
+ throw new Error('Invalid credentials.');
379
+ }
380
+ }
381
+ }
382
+ catch (error) {
383
+ yield this.incrementFailedLoginAttemptCount(dbTransaction);
384
+ }
385
+ const system = yield User._SystemRepository.findOne({
386
+ where: {
387
+ SystemCode: systemCode,
388
+ },
389
+ });
390
+ yield this.alertNewLogin(this.ObjectId, system.SystemCode, ipAddress);
391
+ this.FailedLoginAttemptCount = 0;
392
+ this.LastLoginAt = new Date();
393
+ if (!this.FirstLoginAt) {
394
+ this.FirstLoginAt = new Date();
395
+ }
396
+ yield User._Repository.update({
397
+ FullName: this.FullName,
398
+ UserName: this.UserName,
399
+ IDNo: this.IDNo,
400
+ Email: this.Email,
401
+ ContactNo: this.ContactNo,
402
+ Password: this.Password,
403
+ Status: this.Status,
404
+ DefaultPasswordChangedYN: this.DefaultPasswordChangedYN,
405
+ FirstLoginAt: this.FirstLoginAt,
406
+ LastLoginAt: this.LastLoginAt,
407
+ MFAEnabled: this.MFAEnabled,
408
+ MFAConfig: this.MFAConfig,
409
+ RecoveryEmail: this.RecoveryEmail,
410
+ FailedLoginAttemptCount: this.FailedLoginAttemptCount,
411
+ LastFailedLoginAt: this.LastFailedLoginAt,
412
+ LastPasswordChangedAt: this.LastPasswordChangedAt,
413
+ NeedToChangePasswordYN: this.NeedToChangePasswordYN,
414
+ }, {
415
+ where: {
416
+ UserId: this.UserId,
417
+ },
418
+ transaction: dbTransaction,
419
+ });
420
+ const userSession = yield this._SessionService.retrieveUserSession(this.ObjectId);
421
+ let systemLogin = userSession.systemLogins.find((system) => system.code === systemCode);
422
+ const { randomUUID } = require('crypto');
423
+ const sessionId = randomUUID();
424
+ if (systemLogin) {
425
+ systemLogin = systemLogin.sessionId = sessionId;
426
+ userSession.systemLogins.map((system) => system.code === systemCode ? systemLogin : system);
427
+ }
428
+ else {
429
+ const newLogin = {
430
+ id: system.SystemCode,
431
+ code: system.SystemCode,
432
+ sessionId: sessionId,
433
+ privileges: yield this.getPrivileges(system.SystemCode, dbTransaction),
434
+ };
435
+ userSession.systemLogins.push(newLogin);
436
+ }
437
+ this._SessionService.setUserSession(this.ObjectId, userSession);
438
+ yield User._LoginHistoryRepository.create({
439
+ UserId: this.UserId,
440
+ SystemCode: system.SystemCode,
441
+ OriginIp: ipAddress,
442
+ CreatedAt: new Date(),
443
+ LoginStatus: login_status_enum_1.LoginStatusEnum.SUCCESS,
444
+ }, {
445
+ transaction: dbTransaction,
446
+ });
447
+ const is2FAEnabledYN = config_1.ComponentConfig.getComponentConfigValue('@tomei/sso', 'is2FAEnabledYN');
448
+ const loginUser = yield login_user_1.LoginUser.init(this.SessionService, this.UserId, dbTransaction);
449
+ if (is2FAEnabledYN === 'Y') {
450
+ loginUser.session.Id = `${this.UserId}:`;
451
+ }
452
+ else {
453
+ loginUser.session.Id = `${this.UserId}:${sessionId}`;
454
+ }
455
+ return loginUser;
456
+ }
457
+ catch (error) {
458
+ if (this.ObjectId) {
459
+ yield User._LoginHistoryRepository.create({
460
+ UserId: this.UserId,
461
+ SystemCode: systemCode,
462
+ OriginIp: ipAddress,
463
+ LoginStatus: login_status_enum_1.LoginStatusEnum.FAILURE,
464
+ CreatedAt: new Date(),
465
+ }, {
466
+ transaction: dbTransaction,
467
+ });
468
+ }
469
+ throw error;
470
+ }
471
+ });
472
+ }
473
+ checkSystemAccess(userId, systemCode, dbTransaction) {
474
+ return __awaiter(this, void 0, void 0, function* () {
475
+ try {
476
+ let isUserHaveAccess = false;
477
+ const systemAccess = yield User._UserSystemAccessRepo.findOne({
478
+ where: {
479
+ UserId: userId,
480
+ SystemCode: systemCode,
481
+ Status: 'Active',
482
+ },
483
+ dbTransaction,
484
+ });
485
+ if (systemAccess) {
486
+ isUserHaveAccess = true;
487
+ }
488
+ else {
489
+ const userGroups = yield User._UserGroupRepo.findAll({
490
+ where: {
491
+ UserId: userId,
492
+ InheritGroupAccessYN: 'Y',
493
+ Status: 'Active',
494
+ },
495
+ include: [
496
+ {
497
+ model: group_entity_1.default,
498
+ },
499
+ ],
500
+ dbTransaction,
501
+ });
502
+ for (const usergroup of userGroups) {
503
+ const group = usergroup.Group;
504
+ const groupSystemAccess = yield User.getInheritedSystemAccess(dbTransaction, group);
505
+ for (const system of groupSystemAccess) {
506
+ if (system.SystemCode === systemCode) {
507
+ isUserHaveAccess = true;
508
+ break;
509
+ }
510
+ }
511
+ }
512
+ }
513
+ if (!isUserHaveAccess) {
514
+ throw new Error("User don't have access to the system.");
515
+ }
516
+ }
517
+ catch (error) {
518
+ throw error;
519
+ }
520
+ });
521
+ }
522
+ checkPrivileges(systemCode, privilegeName) {
523
+ return __awaiter(this, void 0, void 0, function* () {
524
+ try {
525
+ if (!this.ObjectId) {
526
+ throw new Error('ObjectId(UserId) is not set');
527
+ }
528
+ const userSession = yield this._SessionService.retrieveUserSession(this.ObjectId);
529
+ const systemLogin = userSession.systemLogins.find((system) => system.code === systemCode);
530
+ if (!systemLogin) {
531
+ return false;
532
+ }
533
+ const privileges = systemLogin.privileges;
534
+ const hasPrivilege = privileges.includes(privilegeName);
535
+ return hasPrivilege;
536
+ }
537
+ catch (error) {
538
+ throw error;
539
+ }
540
+ });
541
+ }
542
+ alertNewLogin(userId, systemCode, ipAddress) {
543
+ return __awaiter(this, void 0, void 0, function* () {
544
+ try {
545
+ const userLogins = yield User._LoginHistoryRepository.findAll({
546
+ where: {
547
+ UserId: userId,
548
+ SystemCode: systemCode,
549
+ },
550
+ });
551
+ const gotPreviousLogins = (userLogins === null || userLogins === void 0 ? void 0 : userLogins.length) !== 0;
552
+ let ipFound = undefined;
553
+ if (gotPreviousLogins) {
554
+ ipFound = userLogins.find((item) => item.OriginIp === ipAddress);
555
+ }
556
+ }
557
+ catch (error) {
558
+ throw error;
559
+ }
560
+ });
561
+ }
562
+ getPrivileges(systemCode, dbTransaction) {
563
+ return __awaiter(this, void 0, void 0, function* () {
564
+ try {
565
+ const system = yield User._SystemRepository.findOne({
566
+ where: {
567
+ SystemCode: systemCode,
568
+ },
569
+ transaction: dbTransaction,
570
+ });
571
+ if (!system) {
572
+ throw new Error('Invalid system code.');
573
+ }
574
+ const userPrivileges = yield this.getUserPersonalPrivileges(systemCode, dbTransaction);
575
+ const objectPrivileges = yield this.getObjectPrivileges(systemCode, dbTransaction);
576
+ const userGroupOwnByUser = yield User._UserGroupRepo.findAll({
577
+ where: {
578
+ UserId: this.UserId,
579
+ InheritGroupSystemAccessYN: 'Y',
580
+ InheritGroupPrivilegeYN: 'Y',
581
+ Status: 'Active',
582
+ },
583
+ include: [
584
+ {
585
+ model: group_entity_1.default,
586
+ where: {
587
+ Status: 'Active',
588
+ },
589
+ include: [
590
+ {
591
+ model: group_system_access_entity_1.default,
592
+ where: {
593
+ SystemCode: systemCode,
594
+ },
595
+ },
596
+ ],
597
+ },
598
+ ],
599
+ transaction: dbTransaction,
600
+ });
601
+ let groupsPrivileges = [];
602
+ for (const userGroup of userGroupOwnByUser) {
603
+ const gp = yield this.getInheritedPrivileges(userGroup.GroupCode, systemCode, dbTransaction);
604
+ groupsPrivileges = [...groupsPrivileges, ...gp];
605
+ }
606
+ const privileges = [
607
+ ...userPrivileges,
608
+ ...objectPrivileges,
609
+ ...groupsPrivileges,
610
+ ];
611
+ return privileges;
612
+ }
613
+ catch (error) {
614
+ throw error;
615
+ }
616
+ });
617
+ }
618
+ getInheritedPrivileges(groupCode, systemCode, dbTransaction) {
619
+ return __awaiter(this, void 0, void 0, function* () {
620
+ try {
621
+ const group = yield User._GroupRepo.findOne({
622
+ where: {
623
+ GroupCode: groupCode,
624
+ Status: 'Active',
625
+ },
626
+ include: [
627
+ {
628
+ model: group_privilege_entity_1.default,
629
+ where: {
630
+ Status: 'Active',
631
+ },
632
+ include: [
633
+ {
634
+ model: system_privilege_entity_1.default,
635
+ where: {
636
+ SystemCode: systemCode,
637
+ Status: 'Active',
638
+ },
639
+ },
640
+ ],
641
+ },
642
+ ],
643
+ transaction: dbTransaction,
644
+ });
645
+ const objectPrivileges = yield User._GroupObjectPrivilegeRepo.findAll({
646
+ where: {
647
+ GroupCode: groupCode,
648
+ },
649
+ include: {
650
+ model: system_privilege_entity_1.default,
651
+ where: {
652
+ SystemCode: systemCode,
653
+ Status: 'Active',
654
+ },
655
+ },
656
+ transaction: dbTransaction,
657
+ });
658
+ let privileges = [];
659
+ const groupPrivileges = [];
660
+ for (const groupPrivilege of group.GroupPrivileges) {
661
+ groupPrivileges.push(groupPrivilege.Privilege.PrivilegeCode);
662
+ }
663
+ const ops = [];
664
+ for (const objectPrivilege of objectPrivileges) {
665
+ ops.push(objectPrivilege.Privilege.PrivilegeCode);
666
+ }
667
+ privileges = [...privileges, ...groupPrivileges, ...ops];
668
+ if (group.ParentGroupCode && group.InheritParentPrivilegeYN === 'Y') {
669
+ const parentGroupPrivileges = yield this.getInheritedPrivileges(group.ParentGroupCode, systemCode, dbTransaction);
670
+ privileges = [...privileges, ...parentGroupPrivileges];
671
+ }
672
+ return privileges;
673
+ }
674
+ catch (error) {
675
+ throw error;
676
+ }
677
+ });
678
+ }
679
+ getUserPersonalPrivileges(systemCode, dbTransaction) {
680
+ return __awaiter(this, void 0, void 0, function* () {
681
+ try {
682
+ const userPrivileges = yield User._UserPrivilegeRepo.findAll({
683
+ where: {
684
+ UserId: this.UserId,
685
+ Status: 'Active',
686
+ },
687
+ include: {
688
+ model: system_privilege_entity_1.default,
689
+ where: {
690
+ SystemCode: systemCode,
691
+ Status: 'Active',
692
+ },
693
+ },
694
+ transaction: dbTransaction,
695
+ });
696
+ const privileges = userPrivileges.map((u) => u.Privilege.PrivilegeCode);
697
+ return privileges;
698
+ }
699
+ catch (error) {
700
+ throw error;
701
+ }
702
+ });
703
+ }
704
+ getObjectPrivileges(systemCode, dbTransaction) {
705
+ return __awaiter(this, void 0, void 0, function* () {
706
+ try {
707
+ const userObjectPrivileges = yield User._UserObjectPrivilegeRepo.findAll({
708
+ where: {
709
+ UserId: this.UserId,
710
+ },
711
+ include: {
712
+ model: system_privilege_entity_1.default,
713
+ where: {
714
+ SystemCode: systemCode,
715
+ Status: 'Active',
716
+ },
717
+ },
718
+ transaction: dbTransaction,
719
+ });
720
+ const privilegesCodes = userObjectPrivileges.map((u) => u.Privilege.PrivilegeCode);
721
+ return privilegesCodes;
722
+ }
723
+ catch (error) {
724
+ throw error;
725
+ }
726
+ });
727
+ }
728
+ static checkUserInfoDuplicated(dbTransaction, query) {
729
+ return __awaiter(this, void 0, void 0, function* () {
730
+ try {
731
+ const { Email, UserName, IdType, IdNo, ContactNo } = query;
732
+ const where = {
733
+ [sequelize_1.Op.or]: {},
734
+ };
735
+ if (Email) {
736
+ where[sequelize_1.Op.or]['Email'] = Email;
737
+ }
738
+ if (UserName) {
739
+ where[sequelize_1.Op.or]['UserName'] = UserName;
740
+ }
741
+ if (IdType && IdNo) {
742
+ where[sequelize_1.Op.or]['IdType'] = IdType;
743
+ where[sequelize_1.Op.or]['IdNo'] = IdNo;
744
+ }
745
+ if (ContactNo) {
746
+ where[sequelize_1.Op.or]['ContactNo'] = ContactNo;
747
+ }
748
+ const user = yield User._Repository.findAll({
749
+ where,
750
+ transaction: dbTransaction,
751
+ });
752
+ if (user && user.length > 0) {
753
+ throw new general_1.ClassError('LoginUser', 'LoginUserErrMsg0X', 'User info already exists');
754
+ }
755
+ }
756
+ catch (error) {
757
+ throw error;
758
+ }
759
+ });
760
+ }
761
+ static generateDefaultPassword() {
762
+ try {
763
+ const passwordPolicy = config_1.ComponentConfig.getComponentConfigValue('@tomei/sso', 'passwordPolicy');
764
+ if (!passwordPolicy ||
765
+ !passwordPolicy.maxLen ||
766
+ !passwordPolicy.minLen ||
767
+ !passwordPolicy.nonAcceptableChar ||
768
+ !passwordPolicy.numOfCapitalLetters ||
769
+ !passwordPolicy.numOfNumbers ||
770
+ !passwordPolicy.numOfSpecialChars) {
771
+ throw new general_1.ClassError('LoginUser', 'LoginUserErrMsg0X', 'Missing password policy. Please set in config file.');
772
+ }
773
+ if (passwordPolicy.numOfCapitalLetters +
774
+ passwordPolicy.numOfNumbers +
775
+ passwordPolicy.numOfSpecialChars >
776
+ passwordPolicy.maxLen) {
777
+ throw new general_1.ClassError('LoginUser', 'LoginUserErrMsg0X', 'Password policy is invalid. Please set in config file.');
778
+ }
779
+ const { maxLen, minLen, nonAcceptableChar, numOfCapitalLetters, numOfNumbers, numOfSpecialChars, } = passwordPolicy;
780
+ const passwordLength = Math.floor(Math.random() * (maxLen - minLen + 1)) + minLen;
781
+ const words = 'abcdefghijklmnopqrstuvwxyz';
782
+ const capitalLetters = words.toUpperCase();
783
+ const numbers = '0123456789';
784
+ const specialChars = '!@#$%^&*()_+-={}[]|:;"<>,.?/~`';
785
+ const nonAcceptableChars = nonAcceptableChar.split(',');
786
+ const filteredWords = words
787
+ .split('')
788
+ .filter((word) => !nonAcceptableChars.includes(word));
789
+ const filteredCapitalLetters = capitalLetters
790
+ .split('')
791
+ .filter((word) => !nonAcceptableChars.includes(word));
792
+ const filteredNumbers = numbers
793
+ .split('')
794
+ .filter((word) => !nonAcceptableChars.includes(word));
795
+ const filteredSpecialChars = specialChars
796
+ .split('')
797
+ .filter((word) => !nonAcceptableChars.includes(word));
798
+ const generatedCapitalLetters = [];
799
+ const generatedNumbers = [];
800
+ const generatedSpecialChars = [];
801
+ const generatedWords = [];
802
+ for (let i = 0; i < numOfCapitalLetters; i++) {
803
+ const randomIndex = Math.floor(Math.random() * filteredCapitalLetters.length);
804
+ generatedCapitalLetters.push(filteredCapitalLetters[randomIndex]);
805
+ }
806
+ for (let i = 0; i < numOfNumbers; i++) {
807
+ const randomIndex = Math.floor(Math.random() * filteredNumbers.length);
808
+ generatedNumbers.push(filteredNumbers[randomIndex]);
809
+ }
810
+ for (let i = 0; i < numOfSpecialChars; i++) {
811
+ const randomIndex = Math.floor(Math.random() * filteredSpecialChars.length);
812
+ generatedSpecialChars.push(filteredSpecialChars[randomIndex]);
813
+ }
814
+ for (let i = 0; i <
815
+ passwordLength -
816
+ (numOfCapitalLetters + numOfNumbers + numOfSpecialChars); i++) {
817
+ const randomIndex = Math.floor(Math.random() * filteredWords.length);
818
+ generatedWords.push(filteredWords[randomIndex]);
819
+ }
820
+ let generatedPassword = '';
821
+ const allGeneratedChars = generatedCapitalLetters.concat(generatedNumbers, generatedSpecialChars, generatedWords);
822
+ allGeneratedChars.sort(() => Math.random() - 0.5);
823
+ generatedPassword = allGeneratedChars.join('');
824
+ return generatedPassword;
825
+ }
826
+ catch (error) {
827
+ throw error;
828
+ }
829
+ }
830
+ static setPassword(dbTransaction, user, password) {
831
+ return __awaiter(this, void 0, void 0, function* () {
832
+ try {
833
+ const passwordPolicy = config_1.ComponentConfig.getComponentConfigValue('@tomei/sso', 'passwordPolicy');
834
+ if (!passwordPolicy ||
835
+ !passwordPolicy.maxLen ||
836
+ !passwordPolicy.minLen ||
837
+ !passwordPolicy.nonAcceptableChar ||
838
+ !passwordPolicy.numOfCapitalLetters ||
839
+ !passwordPolicy.numOfNumbers ||
840
+ !passwordPolicy.numOfSpecialChars) {
841
+ throw new general_1.ClassError('LoginUser', 'LoginUserErrMsg0X', 'Missing password policy. Please set in config file.');
842
+ }
843
+ try {
844
+ if (password.length < passwordPolicy.minLen) {
845
+ throw Error('Password is too short');
846
+ }
847
+ if (password.length > passwordPolicy.maxLen) {
848
+ throw Error('Password is too long');
849
+ }
850
+ const nonAcceptableChars = passwordPolicy.nonAcceptableChar.split(',');
851
+ const nonAcceptableCharsFound = nonAcceptableChars.some((char) => password.includes(char));
852
+ if (nonAcceptableCharsFound) {
853
+ throw Error('Password contains unacceptable characters');
854
+ }
855
+ const capitalLetters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
856
+ const numOfCapitalLetters = passwordPolicy.numOfCapitalLetters;
857
+ const capitalLettersFound = capitalLetters
858
+ .split('')
859
+ .filter((char) => password.includes(char)).length;
860
+ if (capitalLettersFound < numOfCapitalLetters) {
861
+ throw Error('Password does not contain enough capital letters');
862
+ }
863
+ const numbers = '0123456789';
864
+ const numOfNumbers = passwordPolicy.numOfNumbers;
865
+ const numbersFound = numbers
866
+ .split('')
867
+ .filter((char) => password.includes(char)).length;
868
+ if (numbersFound < numOfNumbers) {
869
+ throw Error('Password does not contain enough numbers');
870
+ }
871
+ const specialChars = '!@#$%^&*()_+-={}[]|:;"<>,.?/~`';
872
+ const numOfSpecialChars = passwordPolicy.numOfSpecialChars;
873
+ const specialCharsFound = specialChars
874
+ .split('')
875
+ .filter((char) => password.includes(char)).length;
876
+ if (specialCharsFound < numOfSpecialChars) {
877
+ throw Error('Password does not contain enough special characters');
878
+ }
879
+ }
880
+ catch (error) {
881
+ throw new general_1.ClassError('LoginUser', 'LoginUserErrMsg0X', "Your password doesn't meet security requirements. Try using a mix of uppercase and lowercase letters, numbers, and symbols.");
882
+ }
883
+ const passwordHashService = new password_hash_service_1.PasswordHashService();
884
+ const hashedPassword = yield passwordHashService.hashPassword(password);
885
+ user._Password = hashedPassword;
886
+ return user;
887
+ }
888
+ catch (error) {
889
+ throw error;
890
+ }
891
+ });
892
+ }
893
+ static create(loginUser, dbTransaction, user) {
894
+ return __awaiter(this, void 0, void 0, function* () {
895
+ try {
896
+ const systemCode = config_1.ApplicationConfig.getComponentConfigValue('system-code');
897
+ const isPrivileged = yield loginUser.checkPrivileges(systemCode, 'User - Create');
898
+ if (!isPrivileged) {
899
+ throw new general_1.ClassError('LoginUser', 'LoginUserErrMsg0X', 'You do not have the privilege to create user');
900
+ }
901
+ if (!user.Email && !user.UserName) {
902
+ throw new general_1.ClassError('LoginUser', 'LoginUserErrMsg0X', 'Email and Username is required');
903
+ }
904
+ yield User.checkUserInfoDuplicated(dbTransaction, {
905
+ Email: user.Email,
906
+ UserName: user.UserName,
907
+ IdType: user.IDType,
908
+ IdNo: user.IDNo,
909
+ ContactNo: user.ContactNo,
910
+ });
911
+ const defaultPassword = User.generateDefaultPassword();
912
+ user = yield User.setPassword(dbTransaction, user, defaultPassword);
913
+ const userInfo = {
914
+ UserName: user.UserName,
915
+ FullName: user.FullName,
916
+ IDNo: user.IDNo,
917
+ Email: user.Email,
918
+ ContactNo: user.ContactNo,
919
+ Password: user.Password,
920
+ Status: enum_1.UserStatus.ACTIVE,
921
+ FirstLoginAt: null,
922
+ LastLoginAt: null,
923
+ MFAEnabled: null,
924
+ MFAConfig: null,
925
+ RecoveryEmail: null,
926
+ FailedLoginAttemptCount: 0,
927
+ LastFailedLoginAt: null,
928
+ LastPasswordChangedAt: null,
929
+ DefaultPasswordChangedYN: yn_enum_1.YN.No,
930
+ NeedToChangePasswordYN: yn_enum_1.YN.Yes,
931
+ CreatedById: loginUser.UserId,
932
+ CreatedAt: new Date(),
933
+ UpdatedById: loginUser.UserId,
934
+ UpdatedAt: new Date(),
935
+ UserId: null,
936
+ };
937
+ const newUser = yield User._Repository.create({
938
+ Email: userInfo.Email,
939
+ UserName: userInfo.UserName,
940
+ Password: userInfo.Password,
941
+ Status: userInfo.Status,
942
+ DefaultPasswordChangedYN: userInfo.DefaultPasswordChangedYN,
943
+ FirstLoginAt: userInfo.FirstLoginAt,
944
+ LastLoginAt: userInfo.LastLoginAt,
945
+ MFAEnabled: userInfo.MFAEnabled,
946
+ MFAConfig: userInfo.MFAConfig,
947
+ RecoveryEmail: userInfo.RecoveryEmail,
948
+ FailedLoginAttemptCount: userInfo.FailedLoginAttemptCount,
949
+ LastFailedLoginAt: userInfo.LastFailedLoginAt,
950
+ LastPasswordChangedAt: userInfo.LastPasswordChangedAt,
951
+ NeedToChangePasswordYN: userInfo.NeedToChangePasswordYN,
952
+ CreatedById: userInfo.CreatedById,
953
+ CreatedAt: userInfo.CreatedAt,
954
+ UpdatedById: userInfo.UpdatedById,
955
+ UpdatedAt: userInfo.UpdatedAt,
956
+ }, {
957
+ transaction: dbTransaction,
958
+ });
959
+ userInfo.UserId = newUser.UserId;
960
+ const userToBeCreated = new User(loginUser.SessionService, dbTransaction, userInfo);
961
+ const activity = new activity_history_1.Activity();
962
+ activity.ActivityId = activity.createId();
963
+ activity.Action = activity_history_1.ActionEnum.ADD;
964
+ activity.Description = 'Create User';
965
+ activity.EntityType = 'LoginUser';
966
+ activity.EntityId = newUser.UserId.toString();
967
+ activity.EntityValueBefore = JSON.stringify({});
968
+ activity.EntityValueAfter = JSON.stringify(newUser.get({ plain: true }));
969
+ yield activity.create(loginUser.ObjectId, dbTransaction);
970
+ return userToBeCreated;
971
+ }
972
+ catch (error) {
973
+ throw error;
974
+ }
975
+ });
976
+ }
977
+ incrementFailedLoginAttemptCount(dbTransaction) {
978
+ return __awaiter(this, void 0, void 0, function* () {
979
+ const maxFailedLoginAttempts = config_1.ComponentConfig.getComponentConfigValue('@tomei/sso', 'maxFailedLoginAttempts');
980
+ const autoReleaseYN = config_1.ComponentConfig.getComponentConfigValue('@tomei/sso', 'autoReleaseYN');
981
+ if (!maxFailedLoginAttempts || !autoReleaseYN) {
982
+ throw new general_1.ClassError('LoginUser', 'LoginUserErrMsg0X', 'Missing maxFailedLoginAttempts and or autoReleaseYN. Please set in config file.');
983
+ }
984
+ const FailedLoginAttemptCount = this.FailedLoginAttemptCount + 1;
985
+ const LastFailedLoginAt = new Date();
986
+ if (FailedLoginAttemptCount > maxFailedLoginAttempts) {
987
+ this.Status = enum_1.UserStatus.LOCKED;
988
+ }
989
+ yield User._Repository.update({
990
+ FailedLoginAttemptCount: FailedLoginAttemptCount,
991
+ LastFailedLoginAt: LastFailedLoginAt,
992
+ Status: this.Status,
993
+ }, {
994
+ where: {
995
+ UserId: this.UserId,
996
+ },
997
+ transaction: dbTransaction,
998
+ });
999
+ if (this.Status === enum_1.UserStatus.LOCKED && autoReleaseYN === 'Y') {
1000
+ throw new general_1.ClassError('LoginUser', 'LoginUserErrMsg0X', 'Your account has been temporarily locked due to too many failed login attempts, please try again later.');
1001
+ }
1002
+ if (this.Status === enum_1.UserStatus.LOCKED && autoReleaseYN === 'N') {
1003
+ throw new general_1.ClassError('LoginUser', 'LoginUserErrMsg0X', 'Your account has been locked due to too many failed login attempts, please contact IT Support for instructions on how to unlock your account');
1004
+ }
1005
+ if (this.Status == enum_1.UserStatus.LOCKED) {
1006
+ throw new general_1.ClassError('LoginUser', 'LoginUserErrMsg0X', 'Invalid credentials.');
1007
+ }
1008
+ });
1009
+ }
1010
+ static shouldReleaseLock(LastFailedLoginAt) {
1011
+ const minuteToAutoRelease = config_1.ComponentConfig.getComponentConfigValue('@tomei/sso', 'minuteToAutoRelease');
1012
+ const autoReleaseYN = config_1.ComponentConfig.getComponentConfigValue('@tomei/sso', 'autoReleaseYN');
1013
+ if (!minuteToAutoRelease || !autoReleaseYN) {
1014
+ throw new general_1.ClassError('LoginUser', 'LoginUserErrMsg0X', 'Missing minuteToAutoRelease and or autoReleaseYN. Please set in config file.');
1015
+ }
1016
+ if (autoReleaseYN === 'Y') {
1017
+ const lastFailedDate = new Date(LastFailedLoginAt);
1018
+ const currentDate = new Date();
1019
+ const timeDifferenceInMillis = currentDate.getTime() - lastFailedDate.getTime();
1020
+ const timeDifferenceInMinutes = timeDifferenceInMillis / (1000 * 60);
1021
+ if (timeDifferenceInMinutes > +minuteToAutoRelease) {
1022
+ return true;
1023
+ }
1024
+ else {
1025
+ return false;
1026
+ }
1027
+ }
1028
+ else if (autoReleaseYN === 'N') {
1029
+ return false;
1030
+ }
1031
+ }
1032
+ static releaseLock(UserId, dbTransaction) {
1033
+ this._Repository.update({
1034
+ FailedLoginAttemptCount: 0,
1035
+ Status: enum_1.UserStatus.ACTIVE,
1036
+ }, {
1037
+ where: {
1038
+ UserId: UserId,
1039
+ },
1040
+ transaction: dbTransaction,
1041
+ });
1042
+ }
1043
+ static getGroups(loginUser, dbTransaction) {
1044
+ return __awaiter(this, void 0, void 0, function* () {
1045
+ const systemCode = config_1.ApplicationConfig.getComponentConfigValue('system-code');
1046
+ const isPrivileged = yield loginUser.checkPrivileges(systemCode, 'UserGroup - List Own');
1047
+ if (!isPrivileged) {
1048
+ throw new Error('You do not have permission to list UserGroup.');
1049
+ }
1050
+ const userGroups = yield User._UserGroupRepo.findAll({
1051
+ where: {
1052
+ UserId: loginUser.ObjectId,
1053
+ Status: 'Active',
1054
+ },
1055
+ include: [{ model: user_entity_1.default, as: 'User' }, { model: group_entity_1.default }],
1056
+ transaction: dbTransaction,
1057
+ });
1058
+ return userGroups;
1059
+ });
1060
+ }
1061
+ static getInheritedSystemAccess(dbTransaction, group) {
1062
+ return __awaiter(this, void 0, void 0, function* () {
1063
+ const dataSystemAccesses = yield User._GroupSystemAccessRepo.findAll({
1064
+ where: {
1065
+ GroupCode: group.GroupCode,
1066
+ Status: 'Active',
1067
+ },
1068
+ include: [{ model: system_entity_1.default }],
1069
+ transaction: dbTransaction,
1070
+ });
1071
+ let systemAccesses = dataSystemAccesses;
1072
+ if (group.InheritParentPrivilegeYN === 'Y' && group.ParentGroupCode) {
1073
+ const GroupCode = group.ParentGroupCode;
1074
+ const parentGroup = yield User._GroupRepo.findByPk(GroupCode, dbTransaction);
1075
+ const dataParentSystemAccesses = yield User.getInheritedSystemAccess(dbTransaction, parentGroup);
1076
+ const parentSystemAccesses = dataParentSystemAccesses;
1077
+ systemAccesses = systemAccesses.concat(parentSystemAccesses);
1078
+ }
1079
+ return systemAccesses;
1080
+ });
1081
+ }
1082
+ static combineSystemAccess(loginUser, dbTransaction, groups) {
1083
+ return __awaiter(this, void 0, void 0, function* () {
1084
+ const userAccess = yield User._UserSystemAccessRepo.findAll({
1085
+ where: {
1086
+ UserId: loginUser.ObjectId,
1087
+ Status: 'Active',
1088
+ },
1089
+ include: [{ model: system_entity_1.default }],
1090
+ transaction: dbTransaction,
1091
+ });
1092
+ const groupAccessPromises = groups.map((e) => __awaiter(this, void 0, void 0, function* () {
1093
+ if (e.InheritParentSystemAccessYN) {
1094
+ return yield this.getInheritedSystemAccess(dbTransaction, e);
1095
+ }
1096
+ else {
1097
+ return [];
1098
+ }
1099
+ }));
1100
+ const groupAccess = (yield Promise.all(groupAccessPromises)).flat();
1101
+ const allAccess = userAccess.concat(groupAccess);
1102
+ const uniqueAccess = new Set(allAccess.filter((value, index, self) => {
1103
+ return self.some((prev) => prev.SystemCode === value.SystemCode);
1104
+ }));
1105
+ return Array.from(uniqueAccess);
1106
+ });
1107
+ }
1108
+ static getSystems(loginUser, dbTransaction) {
1109
+ return __awaiter(this, void 0, void 0, function* () {
1110
+ const systemCode = config_1.ApplicationConfig.getComponentConfigValue('system-code');
1111
+ const isPrivileged = yield loginUser.checkPrivileges(systemCode, 'System – List Own');
1112
+ if (!isPrivileged) {
1113
+ throw new Error('You do not have permission to list UserGroup.');
1114
+ }
1115
+ const groups = yield User.getGroups(loginUser, dbTransaction);
1116
+ const systemAccess = yield User.combineSystemAccess(loginUser, dbTransaction, groups);
1117
+ const output = [];
1118
+ if (systemAccess) {
1119
+ for (let i = 0; i < systemAccess.length; i++) {
1120
+ const system = yield User._SystemRepository.findOne({
1121
+ where: {
1122
+ SystemCode: systemAccess[i].SystemCode,
1123
+ Status: 'Active',
1124
+ },
1125
+ });
1126
+ output.push({
1127
+ UserSystemAccessId: systemAccess[i].UserSystemAccessId,
1128
+ UserId: systemAccess[i].UserId,
1129
+ SystemCode: systemAccess[i].SystemCode,
1130
+ Status: systemAccess[i].Status,
1131
+ CreatedById: systemAccess[i].CreatedById,
1132
+ UpdatedById: systemAccess[i].UpdatedById,
1133
+ CreatedAt: systemAccess[i].CreatedAt,
1134
+ UpdatedAt: systemAccess[i].UpdatedAt,
1135
+ System: system,
1136
+ });
1137
+ }
1138
+ }
1139
+ return output;
1140
+ });
1141
+ }
1142
+ static check2FA(loginUser, dbTransaction) {
1143
+ return __awaiter(this, void 0, void 0, function* () {
1144
+ try {
1145
+ const user = yield User._Repository.findOne({
1146
+ where: {
1147
+ UserId: loginUser.UserId,
1148
+ },
1149
+ transaction: dbTransaction,
1150
+ });
1151
+ if (user.MFAEnabled === 1) {
1152
+ return true;
1153
+ }
1154
+ return false;
1155
+ }
1156
+ catch (error) {
1157
+ throw error;
1158
+ }
1159
+ });
1160
+ }
1161
+ static setup2FA(userId, dbTransaction) {
1162
+ var _a, _b, _c, _d;
1163
+ return __awaiter(this, void 0, void 0, function* () {
1164
+ const systemCode = config_1.ApplicationConfig.getComponentConfigValue('system-code');
1165
+ const user = yield User._Repository.findOne({
1166
+ where: {
1167
+ UserId: userId,
1168
+ },
1169
+ });
1170
+ if (!user) {
1171
+ throw new general_1.ClassError('LoginUser', 'LoginUserErrMsg0X', 'Invalid Credentials');
1172
+ }
1173
+ const secretCode = speakeasy.generateSecret({ name: systemCode });
1174
+ let userMFAConfig = null;
1175
+ if ((user === null || user === void 0 ? void 0 : user.MFAConfig) !== null && typeof (user === null || user === void 0 ? void 0 : user.MFAConfig) === 'string') {
1176
+ try {
1177
+ userMFAConfig = JSON.parse(user === null || user === void 0 ? void 0 : user.MFAConfig);
1178
+ }
1179
+ catch (error) {
1180
+ console.error('Invalid JSON string on MFAConfig:', error);
1181
+ }
1182
+ }
1183
+ const MFAConfig = {
1184
+ totp: {
1185
+ enabled: true,
1186
+ secret: secretCode.base32,
1187
+ issuer: systemCode,
1188
+ },
1189
+ sms: {
1190
+ enabled: ((_a = userMFAConfig === null || userMFAConfig === void 0 ? void 0 : userMFAConfig.sms) === null || _a === void 0 ? void 0 : _a.enable) || false,
1191
+ phoneNumber: ((_b = userMFAConfig === null || userMFAConfig === void 0 ? void 0 : userMFAConfig.sms) === null || _b === void 0 ? void 0 : _b.phoneNumber) || '',
1192
+ },
1193
+ email: {
1194
+ enabled: ((_c = userMFAConfig === null || userMFAConfig === void 0 ? void 0 : userMFAConfig.email) === null || _c === void 0 ? void 0 : _c.enable) || false,
1195
+ emailAddress: ((_d = userMFAConfig === null || userMFAConfig === void 0 ? void 0 : userMFAConfig.email) === null || _d === void 0 ? void 0 : _d.emailAddress) || '',
1196
+ },
1197
+ };
1198
+ user.MFAEnabled = 0;
1199
+ user.MFAConfig = JSON.stringify(MFAConfig);
1200
+ yield User._Repository.update({
1201
+ MFAEnabled: user.MFAEnabled,
1202
+ MFAConfig: user.MFAConfig,
1203
+ }, {
1204
+ where: {
1205
+ UserId: userId,
1206
+ },
1207
+ transaction: dbTransaction,
1208
+ });
1209
+ return secretCode.otpauth_url;
1210
+ });
1211
+ }
1212
+ verify2FASetup(userId, mfaToken, dbTransaction) {
1213
+ return __awaiter(this, void 0, void 0, function* () {
1214
+ const user = yield User._Repository.findOne({
1215
+ where: {
1216
+ UserId: userId,
1217
+ },
1218
+ });
1219
+ if (!user) {
1220
+ throw new general_1.ClassError('LoginUser', 'LoginUserErrMsg0X', 'Invalid Credentials');
1221
+ }
1222
+ let userMFAConfig = null;
1223
+ if ((user === null || user === void 0 ? void 0 : user.MFAConfig) !== null && typeof (user === null || user === void 0 ? void 0 : user.MFAConfig) === 'string') {
1224
+ try {
1225
+ userMFAConfig = JSON.parse(user === null || user === void 0 ? void 0 : user.MFAConfig);
1226
+ }
1227
+ catch (error) {
1228
+ console.error('Invalid JSON string on MFAConfig:', error);
1229
+ }
1230
+ }
1231
+ const isVerified = yield speakeasy.totp.verify({
1232
+ secret: userMFAConfig.totp.secret,
1233
+ encoding: 'base32',
1234
+ token: mfaToken,
1235
+ });
1236
+ if (!isVerified) {
1237
+ return false;
1238
+ }
1239
+ yield User._Repository.update({
1240
+ MFAEnabled: 1,
1241
+ }, {
1242
+ where: {
1243
+ UserId: userId,
1244
+ },
1245
+ transaction: dbTransaction,
1246
+ });
1247
+ const userSession = yield this._SessionService.retrieveUserSession(`${userId}`);
1248
+ const systemCode = config_1.ApplicationConfig.getComponentConfigValue('system-code');
1249
+ const systemLogin = userSession.systemLogins.find((e) => e.code === systemCode);
1250
+ return `${userId}:${systemLogin.sessionId}`;
1251
+ });
1252
+ }
1253
+ verify2FACode(userId, mfaToken, dbTransaction) {
1254
+ return __awaiter(this, void 0, void 0, function* () {
1255
+ const user = yield User._Repository.findOne({
1256
+ where: {
1257
+ UserId: userId,
1258
+ },
1259
+ transaction: dbTransaction,
1260
+ });
1261
+ if (!user) {
1262
+ throw new general_1.ClassError('LoginUser', 'LoginUserErrMsg0X', 'Invalid Credentials');
1263
+ }
1264
+ let userMFAConfig = null;
1265
+ if ((user === null || user === void 0 ? void 0 : user.MFAConfig) !== null && typeof (user === null || user === void 0 ? void 0 : user.MFAConfig) === 'string') {
1266
+ try {
1267
+ userMFAConfig = JSON.parse(user === null || user === void 0 ? void 0 : user.MFAConfig);
1268
+ }
1269
+ catch (error) {
1270
+ console.error('Invalid JSON string on MFAConfig:', error);
1271
+ }
1272
+ }
1273
+ const isVerified = yield speakeasy.totp.verify({
1274
+ secret: userMFAConfig.totp.secret,
1275
+ encoding: 'base32',
1276
+ token: mfaToken,
1277
+ });
1278
+ if (!isVerified) {
1279
+ return false;
1280
+ }
1281
+ const userSession = yield this._SessionService.retrieveUserSession(`${userId}`);
1282
+ const systemCode = config_1.ApplicationConfig.getComponentConfigValue('system-code');
1283
+ const systemLogin = userSession.systemLogins.find((e) => e.code === systemCode);
1284
+ return `${userId}:${systemLogin.sessionId}`;
1285
+ });
1286
+ }
1287
+ addUserGroup(GroupCode, loginUser, dbTransaction) {
1288
+ return __awaiter(this, void 0, void 0, function* () {
1289
+ const group = yield User._GroupRepo.findOne({
1290
+ where: {
1291
+ GroupCode,
1292
+ },
1293
+ transaction: dbTransaction,
1294
+ });
1295
+ if (!group) {
1296
+ throw new general_1.ClassError('LoginUser', 'LoginUserErrMsg0X', 'Invalid Group Code');
1297
+ }
1298
+ const entityValueAfter = {
1299
+ UserId: this.UserId,
1300
+ GroupCode: group.GroupCode,
1301
+ CreatedAt: new Date(),
1302
+ CreatedById: loginUser.UserId,
1303
+ UpdatedAt: new Date(),
1304
+ UpdatedById: loginUser.UserId,
1305
+ };
1306
+ yield User._UserGroupRepo.create(entityValueAfter, {
1307
+ transaction: dbTransaction,
1308
+ });
1309
+ const activity = new activity_history_1.Activity();
1310
+ activity.ActivityId = activity.createId();
1311
+ activity.Action = activity_history_1.ActionEnum.ADD;
1312
+ activity.Description = 'Add User Group';
1313
+ activity.EntityType = 'UserGroup';
1314
+ activity.EntityId = group.GroupCode;
1315
+ activity.EntityValueBefore = JSON.stringify({});
1316
+ activity.EntityValueAfter = JSON.stringify(entityValueAfter);
1317
+ yield activity.create(loginUser.ObjectId, dbTransaction);
1318
+ });
1319
+ }
1320
+ update(data, loginUser, dbTransaction) {
1321
+ return __awaiter(this, void 0, void 0, function* () {
1322
+ const systemCode = config_1.ApplicationConfig.getComponentConfigValue('system-code');
1323
+ const isPrivileged = yield loginUser.checkPrivileges(systemCode, 'User - Update');
1324
+ if (!isPrivileged) {
1325
+ throw new general_1.ClassError('LoginUser', 'LoginUserErrMsg0X', 'You do not have the privilege to update user');
1326
+ }
1327
+ if (!this.UserId) {
1328
+ throw new general_1.ClassError('LoginUser', 'LoginUserErrMsg0X', 'UserId is required');
1329
+ }
1330
+ if (data.Email !== this.Email || data.UserName !== this.UserName) {
1331
+ yield User.checkUserInfoDuplicated(dbTransaction, {
1332
+ Email: data.Email,
1333
+ UserName: data.UserName,
1334
+ });
1335
+ }
1336
+ if (data.BuildingCode) {
1337
+ const building = yield group_entity_1.default.findOne({
1338
+ where: {
1339
+ Type: 'Building',
1340
+ GroupCode: data.BuildingCode,
1341
+ },
1342
+ transaction: dbTransaction,
1343
+ });
1344
+ if (!building) {
1345
+ throw new general_1.ClassError('LoginUser', 'LoginUserErrMsg0X', 'Invalid Building Code');
1346
+ }
1347
+ const userBuilding = yield User._UserGroupRepo.findOne({
1348
+ where: {
1349
+ UserId: this.UserId,
1350
+ },
1351
+ include: [
1352
+ {
1353
+ model: group_entity_1.default,
1354
+ where: {
1355
+ Type: 'Building',
1356
+ },
1357
+ },
1358
+ ],
1359
+ transaction: dbTransaction,
1360
+ });
1361
+ if (userBuilding) {
1362
+ yield User._UserGroupRepo.update({
1363
+ GroupCode: data.BuildingCode,
1364
+ UpdatedAt: new Date(),
1365
+ UpdatedById: loginUser.UserId,
1366
+ }, {
1367
+ where: {
1368
+ UserId: this.UserId,
1369
+ GroupCode: userBuilding.GroupCode,
1370
+ },
1371
+ transaction: dbTransaction,
1372
+ });
1373
+ }
1374
+ else {
1375
+ yield User._UserGroupRepo.create({
1376
+ UserId: this.UserId,
1377
+ GroupCode: data.BuildingCode,
1378
+ CreatedAt: new Date(),
1379
+ CreatedById: loginUser.UserId,
1380
+ UpdatedAt: new Date(),
1381
+ UpdatedById: loginUser.UserId,
1382
+ }, {
1383
+ transaction: dbTransaction,
1384
+ });
1385
+ }
1386
+ }
1387
+ if (data.CompanyCode) {
1388
+ const company = yield group_entity_1.default.findOne({
1389
+ where: {
1390
+ Type: 'Company',
1391
+ GroupCode: data.CompanyCode,
1392
+ },
1393
+ transaction: dbTransaction,
1394
+ });
1395
+ if (!company) {
1396
+ throw new general_1.ClassError('LoginUser', 'LoginUserErrMsg0X', 'Invalid Company Code');
1397
+ }
1398
+ const userCompany = yield User._UserGroupRepo.findOne({
1399
+ where: {
1400
+ UserId: this.UserId,
1401
+ },
1402
+ include: [
1403
+ {
1404
+ model: group_entity_1.default,
1405
+ where: {
1406
+ Type: 'Company',
1407
+ },
1408
+ },
1409
+ ],
1410
+ transaction: dbTransaction,
1411
+ });
1412
+ if (userCompany) {
1413
+ yield User._UserGroupRepo.update({
1414
+ GroupCode: data.CompanyCode,
1415
+ UpdatedAt: new Date(),
1416
+ UpdatedById: loginUser.UserId,
1417
+ }, {
1418
+ where: {
1419
+ UserId: this.UserId,
1420
+ GroupCode: userCompany.GroupCode,
1421
+ },
1422
+ transaction: dbTransaction,
1423
+ });
1424
+ }
1425
+ else {
1426
+ yield User._UserGroupRepo.create({
1427
+ UserId: this.UserId,
1428
+ GroupCode: data.CompanyCode,
1429
+ CreatedAt: new Date(),
1430
+ CreatedById: loginUser.UserId,
1431
+ UpdatedAt: new Date(),
1432
+ UpdatedById: loginUser.UserId,
1433
+ }, {
1434
+ transaction: dbTransaction,
1435
+ });
1436
+ }
1437
+ }
1438
+ if (data.DepartmentCode) {
1439
+ const department = yield group_entity_1.default.findOne({
1440
+ where: {
1441
+ Type: 'Department',
1442
+ GroupCode: data.DepartmentCode,
1443
+ },
1444
+ transaction: dbTransaction,
1445
+ });
1446
+ if (!department) {
1447
+ throw new general_1.ClassError('LoginUser', 'LoginUserErrMsg0X', 'Invalid Department Code');
1448
+ }
1449
+ const userDepartment = yield User._UserGroupRepo.findOne({
1450
+ where: {
1451
+ UserId: this.UserId,
1452
+ },
1453
+ include: [
1454
+ {
1455
+ model: group_entity_1.default,
1456
+ where: {
1457
+ Type: 'Department',
1458
+ },
1459
+ },
1460
+ ],
1461
+ transaction: dbTransaction,
1462
+ });
1463
+ if (userDepartment) {
1464
+ yield User._UserGroupRepo.update({
1465
+ GroupCode: data.DepartmentCode,
1466
+ UpdatedAt: new Date(),
1467
+ UpdatedById: loginUser.UserId,
1468
+ }, {
1469
+ where: {
1470
+ UserId: this.UserId,
1471
+ GroupCode: userDepartment.GroupCode,
1472
+ },
1473
+ transaction: dbTransaction,
1474
+ });
1475
+ }
1476
+ else {
1477
+ yield User._UserGroupRepo.create({
1478
+ UserId: this.UserId,
1479
+ GroupCode: data.DepartmentCode,
1480
+ CreatedAt: new Date(),
1481
+ CreatedById: loginUser.UserId,
1482
+ UpdatedAt: new Date(),
1483
+ UpdatedById: loginUser.UserId,
1484
+ }, {
1485
+ transaction: dbTransaction,
1486
+ });
1487
+ }
1488
+ }
1489
+ const entityValueBefore = {
1490
+ UserId: this.UserId,
1491
+ UserName: this.UserName,
1492
+ Email: this.Email,
1493
+ Password: this.Password,
1494
+ Status: this.Status,
1495
+ DefaultPasswordChangedYN: this.DefaultPasswordChangedYN,
1496
+ FirstLoginAt: this.FirstLoginAt,
1497
+ LastLoginAt: this.LastLoginAt,
1498
+ MFAEnabled: this.MFAEnabled,
1499
+ MFAConfig: this.MFAConfig,
1500
+ RecoveryEmail: this.RecoveryEmail,
1501
+ FailedLoginAttemptCount: this.FailedLoginAttemptCount,
1502
+ LastFailedLoginAt: this.LastFailedLoginAt,
1503
+ LastPasswordChangedAt: this.LastPasswordChangedAt,
1504
+ NeedToChangePasswordYN: this.NeedToChangePasswordYN,
1505
+ CreatedById: this.CreatedById,
1506
+ CreatedAt: this.CreatedAt,
1507
+ UpdatedById: this.UpdatedById,
1508
+ UpdatedAt: this.UpdatedAt,
1509
+ };
1510
+ this.UserName = data.UserName;
1511
+ this.Email = data.Email;
1512
+ this.Status = data.Status;
1513
+ this.RecoveryEmail = data.RecoveryEmail;
1514
+ this.UpdatedAt = new Date();
1515
+ this.UpdatedById = loginUser.UserId;
1516
+ yield User._Repository.update({
1517
+ UserName: this.UserName,
1518
+ Email: this.Email,
1519
+ Status: this.Status,
1520
+ RecoveryEmail: this.RecoveryEmail,
1521
+ UpdatedById: this.UpdatedById,
1522
+ UpdatedAt: this.UpdatedAt,
1523
+ }, {
1524
+ where: {
1525
+ UserId: this.UserId,
1526
+ },
1527
+ transaction: dbTransaction,
1528
+ });
1529
+ const entityValueAfter = {
1530
+ UserId: this.UserId,
1531
+ UserName: this.UserName,
1532
+ Email: this.Email,
1533
+ Password: this.Password,
1534
+ Status: this.Status,
1535
+ DefaultPasswordChangedYN: this.DefaultPasswordChangedYN,
1536
+ FirstLoginAt: this.FirstLoginAt,
1537
+ LastLoginAt: this.LastLoginAt,
1538
+ MFAEnabled: this.MFAEnabled,
1539
+ MFAConfig: this.MFAConfig,
1540
+ RecoveryEmail: this.RecoveryEmail,
1541
+ FailedLoginAttemptCount: this.FailedLoginAttemptCount,
1542
+ LastFailedLoginAt: this.LastFailedLoginAt,
1543
+ LastPasswordChangedAt: this.LastPasswordChangedAt,
1544
+ NeedToChangePasswordYN: this.NeedToChangePasswordYN,
1545
+ CreatedById: this.CreatedById,
1546
+ CreatedAt: this.CreatedAt,
1547
+ UpdatedById: this.UpdatedById,
1548
+ UpdatedAt: this.UpdatedAt,
1549
+ };
1550
+ const activity = new activity_history_1.Activity();
1551
+ activity.ActivityId = activity.createId();
1552
+ activity.Action = activity_history_1.ActionEnum.UPDATE;
1553
+ activity.Description = 'Update User';
1554
+ activity.EntityType = 'LoginUser';
1555
+ activity.EntityId = this.UserId.toString();
1556
+ activity.EntityValueBefore = JSON.stringify(entityValueBefore);
1557
+ activity.EntityValueAfter = JSON.stringify(entityValueAfter);
1558
+ yield activity.create(loginUser.ObjectId, dbTransaction);
1559
+ return this;
1560
+ });
1561
+ }
1562
+ static findById(loginUser, dbTransaction, UserId) {
1563
+ var _a, _b, _c;
1564
+ return __awaiter(this, void 0, void 0, function* () {
1565
+ const systemCode = config_1.ApplicationConfig.getComponentConfigValue('system-code');
1566
+ const isPrivileged = yield loginUser.checkPrivileges(systemCode, 'USER_VIEW');
1567
+ if (!isPrivileged) {
1568
+ throw new general_1.ClassError('LoginUser', 'LoginUserErrMsg0X', 'You do not have the privilege to find user');
1569
+ }
1570
+ const user = yield User._Repository.findOne({
1571
+ where: {
1572
+ UserId: UserId,
1573
+ Status: 'Active',
1574
+ },
1575
+ transaction: dbTransaction,
1576
+ });
1577
+ const userAttr = {
1578
+ UserId: user.UserId,
1579
+ UserName: user.UserName,
1580
+ FullName: ((_a = user === null || user === void 0 ? void 0 : user.Staff) === null || _a === void 0 ? void 0 : _a.FullName) || null,
1581
+ IDNo: ((_b = user === null || user === void 0 ? void 0 : user.Staff) === null || _b === void 0 ? void 0 : _b.IdNo) || null,
1582
+ ContactNo: ((_c = user === null || user === void 0 ? void 0 : user.Staff) === null || _c === void 0 ? void 0 : _c.Mobile) || null,
1583
+ Email: user.Email,
1584
+ Password: user.Password,
1585
+ Status: user.Status,
1586
+ DefaultPasswordChangedYN: user.DefaultPasswordChangedYN,
1587
+ FirstLoginAt: user.FirstLoginAt,
1588
+ LastLoginAt: user.LastLoginAt,
1589
+ MFAEnabled: user.MFAEnabled,
1590
+ MFAConfig: user.MFAConfig,
1591
+ RecoveryEmail: user.RecoveryEmail,
1592
+ FailedLoginAttemptCount: user.FailedLoginAttemptCount,
1593
+ LastFailedLoginAt: user.LastFailedLoginAt,
1594
+ LastPasswordChangedAt: user.LastPasswordChangedAt,
1595
+ NeedToChangePasswordYN: user.NeedToChangePasswordYN,
1596
+ CreatedById: user.CreatedById,
1597
+ CreatedAt: user.CreatedAt,
1598
+ UpdatedById: user.UpdatedById,
1599
+ UpdatedAt: user.UpdatedAt,
1600
+ staffs: (user === null || user === void 0 ? void 0 : user.Staff) || null,
1601
+ };
1602
+ return new User(null, dbTransaction, userAttr);
1603
+ });
1604
+ }
1605
+ }
1606
+ exports.User = User;
1607
+ User._Repository = new user_repository_1.UserRepository();
1608
+ User._LoginHistoryRepository = new login_history_repository_1.LoginHistoryRepository();
1609
+ User._UserGroupRepo = new user_group_repository_1.UserGroupRepository();
1610
+ User._UserPrivilegeRepo = new user_privilege_repository_1.UserPrivilegeRepository();
1611
+ User._UserObjectPrivilegeRepo = new user_object_privilege_repository_1.UserObjectPrivilegeRepository();
1612
+ User._GroupObjectPrivilegeRepo = new group_object_privilege_repository_1.GroupObjectPrivilegeRepository();
1613
+ User._SystemRepository = new system_repository_1.SystemRepository();
1614
+ User._UserSystemAccessRepo = new user_system_access_repository_1.UserSystemAccessRepository();
1615
+ User._GroupSystemAccessRepo = new group_system_access_repository_1.GroupSystemAccessRepository();
1616
+ User._GroupRepo = new group_repository_1.GroupRepository();
1617
+ //# sourceMappingURL=user.js.map