@tomei/sso 0.66.1-test.2 → 0.66.1-test.4
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/__tests__/unit/components/group-reporting-user/group-reporting-user.spec.ts +12 -8
- package/__tests__/unit/components/login-user/login.spec.ts +310 -72
- package/__tests__/unit/components/login-user/password-expiry.spec.ts +87 -0
- package/dist/__tests__/unit/components/group-reporting-user/group-reporting-user.spec.js +6 -2
- package/dist/__tests__/unit/components/group-reporting-user/group-reporting-user.spec.js.map +1 -1
- package/dist/__tests__/unit/components/login-user/login.spec.js +227 -69
- package/dist/__tests__/unit/components/login-user/login.spec.js.map +1 -1
- package/dist/__tests__/unit/components/login-user/password-expiry.spec.d.ts +1 -0
- package/dist/__tests__/unit/components/login-user/password-expiry.spec.js +86 -0
- package/dist/__tests__/unit/components/login-user/password-expiry.spec.js.map +1 -0
- package/dist/src/components/login-user/interfaces/user-info.interface.d.ts +1 -0
- package/dist/src/components/login-user/login-user.d.ts +1 -0
- package/dist/src/components/login-user/login-user.js +85 -14
- package/dist/src/components/login-user/login-user.js.map +1 -1
- package/dist/src/components/login-user/user.d.ts +1 -0
- package/dist/src/components/login-user/user.js +7 -1
- package/dist/src/components/login-user/user.js.map +1 -1
- package/dist/src/components/system/system.d.ts +1 -0
- package/dist/src/components/system/system.js +1 -0
- package/dist/src/components/system/system.js.map +1 -1
- package/dist/src/components/system-privilege/system-privilege.d.ts +1 -0
- package/dist/src/components/system-privilege/system-privilege.js +2 -0
- package/dist/src/components/system-privilege/system-privilege.js.map +1 -1
- package/dist/src/index.d.ts +1 -0
- package/dist/src/index.js +1 -0
- package/dist/src/index.js.map +1 -1
- package/dist/src/interfaces/system-privilege.interface.d.ts +1 -0
- package/dist/src/interfaces/system.interface.d.ts +1 -0
- package/dist/src/models/group.entity.d.ts +1 -0
- package/dist/src/models/group.entity.js +8 -1
- package/dist/src/models/group.entity.js.map +1 -1
- package/dist/src/models/system-privilege.entity.d.ts +1 -0
- package/dist/src/models/system-privilege.entity.js +7 -0
- package/dist/src/models/system-privilege.entity.js.map +1 -1
- package/dist/src/models/system.entity.d.ts +1 -0
- package/dist/src/models/system.entity.js +7 -0
- package/dist/src/models/system.entity.js.map +1 -1
- package/dist/src/models/user.entity.d.ts +1 -0
- package/dist/src/models/user.entity.js +7 -0
- package/dist/src/models/user.entity.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +2 -1
- package/src/components/login-user/interfaces/user-info.interface.ts +1 -0
- package/src/components/login-user/login-user.ts +125 -17
- package/src/components/login-user/user.ts +14 -2
- package/src/components/system/system.ts +2 -0
- package/src/components/system-privilege/system-privilege.ts +3 -0
- package/src/index.ts +1 -0
- package/src/interfaces/system-privilege.interface.ts +1 -0
- package/src/interfaces/system.interface.ts +1 -0
- package/src/models/group.entity.ts +7 -1
- package/src/models/system-privilege.entity.ts +6 -0
- package/src/models/system.entity.ts +6 -0
- package/src/models/user.entity.ts +6 -0
- package/coverage/cobertura-coverage.xml +0 -6837
- package/coverage/test-report.xml +0 -161
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tomei/sso",
|
|
3
|
-
"version": "0.66.1-test.
|
|
3
|
+
"version": "0.66.1-test.4",
|
|
4
4
|
"description": "Tomei SSO Package",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"scripts": {
|
|
@@ -65,6 +65,7 @@
|
|
|
65
65
|
"@tomei/general": "^0.21.10",
|
|
66
66
|
"@tomei/mailer": "^0.6.2",
|
|
67
67
|
"argon2": "^0.44.0",
|
|
68
|
+
"axios": "^1.13.2",
|
|
68
69
|
"redis": "^5.8.2",
|
|
69
70
|
"reflect-metadata": "^0.2.2",
|
|
70
71
|
"sequelize": "^6.37.7",
|
|
@@ -12,13 +12,27 @@ import { createHash, randomBytes, randomUUID } from 'crypto';
|
|
|
12
12
|
import { UserGroupRepository } from '../user-group/user-group.repository';
|
|
13
13
|
import GroupSystemAccessModel from '../../models/group-system-access.entity';
|
|
14
14
|
import SystemModel from '../../models/system.entity';
|
|
15
|
-
import { ApplicationConfig } from '@tomei/config';
|
|
15
|
+
import { ApplicationConfig, ComponentConfig } from '@tomei/config';
|
|
16
|
+
import axios from 'axios';
|
|
16
17
|
|
|
17
18
|
export class LoginUser extends User implements ILoginUser {
|
|
18
19
|
session = {
|
|
19
20
|
Id: null,
|
|
20
21
|
};
|
|
21
22
|
|
|
23
|
+
private static isLoginApiEnabled(): boolean {
|
|
24
|
+
try {
|
|
25
|
+
const useLoginApiYN =
|
|
26
|
+
ComponentConfig.getComponentConfigValue(
|
|
27
|
+
'@tomei/sso',
|
|
28
|
+
'useLoginApiYN',
|
|
29
|
+
) || 'Y';
|
|
30
|
+
return String(useLoginApiYN).toUpperCase() !== 'N';
|
|
31
|
+
} catch (error) {
|
|
32
|
+
return true;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
22
36
|
static async init(
|
|
23
37
|
sessionService: ISessionService,
|
|
24
38
|
userId?: number,
|
|
@@ -26,20 +40,43 @@ export class LoginUser extends User implements ILoginUser {
|
|
|
26
40
|
): Promise<LoginUser> {
|
|
27
41
|
User._RedisService = await RedisService.init();
|
|
28
42
|
if (userId) {
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
43
|
+
let user: any;
|
|
44
|
+
|
|
45
|
+
if (LoginUser.isLoginApiEnabled()) {
|
|
46
|
+
const loginApiEndpoint = ComponentConfig.getComponentConfigValue(
|
|
47
|
+
'@tomei/sso',
|
|
48
|
+
'loginApiEndpoint',
|
|
49
|
+
);
|
|
50
|
+
|
|
51
|
+
let payload = { UserId: userId };
|
|
52
|
+
|
|
53
|
+
const { data } = await axios.post(
|
|
54
|
+
`${loginApiEndpoint.baseUrl}${loginApiEndpoint.getProfile}`,
|
|
55
|
+
payload,
|
|
37
56
|
{
|
|
38
|
-
|
|
57
|
+
headers: {
|
|
58
|
+
'Content-Type': 'application/json',
|
|
59
|
+
'x-api-key': loginApiEndpoint.apiKey,
|
|
60
|
+
},
|
|
39
61
|
},
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
}
|
|
62
|
+
);
|
|
63
|
+
user = data.loginUser;
|
|
64
|
+
} else {
|
|
65
|
+
if (dbTransaction) {
|
|
66
|
+
User._Repository = new UserRepository();
|
|
67
|
+
}
|
|
68
|
+
user = await User._Repository.findOne({
|
|
69
|
+
where: {
|
|
70
|
+
UserId: userId,
|
|
71
|
+
},
|
|
72
|
+
include: [
|
|
73
|
+
{
|
|
74
|
+
model: Staff,
|
|
75
|
+
},
|
|
76
|
+
],
|
|
77
|
+
transaction: dbTransaction,
|
|
78
|
+
});
|
|
79
|
+
}
|
|
43
80
|
|
|
44
81
|
if (!user) {
|
|
45
82
|
throw new Error('Invalid credentials.');
|
|
@@ -99,6 +136,30 @@ export class LoginUser extends User implements ILoginUser {
|
|
|
99
136
|
throw new Error('Session name is not set');
|
|
100
137
|
}
|
|
101
138
|
|
|
139
|
+
if (LoginUser.isLoginApiEnabled()) {
|
|
140
|
+
const loginApiEndpoint = ComponentConfig.getComponentConfigValue(
|
|
141
|
+
'@tomei/sso',
|
|
142
|
+
'loginApiEndpoint',
|
|
143
|
+
);
|
|
144
|
+
let payload = {
|
|
145
|
+
SystemCode: systemCode,
|
|
146
|
+
SessionName: sessionName,
|
|
147
|
+
PrivilegeName: privilegeName,
|
|
148
|
+
UserId: this.ObjectId,
|
|
149
|
+
};
|
|
150
|
+
const { data } = await axios.post(
|
|
151
|
+
`${loginApiEndpoint.baseUrl}${loginApiEndpoint.checkPrivileges}`,
|
|
152
|
+
payload,
|
|
153
|
+
{
|
|
154
|
+
headers: {
|
|
155
|
+
'Content-Type': 'application/json',
|
|
156
|
+
'x-api-key': loginApiEndpoint.apiKey,
|
|
157
|
+
},
|
|
158
|
+
},
|
|
159
|
+
);
|
|
160
|
+
return data.hasPrivilege;
|
|
161
|
+
}
|
|
162
|
+
|
|
102
163
|
const userSession = await this._SessionService.retrieveUserSession(
|
|
103
164
|
this.ObjectId,
|
|
104
165
|
sessionName,
|
|
@@ -113,8 +174,7 @@ export class LoginUser extends User implements ILoginUser {
|
|
|
113
174
|
}
|
|
114
175
|
|
|
115
176
|
const privileges = systemLogin.privileges;
|
|
116
|
-
|
|
117
|
-
return hasPrivilege;
|
|
177
|
+
return privileges.includes(privilegeName);
|
|
118
178
|
} catch (error) {
|
|
119
179
|
throw error;
|
|
120
180
|
}
|
|
@@ -131,6 +191,31 @@ export class LoginUser extends User implements ILoginUser {
|
|
|
131
191
|
if (!sessionName) {
|
|
132
192
|
throw new Error('Session name is not set');
|
|
133
193
|
}
|
|
194
|
+
|
|
195
|
+
if (LoginUser.isLoginApiEnabled()) {
|
|
196
|
+
const loginApiEndpoint = ComponentConfig.getComponentConfigValue(
|
|
197
|
+
'@tomei/sso',
|
|
198
|
+
'loginApiEndpoint',
|
|
199
|
+
);
|
|
200
|
+
let payload = {
|
|
201
|
+
SystemCode: systemCode,
|
|
202
|
+
SessionName: sessionName,
|
|
203
|
+
SessionId: sessionId,
|
|
204
|
+
UserId: userId,
|
|
205
|
+
};
|
|
206
|
+
const { data } = await axios.post(
|
|
207
|
+
`${loginApiEndpoint.baseUrl}${loginApiEndpoint.checkSession}`,
|
|
208
|
+
payload,
|
|
209
|
+
{
|
|
210
|
+
headers: {
|
|
211
|
+
'Content-Type': 'application/json',
|
|
212
|
+
'x-api-key': loginApiEndpoint.apiKey,
|
|
213
|
+
},
|
|
214
|
+
},
|
|
215
|
+
);
|
|
216
|
+
return data.systemLogin;
|
|
217
|
+
}
|
|
218
|
+
|
|
134
219
|
const userSession = await this._SessionService.retrieveUserSession(
|
|
135
220
|
userId,
|
|
136
221
|
sessionName,
|
|
@@ -328,6 +413,31 @@ export class LoginUser extends User implements ILoginUser {
|
|
|
328
413
|
throw new Error('Session name is not set in the configuration');
|
|
329
414
|
}
|
|
330
415
|
|
|
416
|
+
if (LoginUser.isLoginApiEnabled()) {
|
|
417
|
+
const loginApiEndpoint = ComponentConfig.getComponentConfigValue(
|
|
418
|
+
'@tomei/sso',
|
|
419
|
+
'loginApiEndpoint',
|
|
420
|
+
);
|
|
421
|
+
let payload = {
|
|
422
|
+
SystemCode: systemCode,
|
|
423
|
+
SessionName: sessionName,
|
|
424
|
+
SessionId: sessionId,
|
|
425
|
+
UserId: this.ObjectId,
|
|
426
|
+
};
|
|
427
|
+
|
|
428
|
+
await axios.post(
|
|
429
|
+
`${loginApiEndpoint.baseUrl}${loginApiEndpoint.setSession}`,
|
|
430
|
+
payload,
|
|
431
|
+
{
|
|
432
|
+
headers: {
|
|
433
|
+
'Content-Type': 'application/json',
|
|
434
|
+
'x-api-key': loginApiEndpoint.apiKey,
|
|
435
|
+
},
|
|
436
|
+
},
|
|
437
|
+
);
|
|
438
|
+
return;
|
|
439
|
+
}
|
|
440
|
+
|
|
331
441
|
const userSession = await this._SessionService.retrieveUserSession(
|
|
332
442
|
this.ObjectId,
|
|
333
443
|
sessionName,
|
|
@@ -344,7 +454,6 @@ export class LoginUser extends User implements ILoginUser {
|
|
|
344
454
|
system.code === systemCode ? systemLogin : system,
|
|
345
455
|
);
|
|
346
456
|
} else {
|
|
347
|
-
// if not, add new system login into the userSession
|
|
348
457
|
const newLogin = {
|
|
349
458
|
id: systemCode,
|
|
350
459
|
code: systemCode,
|
|
@@ -353,7 +462,6 @@ export class LoginUser extends User implements ILoginUser {
|
|
|
353
462
|
};
|
|
354
463
|
userSession.systemLogins.push(newLogin);
|
|
355
464
|
}
|
|
356
|
-
// then update userSession inside the redis storage with 1 day duration of time-to-live
|
|
357
465
|
this._SessionService.setUserSession(
|
|
358
466
|
this.ObjectId,
|
|
359
467
|
userSession,
|
|
@@ -40,6 +40,7 @@ import { UserPasswordHistory } from '../user-password-history/user-password-hist
|
|
|
40
40
|
|
|
41
41
|
export class User extends UserBase {
|
|
42
42
|
ObjectId: string;
|
|
43
|
+
V1Id: number;
|
|
43
44
|
Email: string;
|
|
44
45
|
private _UserName: string;
|
|
45
46
|
private _Password: string;
|
|
@@ -291,6 +292,7 @@ export class User extends UserBase {
|
|
|
291
292
|
// set all the class properties
|
|
292
293
|
if (userInfo) {
|
|
293
294
|
this.UserId = userInfo.UserId;
|
|
295
|
+
this.V1Id = userInfo.V1Id;
|
|
294
296
|
this.UserName = userInfo.UserName;
|
|
295
297
|
this.FullName = userInfo.FullName;
|
|
296
298
|
this.IDNo = userInfo.IDNo;
|
|
@@ -3071,6 +3073,11 @@ export class User extends UserBase {
|
|
|
3071
3073
|
return { expired: false, expiringSoon: false, expiresInDays: null };
|
|
3072
3074
|
}
|
|
3073
3075
|
|
|
3076
|
+
// Accounts authenticated without a local password cannot rotate one here.
|
|
3077
|
+
if (!this.Password) {
|
|
3078
|
+
return { expired: false, expiringSoon: false, expiresInDays: null };
|
|
3079
|
+
}
|
|
3080
|
+
|
|
3074
3081
|
// Forces first-login change for temp-password/admin-created accounts (AC#4), regardless of password age.
|
|
3075
3082
|
if (this.NeedToChangePasswordYN === YN.Yes) {
|
|
3076
3083
|
return { expired: true, expiringSoon: false, expiresInDays: null };
|
|
@@ -3092,14 +3099,19 @@ export class User extends UserBase {
|
|
|
3092
3099
|
}
|
|
3093
3100
|
|
|
3094
3101
|
const createdAt = latestHistory.CreatedAt;
|
|
3102
|
+
const expiryMonth = createdAt.getUTCMonth() + expiryMonths;
|
|
3103
|
+
const lastDayOfExpiryMonth = new Date(
|
|
3104
|
+
Date.UTC(createdAt.getUTCFullYear(), expiryMonth + 1, 0),
|
|
3105
|
+
).getUTCDate();
|
|
3095
3106
|
const expiryDate = new Date(
|
|
3096
3107
|
Date.UTC(
|
|
3097
3108
|
createdAt.getUTCFullYear(),
|
|
3098
|
-
|
|
3099
|
-
createdAt.getUTCDate(),
|
|
3109
|
+
expiryMonth,
|
|
3110
|
+
Math.min(createdAt.getUTCDate(), lastDayOfExpiryMonth),
|
|
3100
3111
|
createdAt.getUTCHours(),
|
|
3101
3112
|
createdAt.getUTCMinutes(),
|
|
3102
3113
|
createdAt.getUTCSeconds(),
|
|
3114
|
+
createdAt.getUTCMilliseconds(),
|
|
3103
3115
|
),
|
|
3104
3116
|
);
|
|
3105
3117
|
|
|
@@ -10,6 +10,7 @@ import { v4 as uuidv4 } from 'uuid';
|
|
|
10
10
|
|
|
11
11
|
export class System extends ObjectBase {
|
|
12
12
|
ObjectId: string;
|
|
13
|
+
V1Id: number;
|
|
13
14
|
ObjectName: string;
|
|
14
15
|
TableName = 'sso_System';
|
|
15
16
|
ObjectType = 'System';
|
|
@@ -49,6 +50,7 @@ export class System extends ObjectBase {
|
|
|
49
50
|
private constructor(systemAttr?: ISystemAttr) {
|
|
50
51
|
super();
|
|
51
52
|
if (systemAttr) {
|
|
53
|
+
this.V1Id = systemAttr.V1Id;
|
|
52
54
|
this.SystemCode = systemAttr.SystemCode;
|
|
53
55
|
this.Name = systemAttr.Name;
|
|
54
56
|
this.Description = systemAttr?.Description;
|
|
@@ -13,6 +13,7 @@ export class SystemPrivilege extends ObjectBase {
|
|
|
13
13
|
ObjectType = 'SystemPrivilege';
|
|
14
14
|
TableName = 'sso_SystemPrivilege';
|
|
15
15
|
ObjectId: string;
|
|
16
|
+
V1Id: string;
|
|
16
17
|
PrivilegeCode: string;
|
|
17
18
|
SystemCode: string;
|
|
18
19
|
ObjectName: string;
|
|
@@ -53,6 +54,7 @@ export class SystemPrivilege extends ObjectBase {
|
|
|
53
54
|
private constructor(systemPrivilegeAttr?: ISystemPrivilegeAttr) {
|
|
54
55
|
super();
|
|
55
56
|
if (systemPrivilegeAttr) {
|
|
57
|
+
this.V1Id = systemPrivilegeAttr.V1Id;
|
|
56
58
|
this.SystemPrivilegeId = systemPrivilegeAttr.SystemPrivilegeId;
|
|
57
59
|
this.PrivilegeCode = systemPrivilegeAttr.PrivilegeCode;
|
|
58
60
|
this.SystemCode = systemPrivilegeAttr.SystemCode;
|
|
@@ -66,6 +68,7 @@ export class SystemPrivilege extends ObjectBase {
|
|
|
66
68
|
}
|
|
67
69
|
|
|
68
70
|
setAttributes(systemPrivilegeAttr: ISystemPrivilegeAttr) {
|
|
71
|
+
this.V1Id = systemPrivilegeAttr.V1Id;
|
|
69
72
|
this.PrivilegeCode = systemPrivilegeAttr.PrivilegeCode;
|
|
70
73
|
this.SystemPrivilegeId = systemPrivilegeAttr.SystemPrivilegeId;
|
|
71
74
|
this.SystemCode = systemPrivilegeAttr.SystemCode;
|
package/src/index.ts
CHANGED
|
@@ -24,6 +24,12 @@ import GroupReportingUserModel from './group-reporting-user.entity';
|
|
|
24
24
|
updatedAt: 'UpdatedAt',
|
|
25
25
|
})
|
|
26
26
|
export default class GroupModel extends Model {
|
|
27
|
+
@Column({
|
|
28
|
+
allowNull: true,
|
|
29
|
+
type: DataType.INTEGER,
|
|
30
|
+
})
|
|
31
|
+
V1Id: number;
|
|
32
|
+
|
|
27
33
|
@Column({
|
|
28
34
|
primaryKey: true,
|
|
29
35
|
allowNull: false,
|
|
@@ -74,7 +80,7 @@ export default class GroupModel extends Model {
|
|
|
74
80
|
|
|
75
81
|
@Column({
|
|
76
82
|
allowNull: false,
|
|
77
|
-
type: DataType.STRING(
|
|
83
|
+
type: DataType.STRING(100),
|
|
78
84
|
})
|
|
79
85
|
Path: string;
|
|
80
86
|
|