@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.
@@ -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
- 'sso_APIKey',
8
- {
9
- APIKeyId: {
10
- primaryKey: true,
11
- type: Sequelize.INTEGER,
12
- allowNull: false,
13
- autoIncrement: true,
14
- },
15
- APIKey: {
16
- type: Sequelize.STRING(128),
17
- allowNull: false,
18
- unique: true,
19
- },
20
- Name: {
21
- type: Sequelize.STRING(255),
22
- allowNull: false,
23
- },
24
- Description: {
25
- type: Sequelize.TEXT,
26
- allowNull: true,
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
- RevokedById: {
57
- type: Sequelize.INTEGER,
58
- allowNull: true,
59
- references: {
60
- model: 'sso_User',
61
- key: 'UserId',
62
- },
63
- onDelete: 'CASCADE',
64
- onUpdate: 'CASCADE',
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
- RevokedReason: {
67
- type: Sequelize.TEXT,
68
- defaultValue: 'Active',
69
- allowNull: true,
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tomei/sso",
3
- "version": "0.44.1",
3
+ "version": "0.45.0",
4
4
  "description": "Tomei SSO Package",
5
5
  "main": "dist/index.js",
6
6
  "scripts": {
@@ -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
- const reportingUser: GroupReportingUser[] = [];
268
- if (result.length > 0) {
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.
@@ -4,6 +4,7 @@ export interface IAPIKeyAttr {
4
4
  APIKeyId: number;
5
5
  ApiKey: string;
6
6
  Name: string;
7
+ SystemCode: string;
7
8
  Description: string;
8
9
  Status: APIKeyStatusEnum;
9
10
  ExpirationDate: Date;
@@ -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
  }