@tomei/sso 0.51.8 → 0.51.10

Sign up to get free protection for your applications and to get access to all the features.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tomei/sso",
3
- "version": "0.51.8",
3
+ "version": "0.51.10",
4
4
  "description": "Tomei SSO Package",
5
5
  "main": "dist/index.js",
6
6
  "scripts": {
@@ -754,6 +754,71 @@ export class Group extends TreeNodeBase<Group> {
754
754
  }
755
755
  }
756
756
 
757
+ public static async getSystemAccessRoles(
758
+ loginUser: LoginUser,
759
+ dbTransaction: any,
760
+ SystemCode: string,
761
+ Page: number,
762
+ Rows: number,
763
+ Search: {
764
+ GroupCode?: string;
765
+ Status?: string;
766
+ },
767
+ ) {
768
+ // Part 1: Privilege Checking
769
+ const systemCode = ApplicationConfig.getComponentConfigValue('system-code');
770
+ const isPrivileged = await loginUser.checkPrivileges(
771
+ systemCode,
772
+ 'SYSTEM_ACCESS_VIEW',
773
+ );
774
+
775
+ if (!isPrivileged) {
776
+ throw new ClassError(
777
+ 'Group',
778
+ 'GroupErrMsg06',
779
+ 'You do not have the privilege to view system access',
780
+ );
781
+ }
782
+
783
+ try {
784
+ // Part 2: Retrieve System Access and returns
785
+ const queryObj: any = { SystemCode: SystemCode };
786
+
787
+ if (Search) {
788
+ Object.entries(Search).forEach(([key, value]) => {
789
+ queryObj[key] = value;
790
+ });
791
+ }
792
+
793
+ let options: any = {
794
+ where: queryObj,
795
+ distinct: true,
796
+ transaction: dbTransaction,
797
+ };
798
+
799
+ if (Page && Rows) {
800
+ options = {
801
+ ...options,
802
+ limit: Rows,
803
+ offset: Rows * (Page - 1),
804
+ order: [['CreatedAt', 'DESC']],
805
+ include: {
806
+ model: GroupModel,
807
+ where: {
808
+ Type: 'Role',
809
+ },
810
+ },
811
+ };
812
+ }
813
+
814
+ const systemAccess =
815
+ await Group._GroupSystemAccessRepo.findAndCountAll(options);
816
+ return systemAccess;
817
+ } catch (error) {
818
+ return error;
819
+ }
820
+ }
821
+
757
822
  private static async getInheritedSystemAccess(
758
823
  dbTransaction: any,
759
824
  group: Group,
@@ -1097,6 +1162,175 @@ export class Group extends TreeNodeBase<Group> {
1097
1162
  }
1098
1163
  }
1099
1164
 
