@tomei/sso 0.15.5 → 0.15.6
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/__tests__/unit/components/login-user/login-user.spec.d.ts +1 -0
- package/dist/__tests__/unit/components/login-user/login-user.spec.js +663 -0
- package/dist/__tests__/unit/components/login-user/login-user.spec.js.map +1 -0
- package/dist/__tests__/unit/components/password-hash/password-hash.service.spec.d.ts +1 -0
- package/dist/__tests__/unit/components/password-hash/password-hash.service.spec.js +38 -0
- package/dist/__tests__/unit/components/password-hash/password-hash.service.spec.js.map +1 -0
- package/dist/__tests__/unit/redis-client/redis.service.spec.d.ts +1 -0
- package/dist/__tests__/unit/redis-client/redis.service.spec.js +32 -0
- package/dist/__tests__/unit/redis-client/redis.service.spec.js.map +1 -0
- package/dist/__tests__/unit/session/session.service.spec.d.ts +1 -0
- package/dist/__tests__/unit/session/session.service.spec.js +55 -0
- package/dist/__tests__/unit/session/session.service.spec.js.map +1 -0
- package/dist/__tests__/unit/system-privilege/system-privilage.spec.d.ts +0 -0
- package/dist/__tests__/unit/system-privilege/system-privilage.spec.js +6 -0
- package/dist/__tests__/unit/system-privilege/system-privilage.spec.js.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +18 -0
- package/dist/index.js.map +1 -0
- package/dist/src/components/building/building.d.ts +39 -0
- package/dist/src/components/building/building.js +129 -0
- package/dist/src/components/building/building.js.map +1 -0
- package/dist/src/components/building/building.repository.d.ts +6 -0
- package/dist/src/components/building/building.repository.js +38 -0
- package/dist/src/components/building/building.repository.js.map +1 -0
- package/dist/src/components/building/index.d.ts +2 -0
- package/dist/src/components/building/index.js +19 -0
- package/dist/src/components/building/index.js.map +1 -0
- package/dist/src/components/building-type/building-type.repository.d.ts +5 -0
- package/dist/src/components/building-type/building-type.repository.js +12 -0
- package/dist/src/components/building-type/building-type.repository.js.map +1 -0
- package/dist/src/components/building-type/index.d.ts +1 -0
- package/dist/src/components/building-type/index.js +18 -0
- package/dist/src/components/building-type/index.js.map +1 -0
- package/dist/src/components/index.d.ts +10 -0
- package/dist/src/components/index.js +27 -0
- package/dist/src/components/index.js.map +1 -0
- package/dist/src/components/login-history/index.d.ts +1 -0
- package/dist/src/components/login-history/index.js +18 -0
- package/dist/src/components/login-history/index.js.map +1 -0
- package/dist/src/components/login-history/login-history.repository.d.ts +5 -0
- package/dist/src/components/login-history/login-history.repository.js +12 -0
- package/dist/src/components/login-history/login-history.repository.js.map +1 -0
- package/dist/src/components/login-user/index.d.ts +3 -0
- package/dist/src/components/login-user/index.js +20 -0
- package/dist/src/components/login-user/index.js.map +1 -0
- package/dist/src/components/login-user/interfaces/index.d.ts +1 -0
- package/dist/src/components/login-user/interfaces/index.js +18 -0
- package/dist/src/components/login-user/interfaces/index.js.map +1 -0
- package/dist/src/components/login-user/interfaces/user-info.interface.d.ts +27 -0
- package/dist/src/components/login-user/interfaces/user-info.interface.js +3 -0
- package/dist/src/components/login-user/interfaces/user-info.interface.js.map +1 -0
- package/dist/src/components/login-user/login-user.d.ts +92 -0
- package/dist/src/components/login-user/login-user.js +588 -0
- package/dist/src/components/login-user/login-user.js.map +1 -0
- package/dist/src/components/login-user/user.repository.d.ts +5 -0
- package/dist/src/components/login-user/user.repository.js +12 -0
- package/dist/src/components/login-user/user.repository.js.map +1 -0
- package/dist/src/components/password-hash/index.d.ts +2 -0
- package/dist/src/components/password-hash/index.js +19 -0
- package/dist/src/components/password-hash/index.js.map +1 -0
- package/dist/src/components/password-hash/interfaces/index.d.ts +1 -0
- package/dist/src/components/password-hash/interfaces/index.js +18 -0
- package/dist/src/components/password-hash/interfaces/index.js.map +1 -0
- package/dist/src/components/password-hash/interfaces/password-hash-service.interface.d.ts +4 -0
- package/dist/src/components/password-hash/interfaces/password-hash-service.interface.js +3 -0
- package/dist/src/components/password-hash/interfaces/password-hash-service.interface.js.map +1 -0
- package/dist/src/components/password-hash/password-hash.service.d.ts +6 -0
- package/dist/src/components/password-hash/password-hash.service.js +28 -0
- package/dist/src/components/password-hash/password-hash.service.js.map +1 -0
- package/dist/src/components/staff/index.d.ts +2 -0
- package/dist/src/components/staff/index.js +19 -0
- package/dist/src/components/staff/index.js.map +1 -0
- package/dist/src/components/staff/staff.d.ts +50 -0
- package/dist/src/components/staff/staff.js +102 -0
- package/dist/src/components/staff/staff.js.map +1 -0
- package/dist/src/components/staff/staff.repository.d.ts +6 -0
- package/dist/src/components/staff/staff.repository.js +38 -0
- package/dist/src/components/staff/staff.repository.js.map +1 -0
- package/dist/src/components/system/index.d.ts +1 -0
- package/dist/src/components/system/index.js +18 -0
- package/dist/src/components/system/index.js.map +1 -0
- package/dist/src/components/system/system.repository.d.ts +5 -0
- package/dist/src/components/system/system.repository.js +12 -0
- package/dist/src/components/system/system.repository.js.map +1 -0
- package/dist/src/components/system-access/index.d.ts +1 -0
- package/dist/src/components/system-access/index.js +18 -0
- package/dist/src/components/system-access/index.js.map +1 -0
- package/dist/src/components/system-access/system-access.repository.d.ts +5 -0
- package/dist/src/components/system-access/system-access.repository.js +12 -0
- package/dist/src/components/system-access/system-access.repository.js.map +1 -0
- package/dist/src/components/system-privilege/privilege.d.ts +6 -0
- package/dist/src/components/system-privilege/privilege.js +77 -0
- package/dist/src/components/system-privilege/privilege.js.map +1 -0
- package/dist/src/components/system-privilege/system-privilege.repository.d.ts +6 -0
- package/dist/src/components/system-privilege/system-privilege.repository.js +35 -0
- package/dist/src/components/system-privilege/system-privilege.repository.js.map +1 -0
- package/dist/src/components/user-group/index.d.ts +1 -0
- package/dist/src/components/user-group/index.js +18 -0
- package/dist/src/components/user-group/index.js.map +1 -0
- package/dist/src/components/user-group/user-group.repository.d.ts +5 -0
- package/dist/src/components/user-group/user-group.repository.js +12 -0
- package/dist/src/components/user-group/user-group.repository.js.map +1 -0
- package/dist/src/components/user-user-group/index.d.ts +1 -0
- package/dist/src/components/user-user-group/index.js +18 -0
- package/dist/src/components/user-user-group/index.js.map +1 -0
- package/dist/src/components/user-user-group/user-user-group.repository.d.ts +5 -0
- package/dist/src/components/user-user-group/user-user-group.repository.js +12 -0
- package/dist/src/components/user-user-group/user-user-group.repository.js.map +1 -0
- package/dist/src/database.d.ts +4 -0
- package/dist/src/database.js +15 -0
- package/dist/src/database.js.map +1 -0
- package/dist/src/enum/index.d.ts +1 -0
- package/dist/src/enum/index.js +18 -0
- package/dist/src/enum/index.js.map +1 -0
- package/dist/src/enum/yn.enum.d.ts +4 -0
- package/dist/src/enum/yn.enum.js +9 -0
- package/dist/src/enum/yn.enum.js.map +1 -0
- package/dist/src/index.d.ts +5 -0
- package/dist/src/index.js +24 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/interfaces/index.d.ts +2 -0
- package/dist/src/interfaces/index.js +19 -0
- package/dist/src/interfaces/index.js.map +1 -0
- package/dist/src/interfaces/system-login.interface.d.ts +6 -0
- package/dist/src/interfaces/system-login.interface.js +3 -0
- package/dist/src/interfaces/system-login.interface.js.map +1 -0
- package/dist/src/interfaces/user-session.interface.d.ts +4 -0
- package/dist/src/interfaces/user-session.interface.js +3 -0
- package/dist/src/interfaces/user-session.interface.js.map +1 -0
- package/dist/src/models/authorization-code.entity.d.ts +14 -0
- package/dist/src/models/authorization-code.entity.js +86 -0
- package/dist/src/models/authorization-code.entity.js.map +1 -0
- package/dist/src/models/bearer-token.entity.d.ts +11 -0
- package/dist/src/models/bearer-token.entity.js +72 -0
- package/dist/src/models/bearer-token.entity.js.map +1 -0
- package/dist/src/models/building-type.entity.d.ts +7 -0
- package/dist/src/models/building-type.entity.js +50 -0
- package/dist/src/models/building-type.entity.js.map +1 -0
- package/dist/src/models/building.entity.d.ts +39 -0
- package/dist/src/models/building.entity.js +251 -0
- package/dist/src/models/building.entity.js.map +1 -0
- package/dist/src/models/city.entity.d.ts +11 -0
- package/dist/src/models/city.entity.js +72 -0
- package/dist/src/models/city.entity.js.map +1 -0
- package/dist/src/models/company.entity.d.ts +18 -0
- package/dist/src/models/company.entity.js +114 -0
- package/dist/src/models/company.entity.js.map +1 -0
- package/dist/src/models/country.entity.d.ts +13 -0
- package/dist/src/models/country.entity.js +76 -0
- package/dist/src/models/country.entity.js.map +1 -0
- package/dist/src/models/department.entity.d.ts +19 -0
- package/dist/src/models/department.entity.js +112 -0
- package/dist/src/models/department.entity.js.map +1 -0
- package/dist/src/models/group-role-privilege.entity.d.ts +17 -0
- package/dist/src/models/group-role-privilege.entity.js +90 -0
- package/dist/src/models/group-role-privilege.entity.js.map +1 -0
- package/dist/src/models/group-system-access.entity.d.ts +11 -0
- package/dist/src/models/group-system-access.entity.js +62 -0
- package/dist/src/models/group-system-access.entity.js.map +1 -0
- package/dist/src/models/group-system-privilege.entity.d.ts +11 -0
- package/dist/src/models/group-system-privilege.entity.js +62 -0
- package/dist/src/models/group-system-privilege.entity.js.map +1 -0
- package/dist/src/models/group-system-role.entity.d.ts +11 -0
- package/dist/src/models/group-system-role.entity.js +62 -0
- package/dist/src/models/group-system-role.entity.js.map +1 -0
- package/dist/src/models/login-history.entity.d.ts +12 -0
- package/dist/src/models/login-history.entity.js +70 -0
- package/dist/src/models/login-history.entity.js.map +1 -0
- package/dist/src/models/oauth-token.entity.d.ts +14 -0
- package/dist/src/models/oauth-token.entity.js +86 -0
- package/dist/src/models/oauth-token.entity.js.map +1 -0
- package/dist/src/models/role.entity.d.ts +17 -0
- package/dist/src/models/role.entity.js +102 -0
- package/dist/src/models/role.entity.js.map +1 -0
- package/dist/src/models/staff-type.entity.d.ts +7 -0
- package/dist/src/models/staff-type.entity.js +50 -0
- package/dist/src/models/staff-type.entity.js.map +1 -0
- package/dist/src/models/staff.entity.d.ts +39 -0
- package/dist/src/models/staff.entity.js +250 -0
- package/dist/src/models/staff.entity.js.map +1 -0
- package/dist/src/models/state.entity.d.ts +10 -0
- package/dist/src/models/state.entity.js +64 -0
- package/dist/src/models/state.entity.js.map +1 -0
- package/dist/src/models/system-accesss.entity.d.ts +6 -0
- package/dist/src/models/system-accesss.entity.js +51 -0
- package/dist/src/models/system-accesss.entity.js.map +1 -0
- package/dist/src/models/system-privilege.entity.d.ts +16 -0
- package/dist/src/models/system-privilege.entity.js +90 -0
- package/dist/src/models/system-privilege.entity.js.map +1 -0
- package/dist/src/models/system-role-privilege.entity.d.ts +11 -0
- package/dist/src/models/system-role-privilege.entity.js +60 -0
- package/dist/src/models/system-role-privilege.entity.js.map +1 -0
- package/dist/src/models/system-role.entity.d.ts +11 -0
- package/dist/src/models/system-role.entity.js +83 -0
- package/dist/src/models/system-role.entity.js.map +1 -0
- package/dist/src/models/system.entity.d.ts +19 -0
- package/dist/src/models/system.entity.js +146 -0
- package/dist/src/models/system.entity.js.map +1 -0
- package/dist/src/models/user-group.entity.d.ts +23 -0
- package/dist/src/models/user-group.entity.js +140 -0
- package/dist/src/models/user-group.entity.js.map +1 -0
- package/dist/src/models/user-role.entity.d.ts +12 -0
- package/dist/src/models/user-role.entity.js +73 -0
- package/dist/src/models/user-role.entity.js.map +1 -0
- package/dist/src/models/user-system-privileges.entity.d.ts +13 -0
- package/dist/src/models/user-system-privileges.entity.js +89 -0
- package/dist/src/models/user-system-privileges.entity.js.map +1 -0
- package/dist/src/models/user-system-role.entity.d.ts +11 -0
- package/dist/src/models/user-system-role.entity.js +60 -0
- package/dist/src/models/user-system-role.entity.js.map +1 -0
- package/dist/src/models/user-user-group.entity.d.ts +14 -0
- package/dist/src/models/user-user-group.entity.js +73 -0
- package/dist/src/models/user-user-group.entity.js.map +1 -0
- package/dist/src/models/user.entity.d.ts +40 -0
- package/dist/src/models/user.entity.js +191 -0
- package/dist/src/models/user.entity.js.map +1 -0
- package/dist/src/redis-client/__mocks__/jest-initial-setup.d.ts +1 -0
- package/dist/src/redis-client/__mocks__/jest-initial-setup.js +5 -0
- package/dist/src/redis-client/__mocks__/jest-initial-setup.js.map +1 -0
- package/dist/src/redis-client/__mocks__/redis-mock.d.ts +2 -0
- package/dist/src/redis-client/__mocks__/redis-mock.js +23 -0
- package/dist/src/redis-client/__mocks__/redis-mock.js.map +1 -0
- package/dist/src/redis-client/index.d.ts +1 -0
- package/dist/src/redis-client/index.js +18 -0
- package/dist/src/redis-client/index.js.map +1 -0
- package/dist/src/redis-client/redis.service.d.ts +7 -0
- package/dist/src/redis-client/redis.service.js +61 -0
- package/dist/src/redis-client/redis.service.js.map +1 -0
- package/dist/src/session/index.d.ts +2 -0
- package/dist/src/session/index.js +19 -0
- package/dist/src/session/index.js.map +1 -0
- package/dist/src/session/interfaces/index.d.ts +1 -0
- package/dist/src/session/interfaces/index.js +18 -0
- package/dist/src/session/interfaces/index.js.map +1 -0
- package/dist/src/session/interfaces/session-service.interface.d.ts +6 -0
- package/dist/src/session/interfaces/session-service.interface.js +3 -0
- package/dist/src/session/interfaces/session-service.interface.js.map +1 -0
- package/dist/src/session/session.service.d.ts +10 -0
- package/dist/src/session/session.service.js +63 -0
- package/dist/src/session/session.service.js.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -0
- package/package.json +2 -2
- package/src/components/login-user/interfaces/user-info.interface.ts +29 -29
- package/src/components/login-user/login-user.ts +749 -749
- package/src/enum/index.ts +1 -1
- package/src/enum/yn.enum.ts +4 -4
- package/src/models/user.entity.ts +160 -160
@@ -1,749 +1,749 @@
|
|
1
|
-
import { LoginUserBase } from '@tomei/general';
|
2
|
-
import { ISessionService } from '../../session/interfaces/session-service.interface';
|
3
|
-
import { IUserAttr } from './interfaces/user-info.interface';
|
4
|
-
import { UserRepository } from './user.repository';
|
5
|
-
import { SystemRepository } from '../system/system.repository';
|
6
|
-
import { SystemAccessRepository } from '../system-access/system-access.repository';
|
7
|
-
import { LoginHistoryRepository } from '../login-history/login-history.repository';
|
8
|
-
import { UserUserGroupRepository } from '../user-user-group/user-user-group.repository';
|
9
|
-
import { PasswordHashService } from '../password-hash/password-hash.service';
|
10
|
-
import { UserGroupRepository } from '../user-group/user-group.repository';
|
11
|
-
import { SMTPMailer } from '@tomei/mailer';
|
12
|
-
import { ISystemLogin } from '../../../src/interfaces/system-login.interface';
|
13
|
-
import Staff from '../../models/staff.entity';
|
14
|
-
import SystemPrivilege from '../../models/system-privilege.entity';
|
15
|
-
import LoginHistory from '../../models/login-history.entity';
|
16
|
-
import GroupSystemPrivilege from '../../models/group-system-privilege.entity';
|
17
|
-
import GroupRolePrivilege from '../../models/group-role-privilege.entity';
|
18
|
-
import UserGroup from '../../models/user-group.entity';
|
19
|
-
import { YN } from '../../enum/yn.enum';
|
20
|
-
|
21
|
-
export class LoginUser extends LoginUserBase {
|
22
|
-
ObjectId: string;
|
23
|
-
Email: string;
|
24
|
-
private _Password: string;
|
25
|
-
private _Status: string;
|
26
|
-
private _DefaultPasswordChangedYN: YN;
|
27
|
-
private _FirstLoginAt: Date;
|
28
|
-
private _LastLoginAt: Date;
|
29
|
-
private _MFAEnabled: number;
|
30
|
-
private _MFAConfig: string;
|
31
|
-
private _RecoveryEmail: string;
|
32
|
-
private _FailedLoginAttemptCount: number;
|
33
|
-
private _LastFailedLoginAt: Date;
|
34
|
-
private _LastPasswordChangedAt: Date;
|
35
|
-
private _NeedToChangePasswordYN: YN;
|
36
|
-
private _CreatedById: number;
|
37
|
-
private _CreatedAt: Date;
|
38
|
-
private _UpdatedById: number;
|
39
|
-
private _UpdatedAt: Date;
|
40
|
-
ObjectName = 'User';
|
41
|
-
TableName = 'sso_Users';
|
42
|
-
ObjectType = 'User';
|
43
|
-
staffs: any;
|
44
|
-
|
45
|
-
private _OriginIP: string;
|
46
|
-
private _SessionService: ISessionService;
|
47
|
-
private _PasswordHashService = new PasswordHashService();
|
48
|
-
private static _Repository = new UserRepository();
|
49
|
-
private static _SystemRepository = new SystemRepository();
|
50
|
-
private static _SystemAccessRepository = new SystemAccessRepository();
|
51
|
-
private static _LoginHistoryRepository = new LoginHistoryRepository();
|
52
|
-
private static _UserUserGroupRepository = new UserUserGroupRepository();
|
53
|
-
private static _UserGroupRepository = new UserGroupRepository();
|
54
|
-
private _dbTransaction: any;
|
55
|
-
|
56
|
-
get UserId(): number {
|
57
|
-
return parseInt(this.ObjectId);
|
58
|
-
}
|
59
|
-
|
60
|
-
private set UserId(value: number) {
|
61
|
-
this.ObjectId = value.toString();
|
62
|
-
}
|
63
|
-
|
64
|
-
get Password(): string {
|
65
|
-
return this._Password;
|
66
|
-
}
|
67
|
-
|
68
|
-
private set Password(value: string) {
|
69
|
-
this._Password = value;
|
70
|
-
}
|
71
|
-
|
72
|
-
get Status(): string {
|
73
|
-
return this._Status;
|
74
|
-
}
|
75
|
-
|
76
|
-
private set Status(value: string) {
|
77
|
-
this._Status = value;
|
78
|
-
}
|
79
|
-
|
80
|
-
get DefaultPasswordChangedYN(): YN {
|
81
|
-
return this._DefaultPasswordChangedYN;
|
82
|
-
}
|
83
|
-
|
84
|
-
private set DefaultPasswordChangedYN(value: YN) {
|
85
|
-
this._DefaultPasswordChangedYN = value;
|
86
|
-
}
|
87
|
-
|
88
|
-
get FirstLoginAt(): Date {
|
89
|
-
return this._FirstLoginAt;
|
90
|
-
}
|
91
|
-
|
92
|
-
private set FirstLoginAt(value: Date) {
|
93
|
-
this._FirstLoginAt = value;
|
94
|
-
}
|
95
|
-
|
96
|
-
get LastLoginAt(): Date {
|
97
|
-
return this._LastLoginAt;
|
98
|
-
}
|
99
|
-
|
100
|
-
private set LastLoginAt(value: Date) {
|
101
|
-
this._LastLoginAt = value;
|
102
|
-
}
|
103
|
-
|
104
|
-
get MFAEnabled(): number {
|
105
|
-
return this._MFAEnabled;
|
106
|
-
}
|
107
|
-
|
108
|
-
private set MFAEnabled(value: number) {
|
109
|
-
this._MFAEnabled = value;
|
110
|
-
}
|
111
|
-
|
112
|
-
get MFAConfig(): string {
|
113
|
-
return this._MFAConfig;
|
114
|
-
}
|
115
|
-
|
116
|
-
private set MFAConfig(value: string) {
|
117
|
-
this._MFAConfig = value;
|
118
|
-
}
|
119
|
-
|
120
|
-
get RecoveryEmail(): string {
|
121
|
-
return this._RecoveryEmail;
|
122
|
-
}
|
123
|
-
|
124
|
-
private set RecoveryEmail(value: string) {
|
125
|
-
this._RecoveryEmail = value;
|
126
|
-
}
|
127
|
-
|
128
|
-
get FailedLoginAttemptCount(): number {
|
129
|
-
return this._FailedLoginAttemptCount;
|
130
|
-
}
|
131
|
-
|
132
|
-
private set FailedLoginAttemptCount(value: number) {
|
133
|
-
this._FailedLoginAttemptCount = value;
|
134
|
-
}
|
135
|
-
|
136
|
-
get LastFailedLoginAt(): Date {
|
137
|
-
return this._LastFailedLoginAt;
|
138
|
-
}
|
139
|
-
|
140
|
-
private set LastFailedLoginAt(value: Date) {
|
141
|
-
this._LastFailedLoginAt = value;
|
142
|
-
}
|
143
|
-
|
144
|
-
get LastPasswordChangedAt(): Date {
|
145
|
-
return this._LastPasswordChangedAt;
|
146
|
-
}
|
147
|
-
|
148
|
-
private set LastPasswordChangedAt(value: Date) {
|
149
|
-
this._LastPasswordChangedAt = value;
|
150
|
-
}
|
151
|
-
|
152
|
-
get NeedToChangePasswordYN(): YN {
|
153
|
-
return this._NeedToChangePasswordYN;
|
154
|
-
}
|
155
|
-
|
156
|
-
private set NeedToChangePasswordYN(value: YN) {
|
157
|
-
this._NeedToChangePasswordYN = value;
|
158
|
-
}
|
159
|
-
|
160
|
-
get CreatedById(): number {
|
161
|
-
return this._CreatedById;
|
162
|
-
}
|
163
|
-
|
164
|
-
private set CreatedById(value: number) {
|
165
|
-
this._CreatedById = value;
|
166
|
-
}
|
167
|
-
|
168
|
-
get CreatedAt(): Date {
|
169
|
-
return this._CreatedAt;
|
170
|
-
}
|
171
|
-
|
172
|
-
private set CreatedAt(value: Date) {
|
173
|
-
this._CreatedAt = value;
|
174
|
-
}
|
175
|
-
|
176
|
-
get UpdatedById(): number {
|
177
|
-
return this._UpdatedById;
|
178
|
-
}
|
179
|
-
|
180
|
-
private set UpdatedById(value: number) {
|
181
|
-
this._UpdatedById = value;
|
182
|
-
}
|
183
|
-
|
184
|
-
get UpdatedAt(): Date {
|
185
|
-
return this._UpdatedAt;
|
186
|
-
}
|
187
|
-
|
188
|
-
private set UpdatedAt(value: Date) {
|
189
|
-
this._UpdatedAt = value;
|
190
|
-
}
|
191
|
-
|
192
|
-
async getDetails(): Promise<{
|
193
|
-
FullName: string;
|
194
|
-
IDNo: string;
|
195
|
-
IDType: string;
|
196
|
-
Email: string;
|
197
|
-
ContactNo: string;
|
198
|
-
}> {
|
199
|
-
return {
|
200
|
-
FullName: this.FullName,
|
201
|
-
IDNo: this.IDNo,
|
202
|
-
IDType: this.IDType,
|
203
|
-
Email: this.Email,
|
204
|
-
ContactNo: this.ContactNo,
|
205
|
-
};
|
206
|
-
}
|
207
|
-
|
208
|
-
private constructor(
|
209
|
-
sessionService: ISessionService,
|
210
|
-
dbTransaction?: any,
|
211
|
-
userInfo?: IUserAttr,
|
212
|
-
) {
|
213
|
-
super();
|
214
|
-
this._SessionService = sessionService;
|
215
|
-
|
216
|
-
if (dbTransaction) {
|
217
|
-
this._dbTransaction = dbTransaction;
|
218
|
-
}
|
219
|
-
// set all the class properties
|
220
|
-
if (userInfo) {
|
221
|
-
this.UserId = userInfo.UserId;
|
222
|
-
this.FullName = userInfo.FullName;
|
223
|
-
this.IDNo = userInfo.IDNo;
|
224
|
-
this.Email = userInfo.Email;
|
225
|
-
this.ContactNo = userInfo.ContactNo;
|
226
|
-
this.Password = userInfo.Password;
|
227
|
-
this.staffs = userInfo.staffs;
|
228
|
-
}
|
229
|
-
}
|
230
|
-
|
231
|
-
static async init(
|
232
|
-
sessionService: ISessionService,
|
233
|
-
userId?: number,
|
234
|
-
dbTransaction = null,
|
235
|
-
): Promise<LoginUser> {
|
236
|
-
if (userId) {
|
237
|
-
if (dbTransaction) {
|
238
|
-
LoginUser._Repository = new UserRepository();
|
239
|
-
}
|
240
|
-
const user = await LoginUser._Repository.findOne({
|
241
|
-
where: {
|
242
|
-
UserId: userId,
|
243
|
-
},
|
244
|
-
include: [
|
245
|
-
{
|
246
|
-
model: Staff,
|
247
|
-
},
|
248
|
-
],
|
249
|
-
});
|
250
|
-
|
251
|
-
if (!user) {
|
252
|
-
throw new Error('Invalid credentials.');
|
253
|
-
}
|
254
|
-
|
255
|
-
if (user) {
|
256
|
-
const userAttr: IUserAttr = {
|
257
|
-
UserId: user.UserId,
|
258
|
-
FullName: user.Staff.FullName,
|
259
|
-
IDNo: user.Staff.IdNo,
|
260
|
-
ContactNo: user.Staff.Mobile,
|
261
|
-
Email: user.Email,
|
262
|
-
Password: user.Password,
|
263
|
-
Status: user.Status,
|
264
|
-
DefaultPasswordChangedYN: user.DefaultPasswordChangedYN,
|
265
|
-
FirstLoginAt: user.FirstLoginAt,
|
266
|
-
LastLoginAt: user.LastLoginAt,
|
267
|
-
MFAEnabled: user.MFAEnabled,
|
268
|
-
MFAConfig: user.MFAConfig,
|
269
|
-
RecoveryEmail: user.RecoveryEmail,
|
270
|
-
FailedLoginAttemptCount: user.FailedLoginAttemptCount,
|
271
|
-
LastFailedLoginAt: user.LastFailedLoginAt,
|
272
|
-
LastPasswordChangedAt: user.LastPasswordChangedAt,
|
273
|
-
NeedToChangePasswordYN: user.NeedToChangePasswordYN,
|
274
|
-
CreatedById: user.CreatedById,
|
275
|
-
CreatedAt: user.CreatedAt,
|
276
|
-
UpdatedById: user.UpdatedById,
|
277
|
-
UpdatedAt: user.UpdatedAt,
|
278
|
-
staffs: user.Staff,
|
279
|
-
};
|
280
|
-
|
281
|
-
return new LoginUser(sessionService, dbTransaction, userAttr);
|
282
|
-
} else {
|
283
|
-
throw new Error('User not found');
|
284
|
-
}
|
285
|
-
}
|
286
|
-
return new LoginUser(sessionService, dbTransaction);
|
287
|
-
}
|
288
|
-
|
289
|
-
async login(
|
290
|
-
systemCode: string,
|
291
|
-
email: string,
|
292
|
-
password: string,
|
293
|
-
ipAddress: string,
|
294
|
-
): Promise<string> {
|
295
|
-
try {
|
296
|
-
//validate email
|
297
|
-
if (!this.ObjectId) {
|
298
|
-
const user = await LoginUser._Repository.findOne({
|
299
|
-
where: {
|
300
|
-
Email: email,
|
301
|
-
},
|
302
|
-
include: [
|
303
|
-
{
|
304
|
-
model: Staff,
|
305
|
-
},
|
306
|
-
],
|
307
|
-
});
|
308
|
-
|
309
|
-
const userAttr: IUserAttr = {
|
310
|
-
UserId: user.UserId,
|
311
|
-
FullName: user.Staff.FullName,
|
312
|
-
IDNo: user.Staff.IdNo,
|
313
|
-
ContactNo: user.Staff.Mobile,
|
314
|
-
Email: user.Email,
|
315
|
-
Password: user.Password,
|
316
|
-
Status: user.Status,
|
317
|
-
DefaultPasswordChangedYN: user.DefaultPasswordChangedYN,
|
318
|
-
FirstLoginAt: user.FirstLoginAt,
|
319
|
-
LastLoginAt: user.LastLoginAt,
|
320
|
-
MFAEnabled: user.MFAEnabled,
|
321
|
-
MFAConfig: user.MFAConfig,
|
322
|
-
RecoveryEmail: user.RecoveryEmail,
|
323
|
-
FailedLoginAttemptCount: user.FailedLoginAttemptCount,
|
324
|
-
LastFailedLoginAt: user.LastFailedLoginAt,
|
325
|
-
LastPasswordChangedAt: user.LastPasswordChangedAt,
|
326
|
-
NeedToChangePasswordYN: user.NeedToChangePasswordYN,
|
327
|
-
CreatedById: user.CreatedById,
|
328
|
-
CreatedAt: user.CreatedAt,
|
329
|
-
UpdatedById: user.UpdatedById,
|
330
|
-
UpdatedAt: user.UpdatedAt,
|
331
|
-
staffs: user.Staff,
|
332
|
-
};
|
333
|
-
|
334
|
-
this.UserId = userAttr.UserId;
|
335
|
-
this.FullName = userAttr.FullName;
|
336
|
-
this.IDNo = userAttr.IDNo;
|
337
|
-
this.Email = userAttr.Email;
|
338
|
-
this.ContactNo = userAttr.ContactNo;
|
339
|
-
this.Password = userAttr.Password;
|
340
|
-
this.Status = userAttr.Status;
|
341
|
-
this.DefaultPasswordChangedYN = userAttr.DefaultPasswordChangedYN;
|
342
|
-
this.FirstLoginAt = userAttr.FirstLoginAt;
|
343
|
-
this.LastLoginAt = userAttr.LastLoginAt;
|
344
|
-
this.MFAEnabled = userAttr.MFAEnabled;
|
345
|
-
this.MFAConfig = userAttr.MFAConfig;
|
346
|
-
this.RecoveryEmail = userAttr.RecoveryEmail;
|
347
|
-
this.FailedLoginAttemptCount = userAttr.FailedLoginAttemptCount;
|
348
|
-
this.LastFailedLoginAt = userAttr.LastFailedLoginAt;
|
349
|
-
this.LastPasswordChangedAt = userAttr.LastPasswordChangedAt;
|
350
|
-
this.NeedToChangePasswordYN = userAttr.NeedToChangePasswordYN;
|
351
|
-
this.CreatedById = userAttr.CreatedById;
|
352
|
-
this.CreatedAt = userAttr.CreatedAt;
|
353
|
-
this.UpdatedById = userAttr.UpdatedById;
|
354
|
-
this.UpdatedAt = userAttr.UpdatedAt;
|
355
|
-
this.staffs = userAttr.staffs;
|
356
|
-
}
|
357
|
-
|
358
|
-
if (this.ObjectId && this.Email !== email) {
|
359
|
-
throw new Error('Invalid credentials.');
|
360
|
-
}
|
361
|
-
|
362
|
-
//validate password
|
363
|
-
const isPasswordValid = await this._PasswordHashService.verify(
|
364
|
-
password,
|
365
|
-
this.Password,
|
366
|
-
);
|
367
|
-
|
368
|
-
if (!isPasswordValid) {
|
369
|
-
throw new Error('Invalid credentials.');
|
370
|
-
}
|
371
|
-
|
372
|
-
//validate system code
|
373
|
-
const system = await LoginUser._SystemRepository.findOne({
|
374
|
-
where: {
|
375
|
-
code: systemCode,
|
376
|
-
},
|
377
|
-
});
|
378
|
-
|
379
|
-
if (!system) {
|
380
|
-
throw new Error('Invalid system code.');
|
381
|
-
}
|
382
|
-
|
383
|
-
//validate system access
|
384
|
-
await this.checkSystemAccess(this.UserId, system.id);
|
385
|
-
// alert user if new login
|
386
|
-
await this.alertNewLogin(this.ObjectId, system.id.toString(), ipAddress);
|
387
|
-
|
388
|
-
// fetch user session if exists
|
389
|
-
const userSession = await this._SessionService.retrieveUserSession(
|
390
|
-
this.ObjectId,
|
391
|
-
);
|
392
|
-
let systemLogin = userSession.systemLogins.find(
|
393
|
-
(system) => system.code === systemCode,
|
394
|
-
);
|
395
|
-
|
396
|
-
// generate new session id
|
397
|
-
const { randomUUID } = require('crypto');
|
398
|
-
const sessionId = randomUUID();
|
399
|
-
|
400
|
-
if (systemLogin) {
|
401
|
-
systemLogin = systemLogin.sessionId = sessionId;
|
402
|
-
userSession.systemLogins.map((system) =>
|
403
|
-
system.code === systemCode ? systemLogin : system,
|
404
|
-
);
|
405
|
-
} else {
|
406
|
-
// if not, add new system login into the userSession
|
407
|
-
const newLogin = {
|
408
|
-
id: system.id.toString(),
|
409
|
-
code: system.Code,
|
410
|
-
sessionId: sessionId,
|
411
|
-
privileges: await this.getPrivileges(system.Code),
|
412
|
-
};
|
413
|
-
userSession.systemLogins.push(newLogin);
|
414
|
-
}
|
415
|
-
// then update userSession inside the redis storage with 1 day duration of time-to-live
|
416
|
-
this._SessionService.setUserSession(this.ObjectId, userSession);
|
417
|
-
|
418
|
-
// record new login history
|
419
|
-
await LoginUser._LoginHistoryRepository.create({
|
420
|
-
UserId: this.UserId,
|
421
|
-
SystemId: system.id,
|
422
|
-
OriginIp: ipAddress,
|
423
|
-
CreatedAt: new Date(),
|
424
|
-
});
|
425
|
-
|
426
|
-
return `${this.UserId}:${sessionId}`;
|
427
|
-
} catch (error) {
|
428
|
-
throw error;
|
429
|
-
}
|
430
|
-
}
|
431
|
-
|
432
|
-
private async checkSystemAccess(
|
433
|
-
userId: number,
|
434
|
-
systemId: number,
|
435
|
-
): Promise<void> {
|
436
|
-
try {
|
437
|
-
const systemAccess = await LoginUser._SystemAccessRepository.findOne({
|
438
|
-
where: {
|
439
|
-
UserId: userId,
|
440
|
-
SystemId: systemId,
|
441
|
-
},
|
442
|
-
});
|
443
|
-
|
444
|
-
if (!systemAccess) {
|
445
|
-
throw new Error("User don't have access to the system.");
|
446
|
-
}
|
447
|
-
} catch (error) {
|
448
|
-
throw error;
|
449
|
-
}
|
450
|
-
}
|
451
|
-
|
452
|
-
private async alertNewLogin(
|
453
|
-
userId: string,
|
454
|
-
systemId: string,
|
455
|
-
ipAddress: string,
|
456
|
-
) {
|
457
|
-
try {
|
458
|
-
const userLogins = await LoginUser._LoginHistoryRepository.findAll({
|
459
|
-
where: {
|
460
|
-
UserId: userId,
|
461
|
-
SystemId: systemId,
|
462
|
-
},
|
463
|
-
});
|
464
|
-
|
465
|
-
const gotPreviousLogins = userLogins?.length !== 0;
|
466
|
-
let ipFound: LoginHistory | undefined = undefined;
|
467
|
-
if (gotPreviousLogins) {
|
468
|
-
ipFound = userLogins.find((item) => item.OriginIp === ipAddress);
|
469
|
-
}
|
470
|
-
|
471
|
-
if (gotPreviousLogins && !ipFound) {
|
472
|
-
const EMAIL_SENDER =
|
473
|
-
process.env.EMAIL_SENDER || 'itd-system@tomei.com.my';
|
474
|
-
const transporter = new SMTPMailer();
|
475
|
-
|
476
|
-
await transporter.sendMail({
|
477
|
-
from: EMAIL_SENDER,
|
478
|
-
to: this.Email,
|
479
|
-
subject: 'New Login Alert',
|
480
|
-
html: `<p>Dear ${this.FullName},</p>
|
481
|
-
<p>There was a new login to your account from ${ipAddress} on ${new Date().toLocaleString()}.</p>
|
482
|
-
<p>If this was you, you can safely ignore this email.</p>
|
483
|
-
<p>If you suspect that someone else is trying to access your account, please contact us immediately at itd-support@tomei.com.my.</p>
|
484
|
-
<p>Thank you!,</p>
|
485
|
-
<p>
|
486
|
-
Best Regards,
|
487
|
-
IT Department
|
488
|
-
</p>`,
|
489
|
-
});
|
490
|
-
}
|
491
|
-
} catch (error) {
|
492
|
-
throw error;
|
493
|
-
}
|
494
|
-
}
|
495
|
-
|
496
|
-
private async getPrivileges(systemCode: string): Promise<string[]> {
|
497
|
-
try {
|
498
|
-
const system = await LoginUser._SystemRepository.findOne({
|
499
|
-
where: {
|
500
|
-
Code: systemCode,
|
501
|
-
},
|
502
|
-
});
|
503
|
-
|
504
|
-
if (!system) {
|
505
|
-
throw new Error('Invalid system code.');
|
506
|
-
}
|
507
|
-
|
508
|
-
// retrive user userGroups with system privileges
|
509
|
-
const userUserGroups = await this.getUserUserGroupFromDB(system.id);
|
510
|
-
|
511
|
-
// get all userGroup data from user userGroups
|
512
|
-
const userGroupData = userUserGroups.map((u) => u.UserGroup);
|
513
|
-
// get all privileges from userGroup data
|
514
|
-
let privileges: string[] = [];
|
515
|
-
for (const userGroup of userGroupData) {
|
516
|
-
const groupSystemPrivileges = userGroup.GroupSystemPrivileges.map(
|
517
|
-
(g) => g.SystemPrivilege.Code,
|
518
|
-
);
|
519
|
-
const groupRolePrivileges = userGroup.GroupRolePrivileges.map(
|
520
|
-
(g) => g.SystemPrivilege.Code,
|
521
|
-
);
|
522
|
-
|
523
|
-
// if userGroup is not root, get all parent tree privileges
|
524
|
-
if (
|
525
|
-
userGroup.GroupLevel !== 0 &&
|
526
|
-
userGroup.AllowInheritFromParentYN === 'Y'
|
527
|
-
) {
|
528
|
-
// get all parent tree privileges
|
529
|
-
const parentTreePrivileges = await this.getPrivilegesFromUserGroup(
|
530
|
-
userGroup.ParentGroupCode,
|
531
|
-
);
|
532
|
-
|
533
|
-
privileges = [...privileges, ...parentTreePrivileges];
|
534
|
-
}
|
535
|
-
|
536
|
-
privileges = [
|
537
|
-
...privileges,
|
538
|
-
...groupSystemPrivileges,
|
539
|
-
...groupRolePrivileges,
|
540
|
-
];
|
541
|
-
}
|
542
|
-
|
543
|
-
// retrive all user personal privileges
|
544
|
-
const userPrivileges = await this.getUserPersonalPrivileges(system.id);
|
545
|
-
|
546
|
-
privileges = [...privileges, ...userPrivileges];
|
547
|
-
privileges = [...new Set(privileges)];
|
548
|
-
return privileges;
|
549
|
-
} catch (error) {
|
550
|
-
throw error;
|
551
|
-
}
|
552
|
-
}
|
553
|
-
|
554
|
-
private async getPrivilegesFromUserGroup(
|
555
|
-
groupCode: string,
|
556
|
-
): Promise<string[]> {
|
557
|
-
try {
|
558
|
-
// Retrieve userGroup from the database based on groupCode
|
559
|
-
const userGroup = await this.getUserGroupFromDB(groupCode);
|
560
|
-
let privileges: string[] = [];
|
561
|
-
|
562
|
-
// Add privileges from the userGroup to the privileges array
|
563
|
-
privileges = [
|
564
|
-
...privileges,
|
565
|
-
...userGroup.GroupSystemPrivileges.map((g) => g.SystemPrivilege.Code),
|
566
|
-
...userGroup.GroupRolePrivileges.map((g) => g.SystemPrivilege.Code),
|
567
|
-
];
|
568
|
-
|
569
|
-
// Recursive call if conditions are not met and ParentGroupCode exists
|
570
|
-
const isContinue =
|
571
|
-
userGroup.GroupLevel !== 0 &&
|
572
|
-
userGroup.AllowInheritFromParentYN === 'Y';
|
573
|
-
if (isContinue) {
|
574
|
-
const recursivePrivileges = await this.getPrivilegesFromUserGroup(
|
575
|
-
userGroup.ParentGroupCode,
|
576
|
-
);
|
577
|
-
privileges = privileges.concat(recursivePrivileges);
|
578
|
-
}
|
579
|
-
|
580
|
-
// return privileges array
|
581
|
-
return privileges;
|
582
|
-
} catch (error) {
|
583
|
-
throw error;
|
584
|
-
}
|
585
|
-
}
|
586
|
-
|
587
|
-
private async getUserGroupFromDB(groupCode: string): Promise<any> {
|
588
|
-
try {
|
589
|
-
const userGroup = await LoginUser._UserGroupRepository.findOne({
|
590
|
-
where: {
|
591
|
-
GroupCode: groupCode,
|
592
|
-
},
|
593
|
-
include: [
|
594
|
-
{
|
595
|
-
model: GroupSystemPrivilege,
|
596
|
-
include: {
|
597
|
-
model: SystemPrivilege,
|
598
|
-
},
|
599
|
-
},
|
600
|
-
{
|
601
|
-
model: GroupRolePrivilege,
|
602
|
-
include: {
|
603
|
-
model: SystemPrivilege,
|
604
|
-
},
|
605
|
-
},
|
606
|
-
],
|
607
|
-
});
|
608
|
-
return userGroup;
|
609
|
-
} catch (error) {
|
610
|
-
throw error;
|
611
|
-
}
|
612
|
-
}
|
613
|
-
|
614
|
-
private async getUserUserGroupFromDB(systemCode: number) {
|
615
|
-
try {
|
616
|
-
return await LoginUser._UserUserGroupRepository.findAll({
|
617
|
-
where: {
|
618
|
-
UserId: this.UserId,
|
619
|
-
SystemId: systemCode,
|
620
|
-
},
|
621
|
-
include: {
|
622
|
-
model: UserGroup,
|
623
|
-
include: [
|
624
|
-
{
|
625
|
-
model: GroupSystemPrivilege,
|
626
|
-
include: {
|
627
|
-
model: SystemPrivilege,
|
628
|
-
},
|
629
|
-
},
|
630
|
-
{
|
631
|
-
model: GroupRolePrivilege,
|
632
|
-
include: {
|
633
|
-
model: SystemPrivilege,
|
634
|
-
},
|
635
|
-
},
|
636
|
-
],
|
637
|
-
},
|
638
|
-
});
|
639
|
-
} catch (error) {
|
640
|
-
throw error;
|
641
|
-
}
|
642
|
-
}
|
643
|
-
|
644
|
-
private async getUserPersonalPrivileges(systemId: number): Promise<string[]> {
|
645
|
-
try {
|
646
|
-
const userRole = await LoginUser._Repository.findOne({
|
647
|
-
where: {
|
648
|
-
UserId: this.ObjectId,
|
649
|
-
},
|
650
|
-
include: {
|
651
|
-
model: SystemPrivilege,
|
652
|
-
},
|
653
|
-
});
|
654
|
-
|
655
|
-
//retrive all user systemPrevileges data from user roles
|
656
|
-
let userSystemPrivileges = userRole.SystemPrivileges;
|
657
|
-
|
658
|
-
userSystemPrivileges = userSystemPrivileges.filter(
|
659
|
-
(u) => u.SystemId === systemId,
|
660
|
-
);
|
661
|
-
|
662
|
-
const userPrivileges: string[] = userSystemPrivileges.map((u) => u.Code);
|
663
|
-
return userPrivileges;
|
664
|
-
} catch (error) {
|
665
|
-
throw error;
|
666
|
-
}
|
667
|
-
}
|
668
|
-
|
669
|
-
async checkPrivileges(
|
670
|
-
systemCode: string,
|
671
|
-
privilegeName: string,
|
672
|
-
): Promise<boolean> {
|
673
|
-
try {
|
674
|
-
if (!this.ObjectId) {
|
675
|
-
throw new Error('ObjectId(UserId) is not set');
|
676
|
-
}
|
677
|
-
|
678
|
-
const userSession = await this._SessionService.retrieveUserSession(
|
679
|
-
this.ObjectId,
|
680
|
-
);
|
681
|
-
|
682
|
-
const systemLogin = userSession.systemLogins.find(
|
683
|
-
(system) => system.code === systemCode,
|
684
|
-
);
|
685
|
-
|
686
|
-
if (!systemLogin) {
|
687
|
-
return false;
|
688
|
-
}
|
689
|
-
|
690
|
-
const privileges = systemLogin.privileges;
|
691
|
-
const hasPrivilege = privileges.includes(privilegeName);
|
692
|
-
return hasPrivilege;
|
693
|
-
} catch (error) {
|
694
|
-
throw error;
|
695
|
-
}
|
696
|
-
}
|
697
|
-
|
698
|
-
async checkSession(
|
699
|
-
systemCode: string,
|
700
|
-
sessionId: string,
|
701
|
-
userId: string,
|
702
|
-
): Promise<ISystemLogin> {
|
703
|
-
try {
|
704
|
-
const userSession = await this._SessionService.retrieveUserSession(
|
705
|
-
userId,
|
706
|
-
);
|
707
|
-
|
708
|
-
if (userSession.systemLogins.length === 0) {
|
709
|
-
throw new Error('Session expired.');
|
710
|
-
}
|
711
|
-
|
712
|
-
const systemLogin = userSession.systemLogins.find(
|
713
|
-
(sl) => sl.code === systemCode,
|
714
|
-
);
|
715
|
-
|
716
|
-
if (!systemLogin) {
|
717
|
-
throw new Error('Session expired.');
|
718
|
-
}
|
719
|
-
|
720
|
-
if (systemLogin.sessionId !== sessionId) {
|
721
|
-
throw new Error('Session expired.');
|
722
|
-
}
|
723
|
-
|
724
|
-
await this._SessionService.refreshDuration(userId);
|
725
|
-
|
726
|
-
return systemLogin;
|
727
|
-
} catch (error) {
|
728
|
-
throw error;
|
729
|
-
}
|
730
|
-
}
|
731
|
-
|
732
|
-
async logout(systemCode: string) {
|
733
|
-
try {
|
734
|
-
if (!this.ObjectId) {
|
735
|
-
throw new Error('ObjectId(UserId) is not set');
|
736
|
-
}
|
737
|
-
const userSession = await this._SessionService.retrieveUserSession(
|
738
|
-
this.ObjectId,
|
739
|
-
);
|
740
|
-
const index = userSession.systemLogins.findIndex(
|
741
|
-
(system) => system.code === systemCode,
|
742
|
-
);
|
743
|
-
userSession.systemLogins.splice(index, 1);
|
744
|
-
this._SessionService.setUserSession(this.ObjectId, userSession);
|
745
|
-
} catch (error) {
|
746
|
-
throw error;
|
747
|
-
}
|
748
|
-
}
|
749
|
-
}
|
1
|
+
import { LoginUserBase } from '@tomei/general';
|
2
|
+
import { ISessionService } from '../../session/interfaces/session-service.interface';
|
3
|
+
import { IUserAttr } from './interfaces/user-info.interface';
|
4
|
+
import { UserRepository } from './user.repository';
|
5
|
+
import { SystemRepository } from '../system/system.repository';
|
6
|
+
import { SystemAccessRepository } from '../system-access/system-access.repository';
|
7
|
+
import { LoginHistoryRepository } from '../login-history/login-history.repository';
|
8
|
+
import { UserUserGroupRepository } from '../user-user-group/user-user-group.repository';
|
9
|
+
import { PasswordHashService } from '../password-hash/password-hash.service';
|
10
|
+
import { UserGroupRepository } from '../user-group/user-group.repository';
|
11
|
+
import { SMTPMailer } from '@tomei/mailer';
|
12
|
+
import { ISystemLogin } from '../../../src/interfaces/system-login.interface';
|
13
|
+
import Staff from '../../models/staff.entity';
|
14
|
+
import SystemPrivilege from '../../models/system-privilege.entity';
|
15
|
+
import LoginHistory from '../../models/login-history.entity';
|
16
|
+
import GroupSystemPrivilege from '../../models/group-system-privilege.entity';
|
17
|
+
import GroupRolePrivilege from '../../models/group-role-privilege.entity';
|
18
|
+
import UserGroup from '../../models/user-group.entity';
|
19
|
+
import { YN } from '../../enum/yn.enum';
|
20
|
+
|
21
|
+
export class LoginUser extends LoginUserBase {
|
22
|
+
ObjectId: string;
|
23
|
+
Email: string;
|
24
|
+
private _Password: string;
|
25
|
+
private _Status: string;
|
26
|
+
private _DefaultPasswordChangedYN: YN;
|
27
|
+
private _FirstLoginAt: Date;
|
28
|
+
private _LastLoginAt: Date;
|
29
|
+
private _MFAEnabled: number;
|
30
|
+
private _MFAConfig: string;
|
31
|
+
private _RecoveryEmail: string;
|
32
|
+
private _FailedLoginAttemptCount: number;
|
33
|
+
private _LastFailedLoginAt: Date;
|
34
|
+
private _LastPasswordChangedAt: Date;
|
35
|
+
private _NeedToChangePasswordYN: YN;
|
36
|
+
private _CreatedById: number;
|
37
|
+
private _CreatedAt: Date;
|
38
|
+
private _UpdatedById: number;
|
39
|
+
private _UpdatedAt: Date;
|
40
|
+
ObjectName = 'User';
|
41
|
+
TableName = 'sso_Users';
|
42
|
+
ObjectType = 'User';
|
43
|
+
staffs: any;
|
44
|
+
|
45
|
+
private _OriginIP: string;
|
46
|
+
private _SessionService: ISessionService;
|
47
|
+
private _PasswordHashService = new PasswordHashService();
|
48
|
+
private static _Repository = new UserRepository();
|
49
|
+
private static _SystemRepository = new SystemRepository();
|
50
|
+
private static _SystemAccessRepository = new SystemAccessRepository();
|
51
|
+
private static _LoginHistoryRepository = new LoginHistoryRepository();
|
52
|
+
private static _UserUserGroupRepository = new UserUserGroupRepository();
|
53
|
+
private static _UserGroupRepository = new UserGroupRepository();
|
54
|
+
private _dbTransaction: any;
|
55
|
+
|
56
|
+
get UserId(): number {
|
57
|
+
return parseInt(this.ObjectId);
|
58
|
+
}
|
59
|
+
|
60
|
+
private set UserId(value: number) {
|
61
|
+
this.ObjectId = value.toString();
|
62
|
+
}
|
63
|
+
|
64
|
+
get Password(): string {
|
65
|
+
return this._Password;
|
66
|
+
}
|
67
|
+
|
68
|
+
private set Password(value: string) {
|
69
|
+
this._Password = value;
|
70
|
+
}
|
71
|
+
|
72
|
+
get Status(): string {
|
73
|
+
return this._Status;
|
74
|
+
}
|
75
|
+
|
76
|
+
private set Status(value: string) {
|
77
|
+
this._Status = value;
|
78
|
+
}
|
79
|
+
|
80
|
+
get DefaultPasswordChangedYN(): YN {
|
81
|
+
return this._DefaultPasswordChangedYN;
|
82
|
+
}
|
83
|
+
|
84
|
+
private set DefaultPasswordChangedYN(value: YN) {
|
85
|
+
this._DefaultPasswordChangedYN = value;
|
86
|
+
}
|
87
|
+
|
88
|
+
get FirstLoginAt(): Date {
|
89
|
+
return this._FirstLoginAt;
|
90
|
+
}
|
91
|
+
|
92
|
+
private set FirstLoginAt(value: Date) {
|
93
|
+
this._FirstLoginAt = value;
|
94
|
+
}
|
95
|
+
|
96
|
+
get LastLoginAt(): Date {
|
97
|
+
return this._LastLoginAt;
|
98
|
+
}
|
99
|
+
|
100
|
+
private set LastLoginAt(value: Date) {
|
101
|
+
this._LastLoginAt = value;
|
102
|
+
}
|
103
|
+
|
104
|
+
get MFAEnabled(): number {
|
105
|
+
return this._MFAEnabled;
|
106
|
+
}
|
107
|
+
|
108
|
+
private set MFAEnabled(value: number) {
|
109
|
+
this._MFAEnabled = value;
|
110
|
+
}
|
111
|
+
|
112
|
+
get MFAConfig(): string {
|
113
|
+
return this._MFAConfig;
|
114
|
+
}
|
115
|
+
|
116
|
+
private set MFAConfig(value: string) {
|
117
|
+
this._MFAConfig = value;
|
118
|
+
}
|
119
|
+
|
120
|
+
get RecoveryEmail(): string {
|
121
|
+
return this._RecoveryEmail;
|
122
|
+
}
|
123
|
+
|
124
|
+
private set RecoveryEmail(value: string) {
|
125
|
+
this._RecoveryEmail = value;
|
126
|
+
}
|
127
|
+
|
128
|
+
get FailedLoginAttemptCount(): number {
|
129
|
+
return this._FailedLoginAttemptCount;
|
130
|
+
}
|
131
|
+
|
132
|
+
private set FailedLoginAttemptCount(value: number) {
|
133
|
+
this._FailedLoginAttemptCount = value;
|
134
|
+
}
|
135
|
+
|
136
|
+
get LastFailedLoginAt(): Date {
|
137
|
+
return this._LastFailedLoginAt;
|
138
|
+
}
|
139
|
+
|
140
|
+
private set LastFailedLoginAt(value: Date) {
|
141
|
+
this._LastFailedLoginAt = value;
|
142
|
+
}
|
143
|
+
|
144
|
+
get LastPasswordChangedAt(): Date {
|
145
|
+
return this._LastPasswordChangedAt;
|
146
|
+
}
|
147
|
+
|
148
|
+
private set LastPasswordChangedAt(value: Date) {
|
149
|
+
this._LastPasswordChangedAt = value;
|
150
|
+
}
|
151
|
+
|
152
|
+
get NeedToChangePasswordYN(): YN {
|
153
|
+
return this._NeedToChangePasswordYN;
|
154
|
+
}
|
155
|
+
|
156
|
+
private set NeedToChangePasswordYN(value: YN) {
|
157
|
+
this._NeedToChangePasswordYN = value;
|
158
|
+
}
|
159
|
+
|
160
|
+
get CreatedById(): number {
|
161
|
+
return this._CreatedById;
|
162
|
+
}
|
163
|
+
|
164
|
+
private set CreatedById(value: number) {
|
165
|
+
this._CreatedById = value;
|
166
|
+
}
|
167
|
+
|
168
|
+
get CreatedAt(): Date {
|
169
|
+
return this._CreatedAt;
|
170
|
+
}
|
171
|
+
|
172
|
+
private set CreatedAt(value: Date) {
|
173
|
+
this._CreatedAt = value;
|
174
|
+
}
|
175
|
+
|
176
|
+
get UpdatedById(): number {
|
177
|
+
return this._UpdatedById;
|
178
|
+
}
|
179
|
+
|
180
|
+
private set UpdatedById(value: number) {
|
181
|
+
this._UpdatedById = value;
|
182
|
+
}
|
183
|
+
|
184
|
+
get UpdatedAt(): Date {
|
185
|
+
return this._UpdatedAt;
|
186
|
+
}
|
187
|
+
|
188
|
+
private set UpdatedAt(value: Date) {
|
189
|
+
this._UpdatedAt = value;
|
190
|
+
}
|
191
|
+
|
192
|
+
async getDetails(): Promise<{
|
193
|
+
FullName: string;
|
194
|
+
IDNo: string;
|
195
|
+
IDType: string;
|
196
|
+
Email: string;
|
197
|
+
ContactNo: string;
|
198
|
+
}> {
|
199
|
+
return {
|
200
|
+
FullName: this.FullName,
|
201
|
+
IDNo: this.IDNo,
|
202
|
+
IDType: this.IDType,
|
203
|
+
Email: this.Email,
|
204
|
+
ContactNo: this.ContactNo,
|
205
|
+
};
|
206
|
+
}
|
207
|
+
|
208
|
+
private constructor(
|
209
|
+
sessionService: ISessionService,
|
210
|
+
dbTransaction?: any,
|
211
|
+
userInfo?: IUserAttr,
|
212
|
+
) {
|
213
|
+
super();
|
214
|
+
this._SessionService = sessionService;
|
215
|
+
|
216
|
+
if (dbTransaction) {
|
217
|
+
this._dbTransaction = dbTransaction;
|
218
|
+
}
|
219
|
+
// set all the class properties
|
220
|
+
if (userInfo) {
|
221
|
+
this.UserId = userInfo.UserId;
|
222
|
+
this.FullName = userInfo.FullName;
|
223
|
+
this.IDNo = userInfo.IDNo;
|
224
|
+
this.Email = userInfo.Email;
|
225
|
+
this.ContactNo = userInfo.ContactNo;
|
226
|
+
this.Password = userInfo.Password;
|
227
|
+
this.staffs = userInfo.staffs;
|
228
|
+
}
|
229
|
+
}
|
230
|
+
|
231
|
+
static async init(
|
232
|
+
sessionService: ISessionService,
|
233
|
+
userId?: number,
|
234
|
+
dbTransaction = null,
|
235
|
+
): Promise<LoginUser> {
|
236
|
+
if (userId) {
|
237
|
+
if (dbTransaction) {
|
238
|
+
LoginUser._Repository = new UserRepository();
|
239
|
+
}
|
240
|
+
const user = await LoginUser._Repository.findOne({
|
241
|
+
where: {
|
242
|
+
UserId: userId,
|
243
|
+
},
|
244
|
+
include: [
|
245
|
+
{
|
246
|
+
model: Staff,
|
247
|
+
},
|
248
|
+
],
|
249
|
+
});
|
250
|
+
|
251
|
+
if (!user) {
|
252
|
+
throw new Error('Invalid credentials.');
|
253
|
+
}
|
254
|
+
|
255
|
+
if (user) {
|
256
|
+
const userAttr: IUserAttr = {
|
257
|
+
UserId: user.UserId,
|
258
|
+
FullName: user.Staff.FullName,
|
259
|
+
IDNo: user.Staff.IdNo,
|
260
|
+
ContactNo: user.Staff.Mobile,
|
261
|
+
Email: user.Email,
|
262
|
+
Password: user.Password,
|
263
|
+
Status: user.Status,
|
264
|
+
DefaultPasswordChangedYN: user.DefaultPasswordChangedYN,
|
265
|
+
FirstLoginAt: user.FirstLoginAt,
|
266
|
+
LastLoginAt: user.LastLoginAt,
|
267
|
+
MFAEnabled: user.MFAEnabled,
|
268
|
+
MFAConfig: user.MFAConfig,
|
269
|
+
RecoveryEmail: user.RecoveryEmail,
|
270
|
+
FailedLoginAttemptCount: user.FailedLoginAttemptCount,
|
271
|
+
LastFailedLoginAt: user.LastFailedLoginAt,
|
272
|
+
LastPasswordChangedAt: user.LastPasswordChangedAt,
|
273
|
+
NeedToChangePasswordYN: user.NeedToChangePasswordYN,
|
274
|
+
CreatedById: user.CreatedById,
|
275
|
+
CreatedAt: user.CreatedAt,
|
276
|
+
UpdatedById: user.UpdatedById,
|
277
|
+
UpdatedAt: user.UpdatedAt,
|
278
|
+
staffs: user.Staff,
|
279
|
+
};
|
280
|
+
|
281
|
+
return new LoginUser(sessionService, dbTransaction, userAttr);
|
282
|
+
} else {
|
283
|
+
throw new Error('User not found');
|
284
|
+
}
|
285
|
+
}
|
286
|
+
return new LoginUser(sessionService, dbTransaction);
|
287
|
+
}
|
288
|
+
|
289
|
+
async login(
|
290
|
+
systemCode: string,
|
291
|
+
email: string,
|
292
|
+
password: string,
|
293
|
+
ipAddress: string,
|
294
|
+
): Promise<string> {
|
295
|
+
try {
|
296
|
+
//validate email
|
297
|
+
if (!this.ObjectId) {
|
298
|
+
const user = await LoginUser._Repository.findOne({
|
299
|
+
where: {
|
300
|
+
Email: email,
|
301
|
+
},
|
302
|
+
include: [
|
303
|
+
{
|
304
|
+
model: Staff,
|
305
|
+
},
|
306
|
+
],
|
307
|
+
});
|
308
|
+
|
309
|
+
const userAttr: IUserAttr = {
|
310
|
+
UserId: user.UserId,
|
311
|
+
FullName: user.Staff.FullName,
|
312
|
+
IDNo: user.Staff.IdNo,
|
313
|
+
ContactNo: user.Staff.Mobile,
|
314
|
+
Email: user.Email,
|
315
|
+
Password: user.Password,
|
316
|
+
Status: user.Status,
|
317
|
+
DefaultPasswordChangedYN: user.DefaultPasswordChangedYN,
|
318
|
+
FirstLoginAt: user.FirstLoginAt,
|
319
|
+
LastLoginAt: user.LastLoginAt,
|
320
|
+
MFAEnabled: user.MFAEnabled,
|
321
|
+
MFAConfig: user.MFAConfig,
|
322
|
+
RecoveryEmail: user.RecoveryEmail,
|
323
|
+
FailedLoginAttemptCount: user.FailedLoginAttemptCount,
|
324
|
+
LastFailedLoginAt: user.LastFailedLoginAt,
|
325
|
+
LastPasswordChangedAt: user.LastPasswordChangedAt,
|
326
|
+
NeedToChangePasswordYN: user.NeedToChangePasswordYN,
|
327
|
+
CreatedById: user.CreatedById,
|
328
|
+
CreatedAt: user.CreatedAt,
|
329
|
+
UpdatedById: user.UpdatedById,
|
330
|
+
UpdatedAt: user.UpdatedAt,
|
331
|
+
staffs: user.Staff,
|
332
|
+
};
|
333
|
+
|
334
|
+
this.UserId = userAttr.UserId;
|
335
|
+
this.FullName = userAttr.FullName;
|
336
|
+
this.IDNo = userAttr.IDNo;
|
337
|
+
this.Email = userAttr.Email;
|
338
|
+
this.ContactNo = userAttr.ContactNo;
|
339
|
+
this.Password = userAttr.Password;
|
340
|
+
this.Status = userAttr.Status;
|
341
|
+
this.DefaultPasswordChangedYN = userAttr.DefaultPasswordChangedYN;
|
342
|
+
this.FirstLoginAt = userAttr.FirstLoginAt;
|
343
|
+
this.LastLoginAt = userAttr.LastLoginAt;
|
344
|
+
this.MFAEnabled = userAttr.MFAEnabled;
|
345
|
+
this.MFAConfig = userAttr.MFAConfig;
|
346
|
+
this.RecoveryEmail = userAttr.RecoveryEmail;
|
347
|
+
this.FailedLoginAttemptCount = userAttr.FailedLoginAttemptCount;
|
348
|
+
this.LastFailedLoginAt = userAttr.LastFailedLoginAt;
|
349
|
+
this.LastPasswordChangedAt = userAttr.LastPasswordChangedAt;
|
350
|
+
this.NeedToChangePasswordYN = userAttr.NeedToChangePasswordYN;
|
351
|
+
this.CreatedById = userAttr.CreatedById;
|
352
|
+
this.CreatedAt = userAttr.CreatedAt;
|
353
|
+
this.UpdatedById = userAttr.UpdatedById;
|
354
|
+
this.UpdatedAt = userAttr.UpdatedAt;
|
355
|
+
this.staffs = userAttr.staffs;
|
356
|
+
}
|
357
|
+
|
358
|
+
if (this.ObjectId && this.Email !== email) {
|
359
|
+
throw new Error('Invalid credentials.');
|
360
|
+
}
|
361
|
+
|
362
|
+
//validate password
|
363
|
+
const isPasswordValid = await this._PasswordHashService.verify(
|
364
|
+
password,
|
365
|
+
this.Password,
|
366
|
+
);
|
367
|
+
|
368
|
+
if (!isPasswordValid) {
|
369
|
+
throw new Error('Invalid credentials.');
|
370
|
+
}
|
371
|
+
|
372
|
+
//validate system code
|
373
|
+
const system = await LoginUser._SystemRepository.findOne({
|
374
|
+
where: {
|
375
|
+
code: systemCode,
|
376
|
+
},
|
377
|
+
});
|
378
|
+
|
379
|
+
if (!system) {
|
380
|
+
throw new Error('Invalid system code.');
|
381
|
+
}
|
382
|
+
|
383
|
+
//validate system access
|
384
|
+
await this.checkSystemAccess(this.UserId, system.id);
|
385
|
+
// alert user if new login
|
386
|
+
await this.alertNewLogin(this.ObjectId, system.id.toString(), ipAddress);
|
387
|
+
|
388
|
+
// fetch user session if exists
|
389
|
+
const userSession = await this._SessionService.retrieveUserSession(
|
390
|
+
this.ObjectId,
|
391
|
+
);
|
392
|
+
let systemLogin = userSession.systemLogins.find(
|
393
|
+
(system) => system.code === systemCode,
|
394
|
+
);
|
395
|
+
|
396
|
+
// generate new session id
|
397
|
+
const { randomUUID } = require('crypto');
|
398
|
+
const sessionId = randomUUID();
|
399
|
+
|
400
|
+
if (systemLogin) {
|
401
|
+
systemLogin = systemLogin.sessionId = sessionId;
|
402
|
+
userSession.systemLogins.map((system) =>
|
403
|
+
system.code === systemCode ? systemLogin : system,
|
404
|
+
);
|
405
|
+
} else {
|
406
|
+
// if not, add new system login into the userSession
|
407
|
+
const newLogin = {
|
408
|
+
id: system.id.toString(),
|
409
|
+
code: system.Code,
|
410
|
+
sessionId: sessionId,
|
411
|
+
privileges: await this.getPrivileges(system.Code),
|
412
|
+
};
|
413
|
+
userSession.systemLogins.push(newLogin);
|
414
|
+
}
|
415
|
+
// then update userSession inside the redis storage with 1 day duration of time-to-live
|
416
|
+
this._SessionService.setUserSession(this.ObjectId, userSession);
|
417
|
+
|
418
|
+
// record new login history
|
419
|
+
await LoginUser._LoginHistoryRepository.create({
|
420
|
+
UserId: this.UserId,
|
421
|
+
SystemId: system.id,
|
422
|
+
OriginIp: ipAddress,
|
423
|
+
CreatedAt: new Date(),
|
424
|
+
});
|
425
|
+
|
426
|
+
return `${this.UserId}:${sessionId}`;
|
427
|
+
} catch (error) {
|
428
|
+
throw error;
|
429
|
+
}
|
430
|
+
}
|
431
|
+
|
432
|
+
private async checkSystemAccess(
|
433
|
+
userId: number,
|
434
|
+
systemId: number,
|
435
|
+
): Promise<void> {
|
436
|
+
try {
|
437
|
+
const systemAccess = await LoginUser._SystemAccessRepository.findOne({
|
438
|
+
where: {
|
439
|
+
UserId: userId,
|
440
|
+
SystemId: systemId,
|
441
|
+
},
|
442
|
+
});
|
443
|
+
|
444
|
+
if (!systemAccess) {
|
445
|
+
throw new Error("User don't have access to the system.");
|
446
|
+
}
|
447
|
+
} catch (error) {
|
448
|
+
throw error;
|
449
|
+
}
|
450
|
+
}
|
451
|
+
|
452
|
+
private async alertNewLogin(
|
453
|
+
userId: string,
|
454
|
+
systemId: string,
|
455
|
+
ipAddress: string,
|
456
|
+
) {
|
457
|
+
try {
|
458
|
+
const userLogins = await LoginUser._LoginHistoryRepository.findAll({
|
459
|
+
where: {
|
460
|
+
UserId: userId,
|
461
|
+
SystemId: systemId,
|
462
|
+
},
|
463
|
+
});
|
464
|
+
|
465
|
+
const gotPreviousLogins = userLogins?.length !== 0;
|
466
|
+
let ipFound: LoginHistory | undefined = undefined;
|
467
|
+
if (gotPreviousLogins) {
|
468
|
+
ipFound = userLogins.find((item) => item.OriginIp === ipAddress);
|
469
|
+
}
|
470
|
+
|
471
|
+
if (gotPreviousLogins && !ipFound) {
|
472
|
+
const EMAIL_SENDER =
|
473
|
+
process.env.EMAIL_SENDER || 'itd-system@tomei.com.my';
|
474
|
+
const transporter = new SMTPMailer();
|
475
|
+
|
476
|
+
await transporter.sendMail({
|
477
|
+
from: EMAIL_SENDER,
|
478
|
+
to: this.Email,
|
479
|
+
subject: 'New Login Alert',
|
480
|
+
html: `<p>Dear ${this.FullName},</p>
|
481
|
+
<p>There was a new login to your account from ${ipAddress} on ${new Date().toLocaleString()}.</p>
|
482
|
+
<p>If this was you, you can safely ignore this email.</p>
|
483
|
+
<p>If you suspect that someone else is trying to access your account, please contact us immediately at itd-support@tomei.com.my.</p>
|
484
|
+
<p>Thank you!,</p>
|
485
|
+
<p>
|
486
|
+
Best Regards,
|
487
|
+
IT Department
|
488
|
+
</p>`,
|
489
|
+
});
|
490
|
+
}
|
491
|
+
} catch (error) {
|
492
|
+
throw error;
|
493
|
+
}
|
494
|
+
}
|
495
|
+
|
496
|
+
private async getPrivileges(systemCode: string): Promise<string[]> {
|
497
|
+
try {
|
498
|
+
const system = await LoginUser._SystemRepository.findOne({
|
499
|
+
where: {
|
500
|
+
Code: systemCode,
|
501
|
+
},
|
502
|
+
});
|
503
|
+
|
504
|
+
if (!system) {
|
505
|
+
throw new Error('Invalid system code.');
|
506
|
+
}
|
507
|
+
|
508
|
+
// retrive user userGroups with system privileges
|
509
|
+
const userUserGroups = await this.getUserUserGroupFromDB(system.id);
|
510
|
+
|
511
|
+
// get all userGroup data from user userGroups
|
512
|
+
const userGroupData = userUserGroups.map((u) => u.UserGroup);
|
513
|
+
// get all privileges from userGroup data
|
514
|
+
let privileges: string[] = [];
|
515
|
+
for (const userGroup of userGroupData) {
|
516
|
+
const groupSystemPrivileges = userGroup.GroupSystemPrivileges.map(
|
517
|
+
(g) => g.SystemPrivilege.Code,
|
518
|
+
);
|
519
|
+
const groupRolePrivileges = userGroup.GroupRolePrivileges.map(
|
520
|
+
(g) => g.SystemPrivilege.Code,
|
521
|
+
);
|
522
|
+
|
523
|
+
// if userGroup is not root, get all parent tree privileges
|
524
|
+
if (
|
525
|
+
userGroup.GroupLevel !== 0 &&
|
526
|
+
userGroup.AllowInheritFromParentYN === 'Y'
|
527
|
+
) {
|
528
|
+
// get all parent tree privileges
|
529
|
+
const parentTreePrivileges = await this.getPrivilegesFromUserGroup(
|
530
|
+
userGroup.ParentGroupCode,
|
531
|
+
);
|
532
|
+
|
533
|
+
privileges = [...privileges, ...parentTreePrivileges];
|
534
|
+
}
|
535
|
+
|
536
|
+
privileges = [
|
537
|
+
...privileges,
|
538
|
+
...groupSystemPrivileges,
|
539
|
+
...groupRolePrivileges,
|
540
|
+
];
|
541
|
+
}
|
542
|
+
|
543
|
+
// retrive all user personal privileges
|
544
|
+
const userPrivileges = await this.getUserPersonalPrivileges(system.id);
|
545
|
+
|
546
|
+
privileges = [...privileges, ...userPrivileges];
|
547
|
+
privileges = [...new Set(privileges)];
|
548
|
+
return privileges;
|
549
|
+
} catch (error) {
|
550
|
+
throw error;
|
551
|
+
}
|
552
|
+
}
|
553
|
+
|
554
|
+
private async getPrivilegesFromUserGroup(
|
555
|
+
groupCode: string,
|
556
|
+
): Promise<string[]> {
|
557
|
+
try {
|
558
|
+
// Retrieve userGroup from the database based on groupCode
|
559
|
+
const userGroup = await this.getUserGroupFromDB(groupCode);
|
560
|
+
let privileges: string[] = [];
|
561
|
+
|
562
|
+
// Add privileges from the userGroup to the privileges array
|
563
|
+
privileges = [
|
564
|
+
...privileges,
|
565
|
+
...userGroup.GroupSystemPrivileges.map((g) => g.SystemPrivilege.Code),
|
566
|
+
...userGroup.GroupRolePrivileges.map((g) => g.SystemPrivilege.Code),
|
567
|
+
];
|
568
|
+
|
569
|
+
// Recursive call if conditions are not met and ParentGroupCode exists
|
570
|
+
const isContinue =
|
571
|
+
userGroup.GroupLevel !== 0 &&
|
572
|
+
userGroup.AllowInheritFromParentYN === 'Y';
|
573
|
+
if (isContinue) {
|
574
|
+
const recursivePrivileges = await this.getPrivilegesFromUserGroup(
|
575
|
+
userGroup.ParentGroupCode,
|
576
|
+
);
|
577
|
+
privileges = privileges.concat(recursivePrivileges);
|
578
|
+
}
|
579
|
+
|
580
|
+
// return privileges array
|
581
|
+
return privileges;
|
582
|
+
} catch (error) {
|
583
|
+
throw error;
|
584
|
+
}
|
585
|
+
}
|
586
|
+
|
587
|
+
private async getUserGroupFromDB(groupCode: string): Promise<any> {
|
588
|
+
try {
|
589
|
+
const userGroup = await LoginUser._UserGroupRepository.findOne({
|
590
|
+
where: {
|
591
|
+
GroupCode: groupCode,
|
592
|
+
},
|
593
|
+
include: [
|
594
|
+
{
|
595
|
+
model: GroupSystemPrivilege,
|
596
|
+
include: {
|
597
|
+
model: SystemPrivilege,
|
598
|
+
},
|
599
|
+
},
|
600
|
+
{
|
601
|
+
model: GroupRolePrivilege,
|
602
|
+
include: {
|
603
|
+
model: SystemPrivilege,
|
604
|
+
},
|
605
|
+
},
|
606
|
+
],
|
607
|
+
});
|
608
|
+
return userGroup;
|
609
|
+
} catch (error) {
|
610
|
+
throw error;
|
611
|
+
}
|
612
|
+
}
|
613
|
+
|
614
|
+
private async getUserUserGroupFromDB(systemCode: number) {
|
615
|
+
try {
|
616
|
+
return await LoginUser._UserUserGroupRepository.findAll({
|
617
|
+
where: {
|
618
|
+
UserId: this.UserId,
|
619
|
+
SystemId: systemCode,
|
620
|
+
},
|
621
|
+
include: {
|
622
|
+
model: UserGroup,
|
623
|
+
include: [
|
624
|
+
{
|
625
|
+
model: GroupSystemPrivilege,
|
626
|
+
include: {
|
627
|
+
model: SystemPrivilege,
|
628
|
+
},
|
629
|
+
},
|
630
|
+
{
|
631
|
+
model: GroupRolePrivilege,
|
632
|
+
include: {
|
633
|
+
model: SystemPrivilege,
|
634
|
+
},
|
635
|
+
},
|
636
|
+
],
|
637
|
+
},
|
638
|
+
});
|
639
|
+
} catch (error) {
|
640
|
+
throw error;
|
641
|
+
}
|
642
|
+
}
|
643
|
+
|
644
|
+
private async getUserPersonalPrivileges(systemId: number): Promise<string[]> {
|
645
|
+
try {
|
646
|
+
const userRole = await LoginUser._Repository.findOne({
|
647
|
+
where: {
|
648
|
+
UserId: this.ObjectId,
|
649
|
+
},
|
650
|
+
include: {
|
651
|
+
model: SystemPrivilege,
|
652
|
+
},
|
653
|
+
});
|
654
|
+
|
655
|
+
//retrive all user systemPrevileges data from user roles
|
656
|
+
let userSystemPrivileges = userRole.SystemPrivileges;
|
657
|
+
|
658
|
+
userSystemPrivileges = userSystemPrivileges.filter(
|
659
|
+
(u) => u.SystemId === systemId,
|
660
|
+
);
|
661
|
+
|
662
|
+
const userPrivileges: string[] = userSystemPrivileges.map((u) => u.Code);
|
663
|
+
return userPrivileges;
|
664
|
+
} catch (error) {
|
665
|
+
throw error;
|
666
|
+
}
|
667
|
+
}
|
668
|
+
|
669
|
+
async checkPrivileges(
|
670
|
+
systemCode: string,
|
671
|
+
privilegeName: string,
|
672
|
+
): Promise<boolean> {
|
673
|
+
try {
|
674
|
+
if (!this.ObjectId) {
|
675
|
+
throw new Error('ObjectId(UserId) is not set');
|
676
|
+
}
|
677
|
+
|
678
|
+
const userSession = await this._SessionService.retrieveUserSession(
|
679
|
+
this.ObjectId,
|
680
|
+
);
|
681
|
+
|
682
|
+
const systemLogin = userSession.systemLogins.find(
|
683
|
+
(system) => system.code === systemCode,
|
684
|
+
);
|
685
|
+
|
686
|
+
if (!systemLogin) {
|
687
|
+
return false;
|
688
|
+
}
|
689
|
+
|
690
|
+
const privileges = systemLogin.privileges;
|
691
|
+
const hasPrivilege = privileges.includes(privilegeName);
|
692
|
+
return hasPrivilege;
|
693
|
+
} catch (error) {
|
694
|
+
throw error;
|
695
|
+
}
|
696
|
+
}
|
697
|
+
|
698
|
+
async checkSession(
|
699
|
+
systemCode: string,
|
700
|
+
sessionId: string,
|
701
|
+
userId: string,
|
702
|
+
): Promise<ISystemLogin> {
|
703
|
+
try {
|
704
|
+
const userSession = await this._SessionService.retrieveUserSession(
|
705
|
+
userId,
|
706
|
+
);
|
707
|
+
|
708
|
+
if (userSession.systemLogins.length === 0) {
|
709
|
+
throw new Error('Session expired.');
|
710
|
+
}
|
711
|
+
|
712
|
+
const systemLogin = userSession.systemLogins.find(
|
713
|
+
(sl) => sl.code === systemCode,
|
714
|
+
);
|
715
|
+
|
716
|
+
if (!systemLogin) {
|
717
|
+
throw new Error('Session expired.');
|
718
|
+
}
|
719
|
+
|
720
|
+
if (systemLogin.sessionId !== sessionId) {
|
721
|
+
throw new Error('Session expired.');
|
722
|
+
}
|
723
|
+
|
724
|
+
await this._SessionService.refreshDuration(userId);
|
725
|
+
|
726
|
+
return systemLogin;
|
727
|
+
} catch (error) {
|
728
|
+
throw error;
|
729
|
+
}
|
730
|
+
}
|
731
|
+
|
732
|
+
async logout(systemCode: string) {
|
733
|
+
try {
|
734
|
+
if (!this.ObjectId) {
|
735
|
+
throw new Error('ObjectId(UserId) is not set');
|
736
|
+
}
|
737
|
+
const userSession = await this._SessionService.retrieveUserSession(
|
738
|
+
this.ObjectId,
|
739
|
+
);
|
740
|
+
const index = userSession.systemLogins.findIndex(
|
741
|
+
(system) => system.code === systemCode,
|
742
|
+
);
|
743
|
+
userSession.systemLogins.splice(index, 1);
|
744
|
+
this._SessionService.setUserSession(this.ObjectId, userSession);
|
745
|
+
} catch (error) {
|
746
|
+
throw error;
|
747
|
+
}
|
748
|
+
}
|
749
|
+
}
|