@tomei/sso 0.44.1 → 0.45.0
Sign up to get free protection for your applications and to get access to all the features.
- package/dist/src/components/api-key/api-key.d.ts +4 -0
- package/dist/src/components/api-key/api-key.js +9 -0
- package/dist/src/components/api-key/api-key.js.map +1 -1
- package/dist/src/components/group/group.d.ts +4 -0
- package/dist/src/components/group/group.js +34 -0
- package/dist/src/components/group/group.js.map +1 -1
- package/dist/src/components/group-reporting-user/group-reporting-user.d.ts +1 -1
- package/dist/src/components/group-reporting-user/group-reporting-user.js +8 -7
- package/dist/src/components/group-reporting-user/group-reporting-user.js.map +1 -1
- package/dist/src/interfaces/api-key-attr.interface.d.ts +1 -0
- package/dist/src/models/api-key-entity.d.ts +3 -0
- package/dist/src/models/api-key-entity.js +13 -0
- package/dist/src/models/api-key-entity.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/migrations/20240528063108-create-api-key-table.js +70 -63
- package/package.json +1 -1
- package/src/components/api-key/api-key.ts +16 -0
- package/src/components/group/group.ts +63 -1
- package/src/components/group-reporting-user/group-reporting-user.ts +9 -9
- package/src/interfaces/api-key-attr.interface.ts +1 -0
- package/src/models/api-key-entity.ts +11 -0
@@ -3,73 +3,80 @@
|
|
3
3
|
/** @type {import('sequelize-cli').Migration} */
|
4
4
|
module.exports = {
|
5
5
|
async up(queryInterface, Sequelize) {
|
6
|
-
await queryInterface.createTable(
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
Status: {
|
29
|
-
type: Sequelize.STRING(50),
|
30
|
-
defaultValue: 'Active',
|
31
|
-
allowNull: false,
|
32
|
-
},
|
33
|
-
ExpirationDate: {
|
34
|
-
allowNull: false,
|
35
|
-
type: Sequelize.DATE,
|
36
|
-
},
|
37
|
-
CreatedAt: {
|
38
|
-
allowNull: false,
|
39
|
-
defaultValue: Sequelize.literal('CURRENT_TIMESTAMP(3)'),
|
40
|
-
type: Sequelize.DATE,
|
41
|
-
},
|
42
|
-
CreatedById: {
|
43
|
-
type: Sequelize.INTEGER,
|
44
|
-
allowNull: true,
|
45
|
-
references: {
|
46
|
-
model: 'sso_User',
|
47
|
-
key: 'UserId',
|
48
|
-
},
|
49
|
-
onDelete: 'CASCADE',
|
50
|
-
onUpdate: 'CASCADE',
|
51
|
-
},
|
52
|
-
RevokedAt: {
|
53
|
-
allowNull: true,
|
54
|
-
type: Sequelize.DATE,
|
6
|
+
await queryInterface.createTable('sso_APIKey', {
|
7
|
+
APIKeyId: {
|
8
|
+
primaryKey: true,
|
9
|
+
type: Sequelize.INTEGER,
|
10
|
+
allowNull: false,
|
11
|
+
autoIncrement: true,
|
12
|
+
},
|
13
|
+
APIKey: {
|
14
|
+
type: Sequelize.STRING(128),
|
15
|
+
allowNull: false,
|
16
|
+
unique: true,
|
17
|
+
},
|
18
|
+
Name: {
|
19
|
+
type: Sequelize.STRING(255),
|
20
|
+
allowNull: false,
|
21
|
+
},
|
22
|
+
SystemCode: {
|
23
|
+
type: Sequelize.STRING(10),
|
24
|
+
allowNull: false,
|
25
|
+
references: {
|
26
|
+
model: 'sso_System',
|
27
|
+
key: 'SystemCode',
|
55
28
|
},
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
29
|
+
onDelete: 'CASCADE',
|
30
|
+
onUpdate: 'CASCADE',
|
31
|
+
},
|
32
|
+
Description: {
|
33
|
+
type: Sequelize.TEXT,
|
34
|
+
allowNull: true,
|
35
|
+
},
|
36
|
+
Status: {
|
37
|
+
type: Sequelize.STRING(50),
|
38
|
+
defaultValue: 'Active',
|
39
|
+
allowNull: false,
|
40
|
+
},
|
41
|
+
ExpirationDate: {
|
42
|
+
allowNull: false,
|
43
|
+
type: Sequelize.DATE,
|
44
|
+
},
|
45
|
+
CreatedAt: {
|
46
|
+
allowNull: false,
|
47
|
+
defaultValue: Sequelize.literal('CURRENT_TIMESTAMP(3)'),
|
48
|
+
type: Sequelize.DATE,
|
49
|
+
},
|
50
|
+
CreatedById: {
|
51
|
+
type: Sequelize.INTEGER,
|
52
|
+
allowNull: true,
|
53
|
+
references: {
|
54
|
+
model: 'sso_User',
|
55
|
+
key: 'UserId',
|
65
56
|
},
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
57
|
+
onDelete: 'CASCADE',
|
58
|
+
onUpdate: 'CASCADE',
|
59
|
+
},
|
60
|
+
RevokedAt: {
|
61
|
+
allowNull: true,
|
62
|
+
type: Sequelize.DATE,
|
63
|
+
},
|
64
|
+
RevokedById: {
|
65
|
+
type: Sequelize.INTEGER,
|
66
|
+
allowNull: true,
|
67
|
+
references: {
|
68
|
+
model: 'sso_User',
|
69
|
+
key: 'UserId',
|
70
70
|
},
|
71
|
+
onDelete: 'CASCADE',
|
72
|
+
onUpdate: 'CASCADE',
|
73
|
+
},
|
74
|
+
RevokedReason: {
|
75
|
+
type: Sequelize.TEXT,
|
76
|
+
defaultValue: 'Active',
|
77
|
+
allowNull: true,
|
71
78
|
},
|
72
|
-
);
|
79
|
+
});
|
73
80
|
},
|
74
81
|
|
75
82
|
async down(queryInterface, Sequelize) {
|
package/package.json
CHANGED
@@ -7,6 +7,7 @@ import { ApplicationConfig } from '@tomei/config';
|
|
7
7
|
import { randomBytes } from 'crypto';
|
8
8
|
import { ActionEnum, Activity } from '@tomei/activity-history';
|
9
9
|
import { Op } from 'sequelize';
|
10
|
+
import { System } from '../system/system';
|
10
11
|
|
11
12
|
export class APIKey extends ObjectBase {
|
12
13
|
ObjectId: string;
|
@@ -16,6 +17,7 @@ export class APIKey extends ObjectBase {
|
|
16
17
|
|
17
18
|
ApiKey: string;
|
18
19
|
Name: string;
|
20
|
+
SystemCode: string;
|
19
21
|
Description: string;
|
20
22
|
Status: APIKeyStatusEnum;
|
21
23
|
ExpirationDate: Date;
|
@@ -57,6 +59,7 @@ export class APIKey extends ObjectBase {
|
|
57
59
|
this.APIKeyId = apiKeyAttr.APIKeyId;
|
58
60
|
this.ApiKey = apiKeyAttr.ApiKey;
|
59
61
|
this.Name = apiKeyAttr.Name;
|
62
|
+
this.SystemCode = apiKeyAttr.SystemCode;
|
60
63
|
this.Description = apiKeyAttr.Description;
|
61
64
|
this.Status = apiKeyAttr.Status;
|
62
65
|
this.ExpirationDate = apiKeyAttr.ExpirationDate;
|
@@ -114,6 +117,12 @@ export class APIKey extends ObjectBase {
|
|
114
117
|
);
|
115
118
|
}
|
116
119
|
|
120
|
+
// Part 3: System Existence Check
|
121
|
+
// Call System.init(dbTransaction, this.SystemCode) to verify the System exists.
|
122
|
+
// If the group does not exist, throw a NotFoundError.
|
123
|
+
|
124
|
+
await System.init(dbTransaction, this.SystemCode);
|
125
|
+
|
117
126
|
// Part 3: Generate API Key
|
118
127
|
// Populate the following attributes:
|
119
128
|
// CreatedById: Set to loginUser.UserId.
|
@@ -133,6 +142,7 @@ export class APIKey extends ObjectBase {
|
|
133
142
|
const EntityValueAfter: any = {
|
134
143
|
ApiKey: this.ApiKey,
|
135
144
|
Name: this.Name,
|
145
|
+
SystemCode: this.SystemCode,
|
136
146
|
Status: this.Status,
|
137
147
|
Description: this.Description,
|
138
148
|
ExpirationDate: this.ExpirationDate,
|
@@ -188,6 +198,7 @@ export class APIKey extends ObjectBase {
|
|
188
198
|
Name: this.Name,
|
189
199
|
Status: this.Status,
|
190
200
|
Description: this.Description,
|
201
|
+
SystemCode: this.SystemCode,
|
191
202
|
ExpirationDate: this.ExpirationDate,
|
192
203
|
CreatedAt: this.CreatedAt,
|
193
204
|
CreatedById: this.CreatedById,
|
@@ -205,6 +216,7 @@ export class APIKey extends ObjectBase {
|
|
205
216
|
loginUser: LoginUser,
|
206
217
|
dbTransaction: any,
|
207
218
|
whereOptions: {
|
219
|
+
SystemCode?: string;
|
208
220
|
Status?: APIKeyStatusEnum;
|
209
221
|
ExpirationDate?: {
|
210
222
|
FromDate: Date;
|
@@ -246,6 +258,9 @@ export class APIKey extends ObjectBase {
|
|
246
258
|
// CreatedById: Filter by the user who created the API key.
|
247
259
|
const where = {};
|
248
260
|
if (whereOptions) {
|
261
|
+
if (whereOptions.SystemCode) {
|
262
|
+
where['SystemCode'] = whereOptions.SystemCode;
|
263
|
+
}
|
249
264
|
if (whereOptions.Status) {
|
250
265
|
where['Status'] = whereOptions.Status;
|
251
266
|
}
|
@@ -311,6 +326,7 @@ export class APIKey extends ObjectBase {
|
|
311
326
|
ApiKeyId: row.APIKeyId,
|
312
327
|
ApiKey: row.ApiKey,
|
313
328
|
Name: row.Name,
|
329
|
+
SystemCode: row.SystemCode,
|
314
330
|
Description: row.Description,
|
315
331
|
Status: row.Status,
|
316
332
|
ExpirationDate: row.ExpirationDate,
|
@@ -5,7 +5,7 @@ import { GroupTypeEnum } from 'enum';
|
|
5
5
|
import { LoginUser } from '../login-user/login-user';
|
6
6
|
import { IGroupSearchAttr } from '../../interfaces/group-search-attr.interface';
|
7
7
|
import { ApplicationConfig } from '@tomei/config';
|
8
|
-
import { Op } from 'sequelize';
|
8
|
+
import { Op, Transaction } from 'sequelize';
|
9
9
|
import { ActionEnum, Activity } from '@tomei/activity-history';
|
10
10
|
import { GroupSystemAccessRepository } from '../group-system-access/group-system-access.repository';
|
11
11
|
import SystemModel from '../../models/system.entity';
|
@@ -18,6 +18,10 @@ import GroupPrivilegeModel from '../../models/group-privilege.entity';
|
|
18
18
|
import { GroupObjectPrivilegeRepository } from '../group-object-privilege/group-object-privilege.repository';
|
19
19
|
import { GroupObjectPrivilege } from '../group-object-privilege/group-object-privilege';
|
20
20
|
import { GroupPrivilege } from '../group-privilege/group-privilege';
|
21
|
+
import { User } from '../login-user/user';
|
22
|
+
import GroupReportingUserModel from '../../models/group-reporting-user.entity';
|
23
|
+
import GroupModel from '../../models/group.entity';
|
24
|
+
import UserModel from '../../models/user.entity';
|
21
25
|
|
22
26
|
export class Group extends TreeNodeBase<Group> {
|
23
27
|
ObjectId: string;
|
@@ -1900,4 +1904,62 @@ export class Group extends TreeNodeBase<Group> {
|
|
1900
1904
|
return tree;
|
1901
1905
|
}
|
1902
1906
|
}
|
1907
|
+
|
1908
|
+
public static async getGroupsWithReportingUser(
|
1909
|
+
loginUser: User, //The user performing the action.
|
1910
|
+
dbTransaction: Transaction, //Active database transaction.
|
1911
|
+
whereOptions: any, //The filter criteria for selecting groups.
|
1912
|
+
) {
|
1913
|
+
try {
|
1914
|
+
// Part 1: Privilege Checking
|
1915
|
+
// Call loginUser.checkPrivileges() by passing:
|
1916
|
+
// SystemCode: Retrieve from app config.
|
1917
|
+
// PrivilegeCode: 'GROUP_VIEW'.
|
1918
|
+
const systemCode =
|
1919
|
+
ApplicationConfig.getComponentConfigValue('system-code');
|
1920
|
+
const isPrivileged = await loginUser.checkPrivileges(
|
1921
|
+
systemCode,
|
1922
|
+
'GROUP_VIEW',
|
1923
|
+
);
|
1924
|
+
if (!isPrivileged) {
|
1925
|
+
throw new ClassError(
|
1926
|
+
'Group',
|
1927
|
+
'GroupErrMsg04',
|
1928
|
+
'User is not privileged to view group',
|
1929
|
+
);
|
1930
|
+
}
|
1931
|
+
// Part 2: Prepare Group Query
|
1932
|
+
// Call Group._Repo.findAll() to fetch groups from the sso_Group table by passing:
|
1933
|
+
// where: whereOptions
|
1934
|
+
// include:
|
1935
|
+
// Model: sso_GroupReportingUsers
|
1936
|
+
// where: { Status: 'Active' }
|
1937
|
+
// include:
|
1938
|
+
// Model: sso_User
|
1939
|
+
// attributes: ['UserId', 'FullName']
|
1940
|
+
// attributes: ['GroupCode', 'UserId', 'Rank']
|
1941
|
+
const options = {
|
1942
|
+
where: whereOptions,
|
1943
|
+
include: [
|
1944
|
+
{
|
1945
|
+
model: GroupReportingUserModel,
|
1946
|
+
where: { Status: 'Active' },
|
1947
|
+
include: [
|
1948
|
+
{
|
1949
|
+
model: UserModel,
|
1950
|
+
attributes: ['UserId', 'FullName'],
|
1951
|
+
},
|
1952
|
+
],
|
1953
|
+
},
|
1954
|
+
],
|
1955
|
+
transaction: dbTransaction,
|
1956
|
+
};
|
1957
|
+
const groups = await Group._Repo.findAll(options);
|
1958
|
+
// Part 3: Retrieve and Return
|
1959
|
+
// Return the list of groups with nested reporting users.
|
1960
|
+
return groups;
|
1961
|
+
} catch (error) {
|
1962
|
+
throw error;
|
1963
|
+
}
|
1964
|
+
}
|
1903
1965
|
}
|
@@ -2,6 +2,7 @@ import { ClassError, ObjectBase } from '@tomei/general';
|
|
2
2
|
import { GroupReportingUserRepository } from './group-reporting-user.repository';
|
3
3
|
import { IGroupReportingUserAttr } from '../../interfaces/group-reporting-user.interface';
|
4
4
|
import { User } from '../login-user/user';
|
5
|
+
import UserModel from '../../models/user.entity';
|
5
6
|
import { Group } from '../group/group';
|
6
7
|
import { ApplicationConfig } from '@tomei/config';
|
7
8
|
import { ActionEnum, Activity } from '@tomei/activity-history';
|
@@ -256,6 +257,12 @@ export class GroupReportingUser extends ObjectBase {
|
|
256
257
|
where: {
|
257
258
|
GroupCode: groupCode,
|
258
259
|
},
|
260
|
+
include: [
|
261
|
+
{
|
262
|
+
model: UserModel,
|
263
|
+
as: 'User',
|
264
|
+
},
|
265
|
+
],
|
259
266
|
order: [
|
260
267
|
['Rank', 'ASC'], // or 'DESC' for descending order
|
261
268
|
],
|
@@ -264,15 +271,8 @@ export class GroupReportingUser extends ObjectBase {
|
|
264
271
|
|
265
272
|
// Part 4: Return Results
|
266
273
|
// Return the array of GroupReportingUser records found.
|
267
|
-
|
268
|
-
|
269
|
-
for (let i = 0; i < result.length; i++) {
|
270
|
-
reportingUser.push(
|
271
|
-
new GroupReportingUser(result[i].get({ plain: true })),
|
272
|
-
);
|
273
|
-
}
|
274
|
-
}
|
275
|
-
return reportingUser;
|
274
|
+
|
275
|
+
return result;
|
276
276
|
} catch (error) {
|
277
277
|
// Part 5: Handle Errors
|
278
278
|
// Catch and handle any errors during the execution. If an error occurs, ensure the transaction is rolled back.
|
@@ -10,6 +10,7 @@ import {
|
|
10
10
|
} from 'sequelize-typescript';
|
11
11
|
import User from './user.entity';
|
12
12
|
import { APIKeyStatusEnum } from '../enum/api-key.enum';
|
13
|
+
import SystemModel from './system.entity';
|
13
14
|
|
14
15
|
@Table({
|
15
16
|
tableName: 'sso_ApiKey',
|
@@ -37,6 +38,13 @@ export default class APIKeyModel extends Model {
|
|
37
38
|
})
|
38
39
|
Name: string;
|
39
40
|
|
41
|
+
@ForeignKey(() => SystemModel)
|
42
|
+
@Column({
|
43
|
+
allowNull: false,
|
44
|
+
type: DataType.STRING(10),
|
45
|
+
})
|
46
|
+
SystemCode: string;
|
47
|
+
|
40
48
|
@Column({
|
41
49
|
type: DataType.TEXT,
|
42
50
|
allowNull: true,
|
@@ -87,4 +95,7 @@ export default class APIKeyModel extends Model {
|
|
87
95
|
|
88
96
|
@BelongsTo(() => User, 'RevokedById')
|
89
97
|
UpdatedByUser: User;
|
98
|
+
|
99
|
+
@BelongsTo(() => SystemModel, 'SystemCode')
|
100
|
+
System: SystemModel;
|
90
101
|
}
|