UNPKG

@tomei/sso

Version:
663 lines (614 loc) 25.1 kB
import { ClassError, ObjectBase } from '@tomei/general'; import { IUserPrivilegeAttr } from '../../interfaces/user-privilege.interface'; import { UserPrivilegeRepository } from './user-privilege.repository'; import { User as UserClass } from '../login-user/user'; import { ApplicationConfig } from '@tomei/config'; import SystemPrivilegeModel from '../../models/system-privilege.entity'; import SystemModel from '../../models/system.entity'; import { UserGroupRepository } from '../user-group/user-group.repository'; import GroupModel from '../../models/group.entity'; import User from '../../models/user.entity'; import { GroupPrivilegeRepository } from '../group-privilege/group-privilege.repository'; import { User as UserLogin } from '../login-user/user'; import { SystemPrivilegeRepository } from '../system-privilege/system-privilege.repository'; import { Op } from 'sequelize'; import { ActionEnum, Activity } from '@tomei/activity-history'; import { UserGroup } from 'components/user-group'; export class UserPrivilege extends ObjectBase { TableName = 'sso_UserPrivilege'; ObjectType = 'UserPrivilege'; ObjectName: string; ObjectId: string; UserPrivilegeId: number; UserId: number; SystemPrivilegeId: string; Status: string; private _CreatedById: number; private _UpdatedById: number; private _CreatedAt: Date; private _UpdatedAt: Date; get CreatedById(): number { return this._CreatedById; } get UpdatedById(): number { return this._UpdatedById; } get CreatedAt(): Date { return this._CreatedAt; } get UpdatedAt(): Date { return this._UpdatedAt; } private static _Repository = new UserPrivilegeRepository(); private static _UserGroupRepository = new UserGroupRepository(); private static _GroupPrivilegeRepository = new GroupPrivilegeRepository(); private static _SystemPrivilegeRepository = new SystemPrivilegeRepository(); private constructor(userPrivilegeAttr?: IUserPrivilegeAttr) { super(); if (userPrivilegeAttr) { this.UserPrivilegeId = userPrivilegeAttr.UserPrivilegeId; this.UserId = userPrivilegeAttr.UserId; this.SystemPrivilegeId = userPrivilegeAttr.SystemPrivilegeId; this.Status = userPrivilegeAttr.Status; this._CreatedById = userPrivilegeAttr.CreatedById; this._UpdatedById = userPrivilegeAttr.UpdatedById; this._CreatedAt = userPrivilegeAttr.CreatedAt; this._UpdatedAt = userPrivilegeAttr.UpdatedAt; } } public static async init(dbTransaction?: any, UserPrivilegeId?: number) { try { let userPrivilege = new UserPrivilege(); if (UserPrivilegeId) { const userPrivilegeAttr = await this._Repository.findOne({ where: { UserPrivilegeId }, transaction: dbTransaction, }); if (userPrivilegeAttr) { userPrivilege = new UserPrivilege(userPrivilegeAttr); } else { throw new ClassError( 'UserPrivilege', 'UserPrivilegeErrMsg00', 'UserPrivilege not found', ); } } return userPrivilege; } catch (error) { throw error; } } public static async findAll( loginUser: UserClass, //The currently logged-in user initiating the request. dbTransaction: any, //The active database transaction to ensure consistency during the query. whereOption: { //An object containing filter criteria, specifically: UserId: number; //The ID of the user whose system access records are to be retrieved. SystemCode?: string; }, pagination: { //An object containing pagination parameters: page: number; //The current page number to retrieve. limit: number; //The number of records to retrieve per page. }, ): Promise<{ records: { UserPrivilegeId: number; SystemPrivilegeId: string; PrivilegeCode: string; SystemName: string; Status: string; CreatedBy: string; CreatedAt: Date; UpdatedBy: string; UpdatedAt: Date; }[]; pagination: { currentPage: number; pageSize: number; totalRecords: number; }; }> { try { // Privilege Checking: // Call loginUser.checkPrivileges() method by passing: // SystemCode: Retrieve from app config. // PrivilegeCode: 'USER_PRIVILEGE_LIST'. const systemCode = ApplicationConfig.getComponentConfigValue('system-code'); const privilegeCode = 'USER_PRIVILEGE_LIST'; const isPrivileged = await loginUser.checkPrivileges( systemCode, privilegeCode, ); if (!isPrivileged) { throw new ClassError( 'UserPrivilege', 'UserPrivilegeErrMsg01', 'You do not have permission to access this resource.', ); } const options: any = { distinct: true, where: { UserId: whereOption.UserId, }, offset: (pagination.page - 1) * pagination.limit, limit: pagination.limit, transaction: dbTransaction, include: [ { model: SystemPrivilegeModel, attributes: ['PrivilegeCode'], include: [ { model: SystemModel, attributes: ['Name'], }, ], }, { model: User, as: 'CreatedByUser', attributes: ['FullName'], }, { model: User, as: 'UpdatedByUser', attributes: ['FullName'], }, ], }; const { count, rows } = await this._Repository.findAllWithPagination(options); return { records: rows.map((record) => { return { UserPrivilegeId: record.UserPrivilegeId, SystemPrivilegeId: record.SystemPrivilegeId, PrivilegeCode: record.Privilege.PrivilegeCode, SystemName: record.Privilege.System.Name, Status: record.Status, CreatedBy: record.CreatedByUser.FullName, CreatedAt: record.CreatedAt, UpdatedBy: record.UpdatedByUser.FullName, UpdatedAt: record.UpdatedAt, }; }), pagination: { currentPage: pagination.page, pageSize: pagination.limit, totalRecords: count, }, }; } catch (error) { throw error; } } public static async findAllInheritedPrivileges( UserId: number, //The ID of the user for whom privileges are being retrieved. loginUser: UserClass, //The currently logged-in user initiating the request. dbTransaction: any, //The active database transaction to ensure consistency during the query. ) { try { // Part 1: Privilege Checking // Call loginUser.checkPrivileges() to ensure the user has permission to retrieve system access information. // SystemCode: Retrieve from app config. // PrivilegeCode: 'USER_PRIVILEGE_LIST'. // If the privilege check fails, throw an error with a 403 Forbidden status. const systemCode = ApplicationConfig.getComponentConfigValue('system-code'); const privilegeCode = 'USER_PRIVILEGE_LIST'; const isPrivileged = await loginUser.checkPrivileges( systemCode, privilegeCode, ); if (!isPrivileged) { throw new ClassError( 'UserPrivilege', 'UserPrivilegeErrMsg01', 'You do not have permission to access this resource.', ); } // Part 2: Retrieve User Groups // Query the sso_UserGroup table to find all active groups the user belongs to. // Join with the sso_Group table to retrieve the GroupCode, GroupName, and InheritGroupPrivilegeYNfields. // Ensure that the value of InheritGroupPrivilegeYN is explicitly 'Y' or 'N' for each group. // If InheritGroupPrivilegeYN is not set, default it to 'N'. // Return only active groups (based on Status field). // The query should return the following fields for each group: // - GroupCode // - GroupName // - InheritPrivilegeYN const userGroups = await UserPrivilege._UserGroupRepository.findAll({ where: { UserId, }, include: [ { model: GroupModel, attributes: ['GroupCode', 'Name', 'InheritParentPrivilegeYN'], }, ], transaction: dbTransaction, }); const listOfGroups = userGroups.map((groups) => { let inheritPrivilegeYN = groups.InheritGroupPrivilegeYN; if (inheritPrivilegeYN !== 'Y') { inheritPrivilegeYN = 'N'; } return { UserGroupId: groups.UserGroupId, GroupCode: groups.GroupCode, GroupName: groups.Group.Name, InheritPrivilegeYN: inheritPrivilegeYN, Status: groups.Status, }; }); // Part 3: Retrieve System Privilege for Groups with Inheritance // For each group where InheritGroupPrivilegeYN = 'Y', query the sso_GroupPrivilege table to retrieve system privilege details. // Join with the sso_SystemPrivilege table to fetch system details (PrivilegeCode). // Ensure only active group privilege (Status = 'Active') are included. // For each privilege, retrieve the following fields: // - GroupPrivilegeId (from sso_GroupPrivilege.GroupPrivilegeId) // - SystemPrivilegeId (from sso_GroupPrivilege.SystemPrivilegeId) // - PrivilegeCode (from sso_SystemPrivilege.SystemCode) // - Status (from sso_GroupPrivilege.Status) // - CreatedAt (from sso_GroupPrivilege.CreatedAt) // - UpdatedAt (from sso_GroupPrivilege.UpdatedAt) const userGroupPrivilege = []; for (let i = 0; i < listOfGroups.length; i++) { const group = await listOfGroups[i]; const data = { UserGroupId: group.UserGroupId, GroupCode: group.GroupCode, GroupName: group.GroupName, InheritPrivilegeYN: group.InheritPrivilegeYN, systems: [], }; // Part 4: Handling Non-Inherited Groups // For groups where InheritGroupSPrivilegeYN = 'N', return the group details without group privilege records. // Set the Privileges field to an empty array or null to indicate no inherited privilege for those groups. if (group.InheritPrivilegeYN === 'Y') { if (group.Status === 'Active') { const options: any = { where: { GroupCode: group.GroupCode, Status: 'Active', }, transaction: dbTransaction, include: [ { model: SystemPrivilegeModel, attributes: ['PrivilegeCode'], include: [ { model: SystemModel, attributes: ['Name'], }, ], }, { model: User, as: 'CreatedByUser', attributes: ['FullName'], }, { model: User, as: 'UpdatedByUser', attributes: ['FullName'], }, ], }; const systemPrivilege = await this._GroupPrivilegeRepository.findAll(options); const privilegeDetails = systemPrivilege.map((record) => { return { GroupPrivilegeId: record.GroupPrivilegeId, SystemPrivilegeId: record.SystemPrivilegeId, PrivilegeCode: record.Privilege.PrivilegeCode, Status: record.Status, CreatedBy: record.CreatedByUser.FullName, CreatedAt: record.CreatedAt, UpdatedBy: record.UpdatedByUser.FullName, UpdatedAt: record.UpdatedAt, }; }); data.systems = privilegeDetails; } } userGroupPrivilege.push(data); } return userGroupPrivilege; } catch (error) { throw error; } } public static async assignPrivileges( loginUser: UserLogin, //The currently logged-in user initiating the request. dbTransaction: any, //The active database transaction to ensure consistency during the query. UserId: string, //The user ID for whom system access is being created. SystemPrivilegeId: string, //The system code for which access is being granted. Status: string, //The status of access ('Active' or 'Inactive'). ) { try { // Part 1: Privilege Check // Call the LoginUser.checkPrivileges() method to validate if the loginUser has the privilege to create system privilege: // SystemCode: retrieve from the application configuration. // PrivilegeCode: set to "USER_PRIVILEGE_CREATE". // If the user does not have the required privilege, throw an appropriate error. const systemCode = ApplicationConfig.getComponentConfigValue('system-code'); const privilegeCode = 'USER_PRIVILEGE_CREATE'; const isPrivileged = await loginUser.checkPrivileges( systemCode, privilegeCode, ); if (!isPrivileged) { throw new ClassError( 'UserSystemPrivilege', 'UserSystemPrivilegeErrMsg01', 'You do not have permission to access this resource.', ); } // Part 2: Validation // Use UserPrivilege._SystemPrivilegeRepo.findOne method to check if the privileges exist: // Pass the following parameters: // - SystemPrivilegeId // - dbTransaction // If the record is not found, throw an error indicating that privileges don't exist. // Use the UserPrivilege.findAll() method to check if the privileges has been assigned to the user: // Pass the following parameters: // - loginUser // - dbTransaction // - whereOption: set to UserId = UserId and SystemPrivilegeId = SystemPrivilegeId. // If a record is found, throw an error indicating that access for this user and system already exists. const isExist = await UserPrivilege._SystemPrivilegeRepository.findAll({ where: { SystemPrivilegeId: SystemPrivilegeId }, transaction: dbTransaction, }); if (isExist?.length < 1) { throw new ClassError( 'UserSystemPrivilege', 'UserSystemPrivilegeErrMsg02', "system privileges don't exist", ); } const isUserAlreadyAssign = await UserPrivilege._Repository.findAll({ where: { [Op.and]: [ { UserId: UserId }, { SystemPrivilegeId: SystemPrivilegeId }, ], }, transaction: dbTransaction, }); if (isUserAlreadyAssign?.length > 0) { throw new ClassError( 'UserSystemPrivilege', 'UserSystemPrivilegeErrMsg03', 'User already have access to this privilege', ); } // Part 3: Insert User Privilege Record // After successful validation, create a new instance of UserPrivilege with the following fields: // - UserPrivilegeId: set to the result of createId // - SystemPrivilegeId: set to payload.SystemPrivilegeId // - Status: set to payload.Status // - CreatedBy: set to LoginUser.UserId // - CreatedAt: set to the current timestamps // - UpdatedBy: set to LoginUser.UserId // - UpdatedAt: set to the current timestamps // Save the new UserPrivilege instance in the database within the dbTransaction. const newUserPrivilege = new UserPrivilege(); newUserPrivilege.UserId = parseInt(UserId); newUserPrivilege.SystemPrivilegeId = SystemPrivilegeId; newUserPrivilege.Status = Status; newUserPrivilege._CreatedById = loginUser.UserId; newUserPrivilege._CreatedAt = new Date(); newUserPrivilege._UpdatedById = loginUser.UserId; newUserPrivilege._UpdatedAt = new Date(); const payload = { UserId: newUserPrivilege.UserId, SystemPrivilegeId: newUserPrivilege.SystemPrivilegeId, Status: newUserPrivilege.Status, CreatedById: newUserPrivilege.CreatedById, CreatedAt: newUserPrivilege.CreatedAt, UpdatedById: newUserPrivilege.UpdatedById, UpdatedAt: newUserPrivilege.UpdatedAt, }; const userPrivilege = await UserPrivilege._Repository.create(payload, { transaction: dbTransaction, }); // Part 4: Record Activity History // Initialize an empty object ({}) as EntityValueBefore. // Set EntityValueAfter to the stringified version of the newly created UserPrivilege instance. // Create a new activity log entry: // - ActivityId: auto-generated by calling activity.createId(). // - Action: set to ActionEnum.Create. // - Description: set to "Create User Privilege". // - EntityType: set to UserPrivilege. // - EntityId: set to the newly created UserPrivilege.UserPrivilegeId. // - EntityValueBefore: set to {} (empty). // - EntityValueAfter: set to the stringified version of the new record. // Call the activity.create() method, passing: // - dbTransaction // - userId: set to loginUser.UserId. const entityValueBefore = {}; //Instantiate new activity const activity = new Activity(); activity.ActivityId = activity.createId(); activity.Action = ActionEnum.CREATE; activity.Description = 'Create User Privilege'; activity.EntityType = 'UserPrivilege'; activity.EntityId = userPrivilege.UserPrivilegeId?.toString(); activity.EntityValueBefore = JSON.stringify(entityValueBefore); activity.EntityValueAfter = JSON.stringify(payload); //Call Activity.create method await activity.create(loginUser.ObjectId, dbTransaction); // Part 5: Return Newly Created Record // Return the newly created UserPrivilege instance with all relevant fields, including UserPrivilegeId, SystemPrivilegeId, Status, CreatedAt, and CreatedById. newUserPrivilege.UserPrivilegeId = userPrivilege.UserPrivilegeId; return newUserPrivilege; } catch (error) { throw error; } } public async update( loginUser: UserLogin, //The user object representing the currently logged-in user. dbTransaction: any, //The database transaction instance for managing the transaction scope. Status: string, //The new access status (Active/Inactive) for the user privilege ) { try { // Part 1: Update User Privilege // Call the UserPrivilege._Repo.update() method to perform the update operation, passing: // - Status: The new status. // - UpdatedById: loginUser.UserId (to indicate who updated the record). // - UpdatedAt: Set to the current date and time. // - dbTransaction: The database transaction instance. const entityValueBefore = { UserPrivilegeId: this.UserPrivilegeId, UserId: this.UserId, SystemPrivilegeId: this.SystemPrivilegeId, Status: this.Status, CreatedById: this.CreatedById, CreatedAt: this.CreatedAt, UpdatedById: this.UpdatedById, UpdatedAt: this.UpdatedAt, }; await UserPrivilege._Repository.update( { Status: Status, UpdatedById: loginUser.UserId, UpdatedAt: new Date(), }, { where: { UserPrivilegeId: this.UserPrivilegeId, }, transaction: dbTransaction, }, ); const entityValueAfter = { UserPrivilegeId: this.UserPrivilegeId, UserId: this.UserId, SystemPrivilegeId: this.SystemPrivilegeId, Status: Status, CreatedById: this.CreatedById, CreatedAt: this.CreatedAt, UpdatedById: loginUser.UserId, UpdatedAt: new Date(), }; // Part 2: Record Activity History // Initialize a variable entityValueBefore to store the current state of the user privilege record before the update. // Create an instance of the Activity class and set the following properties: // - ActivityId: Call activity.createId(). // - Action: Set to ActionEnum.Update. // - Description: Set to Update User Privilege. // - EntityType: Set to UserPrivilege. // - EntityId: Use the ID of the updated user privilege record. // - EntityValueBefore: Stringify entityValueBefore to capture the state before the update. // - EntityValueAfter: Stringify the updated user privilege record to capture the new state after the update. // Call the activity create method with the following parameters: // - dbTransaction // - userId: loginUser.UserId const activity = new Activity(); activity.ActivityId = activity.createId(); activity.Action = ActionEnum.UPDATE; activity.Description = 'Update User Privilege'; activity.EntityType = 'UserPrivilege'; activity.EntityId = this.SystemPrivilegeId + ''; activity.EntityValueBefore = JSON.stringify(entityValueBefore); activity.EntityValueAfter = JSON.stringify(entityValueAfter); await activity.create(loginUser.ObjectId, dbTransaction); // Part 3: Return Updated Record // Retrieve the updated user system access record from the database or return the updated instance as needed. return entityValueAfter; } catch (error) { throw error; } } public static async remove( loginUser: UserLogin, //The currently logged-in user initiating the request. dbTransaction: any, //The active database transaction to ensure consistency during the query. UserPrivilegeId: number, //The unique identifier of the record to be deleted. ) { try { // Part 1: Privilege Checking // Call loginUser.checkPrivileges() method by passing: // - SystemCode: Retrieve from app config. // - PrivilegeCode: 'USER_PRIVILEGE_REMOVE'. // If the user does not have the required privileges, throw an appropriate exception. const systemCode = ApplicationConfig.getComponentConfigValue('system-code'); const privilegeCode = 'USER_PRIVILEGE_REMOVE'; const isPrivileged = await loginUser.checkPrivileges( systemCode, privilegeCode, ); if (!isPrivileged) { throw new ClassError( 'UserSystemPrivilege', 'UserSystemPrivilegeErrMsg01', 'You do not have permission to access this resource.', ); } // Part 2: Retrieve Record // Use the UserPrivilege._Repo.findById(UserPrivilegeId) method to retrieve the record. // If the record does not exist, throw an exception indicating the record was not found. const userPrivilege = await UserPrivilege._Repository.findOne({ where: { UserPrivilegeId: UserPrivilegeId, }, transaction: dbTransaction, }); if (!userPrivilege) { throw new ClassError( 'UserSystemPrivilege', 'UserSystemPrivilegeErrMsg01', 'User Privilege not Found', ); } // Part 3: Delete Record // Call the UserPrivilege._Repo.delete() method, passing: // - UserPrivilegeId // - dbTransaction to permanently delete the record from the database. await UserPrivilege._Repository.delete(UserPrivilegeId, dbTransaction); const entityValueBefore = { UserId: userPrivilege.UserId, SystemPrivilegeId: userPrivilege.SystemPrivilegeId, Status: userPrivilege.Status, CreatedById: userPrivilege.CreatedById, CreatedAt: userPrivilege.CreatedAt, UpdatedById: userPrivilege.UpdatedById, UpdatedAt: userPrivilege.UpdatedAt, }; // Part 4: Record Activity History // Instantiate a new activity from the Activity class, and set: // - ActivityId: activity.createId() // - Action: ActionEnum.Delete // - Description: Delete User Privilege // - EntityType: UserPrivilege // - EntityId: UserPrivilegeId // - EntityValueBefore: Stringified representation of the record before deletion. // - EntityValueAfter: null. // Call the activity.create() method by passing: // - dbTransaction // - userId: loginUser.UserId. //Instantiate new activity const activity = new Activity(); activity.ActivityId = activity.createId(); activity.Action = ActionEnum.DELETE; activity.Description = 'Delete User Privilege'; activity.EntityType = 'UserPrivilege'; activity.EntityId = UserPrivilegeId?.toString(); activity.EntityValueBefore = JSON.stringify(entityValueBefore); activity.EntityValueAfter = JSON.stringify({}); //Call Activity.create method await activity.create(loginUser.ObjectId, dbTransaction); } catch (error) { throw error; } } }