1165
+ public static async getSystemPrivilegeRoles(
1166
+ loginUser: LoginUser,
1167
+ dbTransaction: any,
1168
+ SystemCode: string,
1169
+ search?: {
1170
+ GroupCode?: string[];
1171
+ Status?: string;
1172
+ },
1173
+ ) {
1174
+ try {
1175
+ //Part 1: Privilege Checking
1176
+ const systemCode =
1177
+ ApplicationConfig.getComponentConfigValue('system-code');
1178
+ const isPrivileged = await loginUser.checkPrivileges(
1179
+ systemCode,
1180
+ 'GROUP_PRIVILEGE_VIEW',
1181
+ );
1182
+
1183
+ if (!isPrivileged) {
1184
+ throw new ClassError(
1185
+ 'Group',
1186
+ 'GroupErrMsg11',
1187
+ 'You do not have the privilege to view group privileges',
1188
+ );
1189
+ }
1190
+
1191
+ //Part 2: Retrieve Roles Based on Privilege
1192
+ //Retrieve Roles based on privilege on a system
1193
+ let systemWhere: any = {};
1194
+
1195
+ if (search) {
1196
+ if (search.GroupCode.length) {
1197
+ }
1198
+ }
1199
+
1200
+ if (SystemCode) {
1201
+ systemWhere = {
1202
+ SystemCode: {
1203
+ [Op.substring]: SystemCode,
1204
+ },
1205
+ };
1206
+ }
1207
+
1208
+ const groupCodesPrivileges: {
1209
+ SystemPrivilegeId: string;
1210
+ GroupCodes: { Code: string; Name: string }[];
1211
+ }[] = [];
1212
+
1213
+ const allGroupCodePrivileges = await Group._GroupPrivilegeRepo.findAll({
1214
+ include: [
1215
+ {
1216
+ model: SystemPrivilegeModel,
1217
+ where: systemWhere,
1218
+ },
1219
+ {
1220
+ model: GroupModel,
1221
+ where: {
1222
+ Type: 'Role',
1223
+ },
1224
+ },
1225
+ ],
1226
+ transaction: dbTransaction,
1227
+ });
1228
+
1229
+ // Use a Map to group by SystemPrivilegeId
1230
+ const privilegesMap = new Map<string, { Code: string; Name: string }[]>();
1231
+
1232
+ for (const groupCodePrivilege of allGroupCodePrivileges) {
1233
+ const { SystemPrivilegeId, GroupCode, Group } = groupCodePrivilege; // `Group` contains Name from GroupModel
1234
+
1235
+ if (!privilegesMap.has(SystemPrivilegeId)) {
1236
+ // Initialize with an empty array if not already present
1237
+ privilegesMap.set(SystemPrivilegeId, []);
1238
+ }
1239
+
1240
+ // Add the GroupCode and Name to the array if it exists and is not already present
1241
+ if (GroupCode && Group?.Name) {
1242
+ const groupCodes = privilegesMap.get(SystemPrivilegeId);
1243
+ const newGroupEntry = { Code: GroupCode, Name: Group.Name };
1244
+
1245
+ // Ensure no duplicates
1246
+ if (
1247
+ groupCodes &&
1248
+ !groupCodes.some(
1249
+ (g) => g.Code === GroupCode && g.Name === Group.Name,
1250
+ )
1251
+ ) {
1252
+ groupCodes.push(newGroupEntry);
1253
+ }
1254
+ }
1255
+ }
1256
+
1257
+ // Convert the Map to the desired array format
1258
+ privilegesMap.forEach((groupCodes, SystemPrivilegeId) => {
1259
+ groupCodesPrivileges.push({
1260
+ SystemPrivilegeId,
1261
+ GroupCodes: groupCodes,
1262
+ });
1263
+ });
1264
+
1265
+ const allPrivileges = await SystemPrivilegeModel.findAll({
1266
+ where: systemWhere,
1267
+ transaction: dbTransaction,
1268
+ });
1269
+
1270
+ const groupPrivilegeRoles: {
1271
+ SystemPrivilegeId: string;
1272
+ PrivilegeCode: string;
1273
+ Description: string;
1274
+ GroupCodes: { Code: string; Name: string }[];
1275
+ }[] = [];
1276
+
1277
+ // Iterate through allPrivileges to check for matches in groupCodesPrivileges
1278
+ for (const privilege of allPrivileges) {
1279
+ const matchingGroupPrivilege = groupCodesPrivileges.find(
1280
+ (groupPrivilege) =>
1281
+ groupPrivilege.SystemPrivilegeId === privilege.SystemPrivilegeId,
1282
+ );
1283
+
1284
+ if (matchingGroupPrivilege) {
1285
+ // If match is found, push to groupPrivilegeRoles with GroupCodes
1286
+ groupPrivilegeRoles.push({
1287
+ SystemPrivilegeId: privilege.SystemPrivilegeId,
1288
+ PrivilegeCode: privilege.PrivilegeCode,
1289
+ Description: privilege.Description,
1290
+ GroupCodes: matchingGroupPrivilege.GroupCodes,
1291
+ });
1292
+ } else {
1293
+ // If no match is found, push with an empty array of GroupCodes
1294
+ groupPrivilegeRoles.push({
1295
+ SystemPrivilegeId: privilege.SystemPrivilegeId,
1296
+ PrivilegeCode: privilege.PrivilegeCode,
1297
+ Description: privilege.Description,
1298
+ GroupCodes: [],
1299
+ });
1300
+ }
1301
+ }
1302
+
1303
+ const filteredGroupPrivilegeRoles = groupPrivilegeRoles
1304
+ .map((role) => {
1305
+ if (search.GroupCode?.length) {
1306
+ // Filter GroupCodes to only include matching Codes
1307
+ const matchingGroupCodes = role.GroupCodes.filter((groupCode) =>
1308
+ search.GroupCode.includes(groupCode.Code),
1309
+ );
1310
+
1311
+ // If there are no matching GroupCodes, exclude this role
1312
+ if (matchingGroupCodes.length === 0) {
1313
+ return null;
1314
+ }
1315
+
1316
+ // Return the role with filtered GroupCodes
1317
+ return {
1318
+ ...role,
1319
+ GroupCodes: matchingGroupCodes,
1320
+ };
1321
+ }
1322
+
1323
+ // If search.GroupCode is not provided, include all data
1324
+ return role;
1325
+ })
1326
+ .filter(Boolean); // Remove any null values
1327
+
1328
+ return filteredGroupPrivilegeRoles;
1329
+ } catch (error) {
1330
+ throw error;
1331
+ }
1332
+ }
1333
+
1100
1334
  public static async getInheritedSystemPrivileges(
1101
1335
  dbTransaction: any,
1102
1336
  GroupCode: string,
@@ -1,3 +1,4 @@
1
+ import { Op, Transaction } from 'sequelize';
1
2
  import { ClassError, ObjectBase } from '@tomei/general';
2
3
  import { GroupReportingUserRepository } from './group-reporting-user.repository';
3
4
  import { IGroupReportingUserAttr } from '../../interfaces/group-reporting-user.interface';
@@ -6,7 +7,6 @@ import UserModel from '../../models/user.entity';
6
7
  import { Group } from '../group/group';
7
8
  import { ApplicationConfig } from '@tomei/config';
8
9
  import { ActionEnum, Activity } from '@tomei/activity-history';
9
- import { Transaction } from 'sequelize';
10
10
 
11
11
  export class GroupReportingUser extends ObjectBase {
12
12
  ObjectId: string;
@@ -216,6 +216,151 @@ export class GroupReportingUser extends ObjectBase {
216
216
  }
217
217
  }
218
218
 
219
+ async updateGroupReportingUser(
220
+ loginUser: User, //The user performing the operation(typically the logged -in user).
221
+ dbTransaction: any, //Database transaction object to ensure the operation is atomic.
222
+ groupCode: string, //The code of the group to which the user is being assigned.
223
+ userId: number, //The ID of the user to be added to the group.
224
+ rank: number, //The rank to be assigned to the user in the group.
225
+ status: 'Active' | 'Inactive', //The initial status of the user in the group.
226
+ ): Promise<GroupReportingUser> {
227
+ // Returns a GroupReportingUser instance representing the updated record.
228
+ try {
229
+ //Update a group reporting user entry in the sso_GroupReportingUser table.
230
+
231
+ // Validate Input Parameters
232
+ // Ensure groupCode exists in the sso_Group table by calling the Group.init() method.
233
+ await Group.init(dbTransaction, groupCode);
234
+ // Ensure userId exists in the sso_User table by calling the User.init() method.
235
+ await User.init(dbTransaction, userId);
236
+ // Privilege Checking
237
+ // Call the loginUser.checkPrivileges() method by passing:
238
+ // SystemCode: Retrieve from app config.
239
+ // PrivilegeCode: "GROUP_REPORTING_USER_UPDATE".
240
+
241
+ const systemCode =
242
+ ApplicationConfig.getComponentConfigValue('system-code');
243
+ const isPrivileged = await loginUser.checkPrivileges(
244
+ systemCode,
245
+ 'GROUP_REPORTING_USER_CREATE',
246
+ );
247
+ if (!isPrivileged) {
248
+ throw new ClassError(
249
+ 'GroupReportingUser',
250
+ 'GroupReportingUserErrMsg02',
251
+ 'Insufficient privileges to update a user to the group',
252
+ );
253
+ }
254
+
255
+ //Get the current groupReportingUser
256
+ const currentGroupReportingUser = await GroupReportingUser._Repo.findOne({
257
+ where: {
258
+ GroupCode: groupCode,
259
+ GroupReportingUserId: this.GroupReportingUserId,
260
+ },
261
+ transaction: dbTransaction,
262
+ });
263
+
264
+ // Check for Duplicate User in Group
265
+ // Query the sso_GroupReportingUser table to see if the userId already exists in the specified groupCode.
266
+ const groupReportingUser = await GroupReportingUser._Repo.findOne({
267
+ where: {
268
+ GroupCode: groupCode,
269
+ UserId: userId,
270
+ GroupReportingUserId: {
271
+ [Op.ne]: this.GroupReportingUserId,
272
+ },
273
+ },
274
+ transaction: dbTransaction,
275
+ });
276
+ // If the user already exists in the group, throw an error indicating the user is already part of the group.
277
+ if (groupReportingUser) {
278
+ throw new ClassError(
279
+ 'GroupReportingUser',
280
+ 'GroupReportingUserErrMsg03',
281
+ 'User already exists in the group',
282
+ 'updateGroupReportingUser',
283
+ );
284
+ }
285
+ //Query the sso_GroupReportingUser table to see if the rank already exists in the specified groupCode.
286
+ //If the rank already exists in the group, throw an error indicating the rank is already in of the group.
287
+ const groupReportingUserRank = await GroupReportingUser._Repo.findOne({
288
+ where: {
289
+ GroupCode: groupCode,
290
+ Rank: rank,
291
+ GroupReportingUserId: {
292
+ [Op.ne]: this.GroupReportingUserId,
293
+ },
294
+ },
295
+ transaction: dbTransaction,
296
+ });
297
+ if (groupReportingUserRank) {
298
+ throw new ClassError(
299
+ 'GroupReportingUser',
300
+ 'GroupReportingUserErrMsg04',
301
+ 'Rank already exists in the group',
302
+ 'updateGroupReportingUser',
303
+ );
304
+ }
305
+
306
+ // UPDATE GroupReportingUser Entry
307
+ // If validation and privilege checks pass, insert a new record in the sso_GroupReportingUser table with the provided groupCode, userId, rank, status, and loginUser.UserId.Automatically capture the current timestamp for CreatedAt.
308
+ this.GroupCode = groupCode;
309
+ this.UserId = userId;
310
+ this.Rank = rank;
311
+ this.Status = status;
312
+ this._CreatedById = currentGroupReportingUser.CreatedById;
313
+ this._CreatedAt = currentGroupReportingUser.CreatedAt;
314
+ this._UpdatedAt = new Date();
315
+ this._UpdatedById = loginUser.UserId;
316
+
317
+ const entityValueAfter: any = {
318
+ GroupCode: groupCode,
319
+ UserId: userId,
320
+ Rank: rank,
321
+ Status: status,
322
+ CreatedById: currentGroupReportingUser.CreatedById,
323
+ CreatedAt: this._CreatedAt,
324
+ UpdatedById: loginUser.UserId,
325
+ UpdatedAt: this._UpdatedAt,
326
+ };
327
+
328
+ await GroupReportingUser._Repo.update(entityValueAfter, {
329
+ where: {
330
+ GroupReportingUserId: this.GroupReportingUserId,
331
+ },
332
+ transaction: dbTransaction,
333
+ });
334
+
335
+ // Record Update Activity
336
+ // Instantiate a new activity from the Activity class, and set:\
337
+ // ActivityId: activity.createId()
338
+ // Action: ActionEnum.Update
339
+ // Description: Update Group Reporting User
340
+ // EntityType: GroupReportingUser
341
+ // EntityId: newGroupReportingUser.GroupReportingUserId
342
+ // EntityValueBefore: Stringified empty object({})
343
+ // EntityValueAfter: EntityValueAfter(stringified representation of the newly created entity)
344
+ const activity = new Activity();
345
+ activity.ActivityId = activity.createId();
346
+ activity.Action = ActionEnum.UPDATE;
347
+ activity.Description = 'Update Group Reporting User';
348
+ activity.EntityType = 'GroupReportingUser';
349
+ activity.EntityId = this.GroupReportingUserId.toString();
350
+ activity.EntityValueBefore = JSON.stringify({});
351
+ activity.EntityValueAfter = JSON.stringify(entityValueAfter);
352
+ // Call the activity create() method by passing:
353
+ // dbTransaction
354
+ // userId: loginUser.UserId
355
+ await activity.create(loginUser.ObjectId, dbTransaction);
356
+ // Return the Updated GroupReportingUser
357
+ // Return the updated GroupReportingUser instance, including all the relevant details like GroupReportingUserId, groupCode, userId, rank, status, and timestamps for CreatedAt.
358
+ return this;
359
+ } catch (error) {
360
+ throw error;
361
+ }
362
+ }
363
+
219
364
  public static async findAllGroupReportingUsers(
220
365
  loginUser: User, //The authenticated user requesting the information.
221
366
  dbTransaction: any, //The database transaction to be used for this operation.