@tomei/sso
Version:
Tomei SSO Package
718 lines (656 loc) • 24.7 kB
text/typescript
import { ClassError, ObjectBase } from '@tomei/general';
import { UserSystemAccessRepository } from './user-system-access.repository';
import { IUserSystemAccess } from '../../interfaces/user-system-access.interface';
import { User } from '../login-user/user';
import { ApplicationConfig } from '@tomei/config';
import SystemModel from '../../models/system.entity';
import SystemPrivilegeModel from '../../models/system-privilege.entity';
import UserSystemAccessModel from '../../models/user-system-access.entity';
import GroupModel from '../../models/group.entity';
import GroupSystemAccessModel from '../../models/group-system-access.entity';
import UserModel from '../../models/user.entity';
import { ActionEnum, Activity } from '@tomei/activity-history';
import { Op } from 'sequelize';
import { UserPrivilegeRepository } from '../user-privilege/user-privilege.repository';
import UserGroupModel from 'models/user-group.entity';
import { UserStatus } from '../../enum';
export class UserSystemAccess extends ObjectBase {
ObjectType = 'UserSystemAccess';
TableName = 'sso_UserSystemAccess';
ObjectName: string;
ObjectId: string;
UserSystemAccessId: number;
UserId: number;
SystemCode: string;
Status: string;
private _CreatedAt: Date;
private _UpdatedAt: Date;
private _CreatedById: number;
private _UpdatedById: number;
get CreatedAt() {
return this._CreatedAt;
}
get UpdatedAt() {
return this._UpdatedAt;
}
get CreatedById() {
return this._CreatedById;
}
get UpdatedById() {
return this._UpdatedById;
}
private static _Repository = new UserSystemAccessRepository();
private static _UserPrivilegeRepo = new UserPrivilegeRepository();
private constructor(userSystemAccessAttr?: IUserSystemAccess) {
super();
if (userSystemAccessAttr) {
this.UserSystemAccessId = userSystemAccessAttr.UserSystemAccessId;
this.UserId = userSystemAccessAttr.UserId;
this.SystemCode = userSystemAccessAttr.SystemCode;
this.Status = userSystemAccessAttr.Status;
this._CreatedById = userSystemAccessAttr.CreatedById;
this._CreatedAt = userSystemAccessAttr.CreatedAt;
this._UpdatedById = userSystemAccessAttr.UpdatedById;
this._UpdatedAt = userSystemAccessAttr.UpdatedAt;
}
}
static async init(dbTransaction: any, UserSystemAccessId?: number) {
try {
const userSystemAccess = new UserSystemAccess();
if (UserSystemAccessId) {
const userSystemAccessAttr = await this._Repository.findOne({
where: { UserSystemAccessId },
transaction: dbTransaction,
});
if (userSystemAccessAttr) {
return new UserSystemAccess(
userSystemAccessAttr.get({ plain: true }),
);
} else {
throw new ClassError(
'UserSystemAccess',
'UserSystemAccessErrMsg00',
'UserSystemAccess not found',
);
}
}
return userSystemAccess;
} catch (error) {
throw error;
}
}
public static async findAll(
loginUser: User, //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: {
SystemName: string;
SystemCode: 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_SYSTEM_ACCESS_LIST'.
const systemCode =
ApplicationConfig.getComponentConfigValue('system-code');
const privilegeCode = 'USER_SYSTEM_ACCESS_LIST';
const isPrivileged = await loginUser.checkPrivileges(
systemCode,
privilegeCode,
);
if (!isPrivileged) {
throw new ClassError(
'UserSystemAccess',
'UserSystemAccessErrMsg01',
'You do not have permission to access this resource.',
);
}
// Create a where condition using whereOption to filter by UserId.
// Set up pagination logic using the pagination parameter:
// Calculate offset based on page and limit.
const options: any = {
distinct: true,
where: {
UserId: whereOption.UserId,
},
offset: (pagination.page - 1) * pagination.limit,
limit: pagination.limit,
transaction: dbTransaction,
include: [
{
model: SystemModel,
attributes: ['Name', 'SystemCode'],
},
{
model: UserModel,
as: 'CreatedBy',
attributes: ['FullName'],
},
{
model: UserModel,
as: 'UpdatedBy',
attributes: ['FullName'],
},
],
};
const userSystemAccesses =
await this._Repository.findAllWithPagination(options);
return {
records: userSystemAccesses.rows.map((userSystemAccess) => {
return {
UserSystemAccessId: userSystemAccess.UserSystemAccessId,
SystemName: userSystemAccess.System.Name,
SystemCode: userSystemAccess.System.SystemCode,
Status: userSystemAccess.Status,
CreatedBy: userSystemAccess.CreatedBy.FullName,
CreatedAt: userSystemAccess.CreatedAt,
UpdatedBy: userSystemAccess.UpdatedBy.FullName,
UpdatedAt: userSystemAccess.UpdatedAt,
};
}),
pagination: {
currentPage: pagination.page,
pageSize: pagination.limit,
totalRecords: userSystemAccesses.count,
},
};
} catch (error) {
throw error;
}
}
public static async findAllUsers(
loginUser: User, //The currently logged-in user initiating the request.
dbTransaction: any, //The active database transaction to ensure consistency during the query.
SystemCode: string,
Page: number,
Rows: number,
Search: {
UserId?: string | number;
Status?: string;
},
) {
// Part 1: Privilege Checking
const systemCode = ApplicationConfig.getComponentConfigValue('system-code');
const isPrivileged = await loginUser.checkPrivileges(
systemCode,
'USER_SYSTEM_ACCESS_LIST',
);
if (!isPrivileged) {
throw new ClassError(
'UserSystemAccessUser',
'UserSystemAccessUserErrMsg01',
'You do not have permission to view system access users.',
);
}
try {
// Part 2: Retrieve System Access Users and returns
const queryObj: any = { SystemCode: SystemCode };
if (Search) {
Object.entries(Search).forEach(([key, value]) => {
queryObj[key] = value;
});
}
let options: any = {
where: queryObj,
distinct: true,
transaction: dbTransaction,
};
if (Page && Rows) {
options = {
...options,
limit: Rows,
offset: Rows * (Page - 1),
order: [['CreatedAt', 'DESC']],
include: [
{
model: SystemModel,
attributes: ['Name', 'SystemCode'],
},
{
model: UserModel,
where: {
Status: UserStatus.ACTIVE,
},
as: 'User',
attributes: ['UserId', 'FullName', 'Email'],
},
],
};
}
const userSystemAccesses =
await this._Repository.findAndCountAll(options);
return userSystemAccesses;
} catch (error) {
throw error;
}
}
public static async findAllUserPrivileges(
loginUser: User, //The currently logged-in user initiating the request.
dbTransaction: any, //The active database transaction to ensure consistency during the query.
SystemCode: string,
search?: {
UserId?: string[];
Status?: string;
},
) {
// Part 1: Privilege Checking
const systemCode = ApplicationConfig.getComponentConfigValue('system-code');
const isPrivileged = await loginUser.checkPrivileges(
systemCode,
'USER_SYSTEM_ACCESS_LIST',
);
if (!isPrivileged) {
throw new ClassError(
'UserSystemAccessUser',
'UserSystemAccessUserErrMsg01',
'You do not have permission to view system access users.',
);
}
try {
//Part 2: Retrieve User System Access Based on Privileges
let systemWhere: any = {};
if (SystemCode) {
systemWhere = {
SystemCode: {
[Op.substring]: SystemCode,
},
};
}
const allSystemAccessUsers = await UserSystemAccessModel.findAll({
include: [
{
model: SystemModel,
where: systemWhere,
},
{
model: UserModel,
as: 'User',
attributes: ['UserId', 'FullName'],
},
],
transaction: dbTransaction,
});
const allPrivileges = await SystemPrivilegeModel.findAll({
where: systemWhere,
transaction: dbTransaction,
});
const systemAccessUserPrivileges = allPrivileges.map(
async (privilege) => {
const filteredUsers = allSystemAccessUsers
.map((userAccess) => userAccess.User)
.filter((user) => search.UserId.includes(String(user.UserId)));
return {
...privilege.get({ plain: true }),
Users: filteredUsers,
};
},
);
return systemAccessUserPrivileges;
} catch (error) {
throw error;
}
}
public static async findAllUserRoles(
loginUser: User, //The currently logged-in user initiating the request.
dbTransaction: any, //The active database transaction to ensure consistency during the query.
SystemCode: string,
search?: {
UserId?: string[];
Status?: string;
},
) {
// Part 1: Privilege Checking
const systemCode = ApplicationConfig.getComponentConfigValue('system-code');
const isPrivileged = await loginUser.checkPrivileges(
systemCode,
'USER_SYSTEM_ACCESS_LIST',
);
if (!isPrivileged) {
throw new ClassError(
'UserSystemAccessUser',
'UserSystemAccessUserErrMsg01',
'You do not have permission to view system access users.',
);
}
try {
//Part 2: Retrieve User System Access Based on Privileges
let systemWhere: any = {};
if (SystemCode) {
systemWhere = {
SystemCode: {
[Op.substring]: SystemCode,
},
};
}
const allGroupSystemAccess = await GroupSystemAccessModel.findAll({
where: systemWhere,
include: [
{
model: GroupModel,
where: {
Type: 'Role',
},
},
],
transaction: dbTransaction,
});
const allSystemAccessUsers = await UserSystemAccessModel.findAll({
include: [
{
model: SystemModel,
where: systemWhere,
},
{
model: UserModel,
as: 'User',
attributes: ['UserId', 'FullName'],
},
],
transaction: dbTransaction,
});
const systemAccessUserRoles = allGroupSystemAccess.map(
(groupSystemAccess) => {
const filteredUsers = allSystemAccessUsers
.map((userAccess) => userAccess.User)
.filter((user) => search.UserId.includes(String(user.UserId)));
return {
...groupSystemAccess.Group.get({ plain: true }),
Users: filteredUsers,
};
},
);
return systemAccessUserRoles;
} catch (error) {
throw error;
}
}
public static async createAccess(
loginUser: User, //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.
SystemCode: string, //The system code for which access is being granted.
Status: string, //The status of access ('Active' or 'Inactive').
) {
try {
// Part 1: Privilege Checking:
// Call loginUser.checkPrivileges() method by passing:
// SystemCode: Retrieve from app config.
// PrivilegeCode: 'USER_SYSTEM_ACCESS_CREATE'.
const systemCode =
ApplicationConfig.getComponentConfigValue('system-code');
const privilegeCode = 'USER_SYSTEM_ACCESS_CREATE';
const isPrivileged = await loginUser.checkPrivileges(
systemCode,
privilegeCode,
);
if (!isPrivileged) {
throw new ClassError(
'UserSystemAccess',
'UserSystemAccessErrMsg01',
'You do not have permission to access this resource.',
);
}
// Part 2: Validation for Existing Access
// Use the UserSystemAccess.findAll() method to check if the user already has access to the specified system:
// Pass the following parameters:
// loginUser
// dbTransaction
// whereOption: set to UserId = UserId and SystemCode = SystemCode.
// If a record is found, throw an error indicating that access for this user and system already exists.
const isExist = await UserSystemAccess._Repository.findAll({
where: { [Op.and]: [{ UserId: UserId }, { SystemCode: SystemCode }] },
transaction: dbTransaction,
});
if (isExist?.length > 0) {
throw new ClassError(
'UserSystemAccess',
'UserSystemAccessErrMsg01',
'User already have access to this system',
);
}
// Part 3: Insert System Access Record
// After successful validation, create a new instance of UserSystemAccess with the following fields:
// - UserId: set to the UserId parameter.
// - SystemCode: set to the SystemCode parameter.
// - Status: set to the Status parameter.
// - CreatedById: set to loginUser.UserId.
// - CreatedAt: set to the current timestamp.
// - UpdatedById: set to loginUser.UserId.
// - UpdatedAt: set to the current timestamp (same as CreatedAt).
// Save the new UserSystemAccess instance in the database within the dbTransaction.
const newUserSystemAccess = new UserSystemAccess();
newUserSystemAccess.UserId = parseInt(UserId);
newUserSystemAccess.SystemCode = SystemCode;
newUserSystemAccess.Status = Status;
newUserSystemAccess._CreatedById = loginUser.UserId;
newUserSystemAccess._CreatedAt = new Date();
newUserSystemAccess._UpdatedById = loginUser.UserId;
newUserSystemAccess._UpdatedAt = new Date();
const payload = {
UserId: newUserSystemAccess.UserId,
SystemCode: newUserSystemAccess.SystemCode,
Status: newUserSystemAccess.Status,
CreatedById: newUserSystemAccess.CreatedById,
CreatedAt: newUserSystemAccess.CreatedAt,
UpdatedById: newUserSystemAccess.UpdatedById,
UpdatedAt: newUserSystemAccess.UpdatedAt,
};
const systemAccess = await UserSystemAccess._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 UserSystemAccess instance.
// Create a new activity log entry:
// ActivityId: auto-generated by calling activity.createId().
// Action: set to ActionEnum.Create.
// Description: set to "Create User System Access".
// EntityType: set to UserSystemAccess.
// EntityId: set to the newly created UserSystemAccess.UserSystemAccessId.
// EntityValueBefore: set to {} (empty).
// EntityValueAfter: set to the stringified version of the new access 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 System Access';
activity.EntityType = 'UserSystemAccess';
activity.EntityId = systemAccess.UserSystemAccessId?.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 UserSystemAccess instance with all relevant fields, including UserSystemAccessId, SystemCode, Status, CreatedAt, and CreatedById.
newUserSystemAccess.UserSystemAccessId = systemAccess.UserSystemAccessId;
return newUserSystemAccess;
} catch (error) {
throw error;
}
}
public async update(
loginUser: User, //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 system access.
) {
try {
// Part 1: Update Access
// Call the UserSystemAccess._Repo.update() method to perform the update operation, passing:
// - Status: The new access 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 = {
UserId: this.UserId,
SystemCode: this.SystemCode,
Status: this.Status,
CreatedById: this.CreatedById,
CreatedAt: this.CreatedAt,
UpdatedById: this.UpdatedById,
UpdatedAt: this.UpdatedAt,
};
await UserSystemAccess._Repository.update(
{
Status: Status,
UpdatedById: loginUser.UserId,
UpdatedAt: new Date(),
},
{
where: {
UserSystemAccessId: this.UserSystemAccessId,
},
transaction: dbTransaction,
},
);
const entityValueAfter = {
UserId: this.UserId,
SystemCode: this.SystemCode,
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 system access 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 System Access.
// - EntityType: Set to UserSystemAccess.
// - EntityId: Use the ID of the updated user system access record.
// - EntityValueBefore: Stringify entityValueBefore to capture the state before the update.
// - EntityValueAfter: Stringify the updated user system access 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 System Access';
activity.EntityType = 'UserSystemAccess';
activity.EntityId = this.UserSystemAccessId + '';
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.
// Part 5: Return Newly Created Record
// Return the newly created UserSystemAccess instance with all relevant fields, including UserSystemAccessId, SystemCode, Status, CreatedAt, and CreatedById.
return entityValueAfter;
} catch (error) {
throw error;
}
}
public static async remove(
loginUser: User, //The currently logged-in user initiating the request.
dbTransaction: any, //The active database transaction to ensure consistency during the query.
UserSystemAccessId: number, //The unique identifier of the User System Access record to be deleted.
) {
try {
// Part 1: Privilege Checking
// Call loginUser.checkPrivileges() method by passing:
// - SystemCode: Retrieve from app config.
// - PrivilegeCode: 'USER_SYSTEM_ACCESS_REMOVE'.
// If the user does not have the required privileges, throw an appropriate exception.
const systemCode =
ApplicationConfig.getComponentConfigValue('system-code');
const privilegeCode = 'USER_SYSTEM_ACCESS_REMOVE';
const isPrivileged = await loginUser.checkPrivileges(
systemCode,
privilegeCode,
);
if (!isPrivileged) {
throw new ClassError(
'UserSystemAccess',
'UserSystemAccessErrMsg01',
'You do not have permission to access this resource.',
);
}
// Part 2: Retrieve Record
// Use the UserSystemAccessRepo.findById(UserSystemAccessId) method to retrieve the record.
// If the record does not exist, throw an exception indicating the record was not found.
const userSystemAccess = await UserSystemAccess._Repository.findOne({
where: {
UserSystemAccessId: UserSystemAccessId,
},
transaction: dbTransaction,
});
if (!userSystemAccess) {
throw new ClassError(
'UserSystemAccess',
'UserSystemAccessErrMsg02',
'User System Access not Found',
);
}
// Part 3: Delete Record
// Call the UserSystemAccess._Repo.delete() method, passing:
// - UserSystemAccessId
// dbTransaction to permanently delete the record from the database.
await UserSystemAccess._Repository.delete(
UserSystemAccessId,
dbTransaction,
);
const entityValueBefore = {
UserId: userSystemAccess.UserId,
SystemCode: userSystemAccess.SystemCode,
Status: userSystemAccess.Status,
CreatedById: userSystemAccess.CreatedById,
CreatedAt: userSystemAccess.CreatedAt,
UpdatedById: userSystemAccess.UpdatedById,
UpdatedAt: userSystemAccess.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 System Access
// - EntityType: UserSystemAccess
// - EntityId: UserSystemAccessId
// - 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 System Access';
activity.EntityType = 'UserSystemAccess';
activity.EntityId = UserSystemAccessId?.toString();
activity.EntityValueBefore = JSON.stringify(entityValueBefore);
activity.EntityValueAfter = JSON.stringify({});
//Call Activity.create method
await activity.create(loginUser.ObjectId, dbTransaction);
} catch (error) {
throw error;
}
}
}