830 lines
24 KiB
TypeScript
830 lines
24 KiB
TypeScript
/**
|
|
* Copyright since 2025 Mifos Initiative
|
|
*
|
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
*/
|
|
|
|
/** Angular Imports */
|
|
import { Component, OnInit, inject } from '@angular/core';
|
|
import { UntypedFormBuilder, UntypedFormGroup, Validators, FormArray, ReactiveFormsModule } from '@angular/forms';
|
|
import { MatDialog } from '@angular/material/dialog';
|
|
import { ActivatedRoute, Router } from '@angular/router';
|
|
import * as _ from 'lodash';
|
|
import { SystemService } from '../../system.service';
|
|
|
|
/** Custom Components */
|
|
import { TranslateService } from '@ngx-translate/core';
|
|
import { DeleteDialogComponent } from '../../../shared/delete-dialog/delete-dialog.component';
|
|
import { DisableDialogComponent } from '../../../shared/disable-dialog/disable-dialog.component';
|
|
import { EnableDialogComponent } from '../../../shared/enable-dialog/enable-dialog.component';
|
|
import { FaIconComponent } from '@fortawesome/angular-fontawesome';
|
|
import { MatCheckbox } from '@angular/material/checkbox';
|
|
import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
|
|
import { AlertService } from 'app/core/alert/alert.service';
|
|
|
|
/** Custom Service Zitadel */
|
|
import { environment } from '../../../../environments/environment';
|
|
import { AuthService } from 'app/zitadel/auth.service';
|
|
|
|
/**
|
|
* View Role and Permissions Component
|
|
*/
|
|
@Component({
|
|
selector: 'mifosx-view-role',
|
|
templateUrl: './view-role.component.html',
|
|
styleUrls: ['./view-role.component.scss'],
|
|
imports: [
|
|
...STANDALONE_SHARED_IMPORTS,
|
|
FaIconComponent,
|
|
MatCheckbox
|
|
]
|
|
})
|
|
export class ViewRoleComponent implements OnInit {
|
|
private route = inject(ActivatedRoute);
|
|
private systemService = inject(SystemService);
|
|
private router = inject(Router);
|
|
private formBuilder = inject(UntypedFormBuilder);
|
|
private translateService = inject(TranslateService);
|
|
dialog = inject(MatDialog);
|
|
private authService = inject(AuthService);
|
|
private alertService = inject(AlertService);
|
|
|
|
/** Role Permissions Data */
|
|
rolePermissionService: any;
|
|
/** Stores the current grouping */
|
|
currentGrouping: string;
|
|
/** Stores the previous grouping */
|
|
previousGrouping = '';
|
|
/** Stores Grouping Data */
|
|
groupings: string[] = [];
|
|
/** Stores the selected role */
|
|
selectedItem = '';
|
|
/** Grouped categories for sidebar */
|
|
roleGroups: { name: string; icon: string; categories: string[]; expanded: boolean }[] = [];
|
|
/** Mapping of category groupings to role groups */
|
|
private categoryToGroupMap: { [key: string]: string } = {
|
|
// Special & Authorisation
|
|
special: 'Special & Authorisation',
|
|
authorisation: 'Special & Authorisation',
|
|
|
|
// Configuration & Admin
|
|
configuration: 'Configuration & Admin',
|
|
organisation: 'Configuration & Admin',
|
|
datatable: 'Configuration & Admin',
|
|
jobs: 'Configuration & Admin',
|
|
|
|
// Portfolio — Client, Loan, Savings, FD, RD, Guarantor etc.
|
|
portfolio: 'Portfolio',
|
|
portfolio_group: 'Portfolio — Groups & Centers',
|
|
portfolio_center: 'Portfolio — Groups & Centers',
|
|
|
|
// Transactions
|
|
transaction_loan: 'Transactions — Loan',
|
|
transaction_savings: 'Transactions — Savings',
|
|
transaction_shareaccount: 'Transactions — Share Account',
|
|
|
|
// Accounting & Finance
|
|
accounting: 'Accounting & Finance',
|
|
loan_provisioning: 'Accounting & Finance',
|
|
loan_reschedule: 'Accounting & Finance',
|
|
|
|
// Cash Management
|
|
cash_mgmt: 'Cash Management',
|
|
|
|
// Reporting
|
|
report: 'Reporting & Analytics',
|
|
|
|
// Share Account
|
|
shareaccount: 'Share Account',
|
|
|
|
// Heading Menu (Top Navigation Bar)
|
|
heading_menu: 'Heading Menu',
|
|
|
|
// Left Panel Menu (Sidebar)
|
|
sidebar_menu: 'Left Panel Menu'
|
|
};
|
|
private groupIcons: { [key: string]: string } = {
|
|
'Special & Authorisation': 'fa-star',
|
|
'Configuration & Admin': 'fa-cog',
|
|
Portfolio: 'fa-briefcase',
|
|
'Portfolio — Groups & Centers': 'fa-users',
|
|
'Transactions — Loan': 'fa-exchange-alt',
|
|
'Transactions — Savings': 'fa-piggy-bank',
|
|
'Transactions — Share Account': 'fa-share-alt',
|
|
'Accounting & Finance': 'fa-calculator',
|
|
'Cash Management': 'fa-cash-register',
|
|
'Reporting & Analytics': 'fa-chart-bar',
|
|
'Share Account': 'fa-chart-pie',
|
|
'Heading Menu': 'fa-th-list',
|
|
'Left Panel Menu': 'fa-bars'
|
|
};
|
|
/** Checks if its disabled */
|
|
isDisabled: Boolean = true;
|
|
/** Checks if there is any change in data */
|
|
checkboxesChanged: Boolean = false;
|
|
/** Stores backup values */
|
|
bValuesOnly: string[] = [];
|
|
/** Role ID */
|
|
roleId: any;
|
|
/** Creates permission form */
|
|
formGroup: UntypedFormGroup;
|
|
/** Creates Backup form */
|
|
backupform: UntypedFormGroup;
|
|
/** Temporarily stores Permission data */
|
|
tempPermissionUIData: {
|
|
[key: string]: {
|
|
permissions: { code: string; id: number; selected?: boolean }[];
|
|
};
|
|
} = {};
|
|
/** Stores permissions */
|
|
permissions: {
|
|
permissions: { code: string; id: number }[];
|
|
} = { permissions: [] };
|
|
/** Sub-grouped permissions for large categories */
|
|
permissionSubGroups: {
|
|
entity: string;
|
|
makerPerms: { code: string; id: number }[];
|
|
checkerPerms: { code: string; id: number }[];
|
|
expanded: boolean;
|
|
}[] = [];
|
|
/** Flat maker/checker split for small categories */
|
|
flatMakerPerms: { code: string; id: number }[] = [];
|
|
flatCheckerPerms: { code: string; id: number }[] = [];
|
|
/** Threshold for sub-grouping */
|
|
subGroupThreshold = 30;
|
|
/** Add role zitadel */
|
|
|
|
/**
|
|
* Retrieves the roledetails data from `resolve`.
|
|
* @param {ActivatedRoute} route Activated Route.
|
|
* @param {SystemService} systemService System Service.
|
|
* @param {Router} router Router for navigation.
|
|
* @param {FormBuilder} formBuilder Form Builder.
|
|
* @param {MatDialog} dialog Shared Dialog Boxes.
|
|
* @param {TranslateService} translateService Translate Service.
|
|
*/
|
|
constructor() {
|
|
this.route.data.subscribe((data: { roledetails: any }) => {
|
|
this.rolePermissionService = data.roledetails;
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Groups all the data on init
|
|
*/
|
|
ngOnInit() {
|
|
this.permissions = {
|
|
permissions: []
|
|
};
|
|
this.createForm();
|
|
this.groupRules();
|
|
this.buildRoleGroups();
|
|
this.selectedItem = 'special';
|
|
this.showPermissions('special');
|
|
this.route.params.subscribe((routeParams: any) => {
|
|
this.roleId = routeParams.id;
|
|
});
|
|
}
|
|
|
|
/**
|
|
* creates the form to display and edit permissions
|
|
*/
|
|
createForm() {
|
|
this.formGroup = this.formBuilder.group({
|
|
roster: this.formBuilder.array(
|
|
this.rolePermissionService.permissionUsageData.map((elem: any) => this.createMemberGroup(elem))
|
|
)
|
|
});
|
|
}
|
|
|
|
createMemberGroup(permission: any): UntypedFormGroup {
|
|
return this.formBuilder.group({
|
|
...permission,
|
|
...{
|
|
code: [
|
|
permission.code,
|
|
Validators.required
|
|
],
|
|
selected: [
|
|
{ value: permission.selected, disabled: true },
|
|
Validators.required
|
|
]
|
|
}
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Groups the permissions based on rules
|
|
*/
|
|
groupRules() {
|
|
this.tempPermissionUIData = {};
|
|
for (const i in this.rolePermissionService.permissionUsageData) {
|
|
if (this.rolePermissionService.permissionUsageData[i]) {
|
|
if (this.rolePermissionService.permissionUsageData[i].grouping !== this.currentGrouping) {
|
|
this.currentGrouping = this.rolePermissionService.permissionUsageData[i].grouping;
|
|
this.groupings.push(this.currentGrouping);
|
|
this.tempPermissionUIData[this.currentGrouping] = { permissions: [] };
|
|
}
|
|
const temp = {
|
|
code: this.rolePermissionService.permissionUsageData[i].code,
|
|
id: +i,
|
|
selected: this.rolePermissionService.permissionUsageData[i].selected
|
|
};
|
|
this.tempPermissionUIData[this.currentGrouping].permissions.push(temp);
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Builds role groups from flat groupings
|
|
*/
|
|
buildRoleGroups() {
|
|
const groupMap: { [key: string]: string[] } = {};
|
|
for (const g of this.groupings) {
|
|
const groupName = this.categoryToGroupMap[g] || 'Other';
|
|
if (!groupMap[groupName]) {
|
|
groupMap[groupName] = [];
|
|
}
|
|
groupMap[groupName].push(g);
|
|
}
|
|
const order = [
|
|
'Special & Authorisation',
|
|
'Configuration & Admin',
|
|
'Portfolio',
|
|
'Portfolio — Groups & Centers',
|
|
'Transactions — Loan',
|
|
'Transactions — Savings',
|
|
'Transactions — Share Account',
|
|
'Accounting & Finance',
|
|
'Cash Management',
|
|
'Reporting & Analytics',
|
|
'Share Account',
|
|
'Heading Menu',
|
|
'Left Panel Menu',
|
|
'Other'
|
|
];
|
|
this.roleGroups = order
|
|
.filter((name) => groupMap[name])
|
|
.map((name) => ({
|
|
name,
|
|
icon: this.groupIcons[name] || 'fa-folder',
|
|
categories: groupMap[name],
|
|
expanded: name === 'Special & Authorisation'
|
|
}));
|
|
}
|
|
|
|
toggleGroup(group: any) {
|
|
group.expanded = !group.expanded;
|
|
}
|
|
|
|
selectAllGroup(group: any) {
|
|
const roster = this.formGroup.get('roster') as FormArray;
|
|
for (const cat of group.categories) {
|
|
const perms = this.tempPermissionUIData[cat]?.permissions || [];
|
|
for (const p of perms) {
|
|
roster.at(p.id).patchValue({ selected: true });
|
|
}
|
|
}
|
|
}
|
|
|
|
deselectAllGroup(group: any) {
|
|
const roster = this.formGroup.get('roster') as FormArray;
|
|
for (const cat of group.categories) {
|
|
const perms = this.tempPermissionUIData[cat]?.permissions || [];
|
|
for (const p of perms) {
|
|
roster.at(p.id).patchValue({ selected: false });
|
|
}
|
|
}
|
|
}
|
|
|
|
selectAllCategory(cat: string) {
|
|
const roster = this.formGroup.get('roster') as FormArray;
|
|
const perms = this.tempPermissionUIData[cat]?.permissions || [];
|
|
for (const p of perms) {
|
|
roster.at(p.id).patchValue({ selected: true });
|
|
}
|
|
}
|
|
|
|
deselectAllCategory(cat: string) {
|
|
const roster = this.formGroup.get('roster') as FormArray;
|
|
const perms = this.tempPermissionUIData[cat]?.permissions || [];
|
|
for (const p of perms) {
|
|
roster.at(p.id).patchValue({ selected: false });
|
|
}
|
|
}
|
|
|
|
getGroupPermCount(group: any): number {
|
|
let count = 0;
|
|
for (const cat of group.categories) {
|
|
count += this.tempPermissionUIData[cat]?.permissions?.length || 0;
|
|
}
|
|
return count;
|
|
}
|
|
|
|
getCatPermCount(cat: string): number {
|
|
return this.tempPermissionUIData[cat]?.permissions?.length || 0;
|
|
}
|
|
|
|
/** Entity display names */
|
|
private entityNames: { [key: string]: string } = {
|
|
CLIENT: 'Client',
|
|
CLIENTIMAGE: 'Client Image',
|
|
CLIENTIDENTIFIER: 'Client Identifier',
|
|
CLIENTNOTE: 'Client Note',
|
|
CLIENTCHARGE: 'Client Charge',
|
|
LOAN: 'Loan',
|
|
LOANNOTE: 'Loan Note',
|
|
LOANCHARGE: 'Loan Charge',
|
|
LOANTRANSACTIONNOTE: 'Loan Transaction Note',
|
|
SAVINGSACCOUNT: 'Savings Account',
|
|
SAVINGSACCOUNTCHARGE: 'Savings Account Charge',
|
|
SAVINGNOTE: 'Savings Note',
|
|
FIXEDDEPOSITACCOUNT: 'Fixed Deposit Account',
|
|
RECURRINGDEPOSITACCOUNT: 'Recurring Deposit Account',
|
|
SHAREACCOUNT: 'Share Account',
|
|
GROUP: 'Group',
|
|
GROUPNOTE: 'Group Note',
|
|
CENTER: 'Center',
|
|
GUARANTOR: 'Guarantor',
|
|
COLLATERAL: 'Collateral',
|
|
DOCUMENT: 'Document',
|
|
ACCOUNTTRANSFER: 'Account Transfer',
|
|
STANDINGINSTRUCTION: 'Standing Instruction',
|
|
RESCHEDULELOAN: 'Reschedule Loan',
|
|
JOURNALENTRY: 'Journal Entry',
|
|
TELLER: 'Teller',
|
|
CASHIER: 'Cashier',
|
|
ROLE: 'Role',
|
|
USER: 'User',
|
|
PERMISSION: 'Permission',
|
|
CODE: 'Code',
|
|
CODEVALUE: 'Code Value',
|
|
OFFICE: 'Office',
|
|
OFFICETRANSACTION: 'Office Transaction',
|
|
STAFF: 'Staff',
|
|
STAFFIMAGE: 'Staff Image',
|
|
CHARGE: 'Charge',
|
|
FUND: 'Fund',
|
|
LOANPRODUCT: 'Loan Product',
|
|
SAVINGSPRODUCT: 'Savings Product',
|
|
FIXEDDEPOSITPRODUCT: 'Fixed Deposit Product',
|
|
RECURRINGDEPOSITPRODUCT: 'Recurring Deposit Product',
|
|
SHAREPRODUCT: 'Share Product',
|
|
CURRENCY: 'Currency',
|
|
DATATABLE: 'Data Table',
|
|
CALENDAR: 'Calendar',
|
|
CONFIGURATION: 'Configuration',
|
|
AUDIT: 'Audit',
|
|
REPORT: 'Report',
|
|
HOOK: 'Hook',
|
|
TEMPLATE: 'Template',
|
|
PAYMENTTYPE: 'Payment Type',
|
|
HOLIDAY: 'Holiday',
|
|
WORKINGDAYS: 'Working Days',
|
|
GLACCOUNT: 'GL Account',
|
|
GLCLOSURE: 'GL Closure',
|
|
FINANCIALACTIVITYACCOUNT: 'Financial Activity Account',
|
|
TAXCOMPONENT: 'Tax Component',
|
|
TAXGROUP: 'Tax Group',
|
|
PRODUCTMIX: 'Product Mix',
|
|
EXTERNALSERVICES: 'External Services',
|
|
SCHEDULER: 'Scheduler',
|
|
MEETING: 'Meeting',
|
|
INTERESTRATECHART: 'Interest Rate Chart',
|
|
FLOATINGRATE: 'Floating Rate',
|
|
ACCOUNTNUMBERFORMAT: 'Account Number Format',
|
|
ACCOUNTINGRULE: 'Accounting Rule',
|
|
ENTITYMAPPING: 'Entity Mapping',
|
|
PROVISION: 'Provisioning',
|
|
REPORTMAILINGJOB: 'Report Mailing Job',
|
|
PASSWORD_PREFERENCES: 'Password Preferences',
|
|
ADDRESS: 'Address',
|
|
CACHE: 'Cache'
|
|
};
|
|
|
|
/**
|
|
* Extracts entity name from permission code (e.g., CREATE_CLIENT -> CLIENT)
|
|
*/
|
|
private extractEntity(code: string): string {
|
|
// Common action prefixes to strip
|
|
const actions = [
|
|
'CREATE',
|
|
'READ',
|
|
'UPDATE',
|
|
'DELETE',
|
|
'APPROVE',
|
|
'REJECT',
|
|
'ACTIVATE',
|
|
'DEACTIVATE',
|
|
'CLOSE',
|
|
'DEPOSIT',
|
|
'WITHDRAWAL',
|
|
'WITHDRAW',
|
|
'DISBURSE',
|
|
'DISBURSETOSAVINGS',
|
|
'DISBURSALUNDO',
|
|
'DISBURSALLASTUNDO',
|
|
'REPAYMENT',
|
|
'ADJUST',
|
|
'WAIVE',
|
|
'WAIVEINTERESTPORTION',
|
|
'WRITEOFF',
|
|
'UNDOWRITEOFF',
|
|
'UNDOAPPROVAL',
|
|
'UNDOTRANSACTION',
|
|
'UNDO',
|
|
'CLOSEASRESCHEDULED',
|
|
'FORECLOSURE',
|
|
'REOPEN',
|
|
'REACTIVATE',
|
|
'POSTINTEREST',
|
|
'CALCULATEINTEREST',
|
|
'APPLYANNUALFEE',
|
|
'PREMATURECLOSE',
|
|
'UPDATEDEPOSITAMOUNT',
|
|
'WITHDRAWWITHHELD',
|
|
'UPDATELOANOFFICER',
|
|
'REMOVELOANOFFICER',
|
|
'BULKREASSIGN',
|
|
'REFUNDBYCASH',
|
|
'REFUNDBYTRANSFER',
|
|
'RECOVERGUARANTEES',
|
|
'RECOVERYPAYMENT',
|
|
'CREATESCHEDULEEXCEPTIONS',
|
|
'DELETESCHEDULEEXCEPTIONS',
|
|
'UPDATERUNNINGBALANCE',
|
|
'DEFINEOPENINGBALANCE',
|
|
'REVERSE',
|
|
'REGISTER',
|
|
'DEREGISTER',
|
|
'ENABLE',
|
|
'DISABLE',
|
|
'PERMISSIONS',
|
|
'INACTIVATE',
|
|
'PAY',
|
|
'PROPOSETRANSFER',
|
|
'ACCEPTTRANSFER',
|
|
'REJECTTRANSFER',
|
|
'WITHDRAWTRANSFER',
|
|
'ASSIGNSTAFF',
|
|
'UNASSIGNSTAFF',
|
|
'ASSIGNROLE',
|
|
'UPDATEROLE',
|
|
'DISASSOCIATECLIENTS',
|
|
'ASSOCIATECLIENTS',
|
|
'TRANSFERCLIENTS',
|
|
'ASSOCIATEGROUPS',
|
|
'DISASSOCIATEGROUPS',
|
|
'ALLOCATECASHIER',
|
|
'ALLOCATECASHTOCASHIER',
|
|
'SETTLECASHFROMCASHIER',
|
|
'EXECUTEJOB',
|
|
'EXECUTE',
|
|
'DIVIDEND',
|
|
'APPLYADDITIONALSHARES',
|
|
'APPROVEADDITIONALSHARES',
|
|
'REJECTADDITIONALSHARES',
|
|
'REDEEMSHARES'
|
|
];
|
|
|
|
// Try to match action_entity pattern
|
|
for (const action of actions) {
|
|
if (code.startsWith(action + '_')) {
|
|
const entity = code.substring(action.length + 1);
|
|
// Remove _CHECKER suffix
|
|
return entity.replace(/_CHECKER$/, '');
|
|
}
|
|
}
|
|
// Fallback: return the code itself
|
|
return code.replace(/_CHECKER$/, '');
|
|
}
|
|
|
|
private isChecker(code: string): boolean {
|
|
return code.endsWith('_CHECKER');
|
|
}
|
|
|
|
/**
|
|
* Splits permissions into maker/checker for flat display
|
|
*/
|
|
buildFlatMakerChecker() {
|
|
const perms = this.permissions.permissions;
|
|
this.flatMakerPerms = perms.filter((p) => !this.isChecker(p.code));
|
|
this.flatCheckerPerms = perms.filter((p) => this.isChecker(p.code));
|
|
}
|
|
|
|
/**
|
|
* Builds sub-groups for permissions in the current category
|
|
*/
|
|
buildSubGroups() {
|
|
const perms = this.permissions.permissions;
|
|
this.buildFlatMakerChecker();
|
|
|
|
if (perms.length <= this.subGroupThreshold) {
|
|
this.permissionSubGroups = [];
|
|
return;
|
|
}
|
|
|
|
const groups: {
|
|
[entity: string]: { maker: { code: string; id: number }[]; checker: { code: string; id: number }[] };
|
|
} = {};
|
|
for (const p of perms) {
|
|
const entity = this.extractEntity(p.code);
|
|
if (!groups[entity]) {
|
|
groups[entity] = { maker: [], checker: [] };
|
|
}
|
|
if (this.isChecker(p.code)) {
|
|
groups[entity].checker.push(p);
|
|
} else {
|
|
groups[entity].maker.push(p);
|
|
}
|
|
}
|
|
|
|
this.permissionSubGroups = Object.keys(groups).map((entity) => ({
|
|
entity,
|
|
makerPerms: groups[entity].maker,
|
|
checkerPerms: groups[entity].checker,
|
|
expanded: false
|
|
}));
|
|
}
|
|
|
|
getEntityDisplayName(entity: string): string {
|
|
return this.entityNames[entity] || entity.replace(/_/g, ' ');
|
|
}
|
|
|
|
toggleSubGroup(subGroup: any) {
|
|
subGroup.expanded = !subGroup.expanded;
|
|
}
|
|
|
|
selectAllSubGroup(subGroup: any) {
|
|
const roster = this.formGroup.get('roster') as FormArray;
|
|
for (const p of [
|
|
...subGroup.makerPerms,
|
|
...subGroup.checkerPerms
|
|
]) {
|
|
roster.at(p.id).patchValue({ selected: true });
|
|
}
|
|
}
|
|
|
|
deselectAllSubGroup(subGroup: any) {
|
|
const roster = this.formGroup.get('roster') as FormArray;
|
|
for (const p of [
|
|
...subGroup.makerPerms,
|
|
...subGroup.checkerPerms
|
|
]) {
|
|
roster.at(p.id).patchValue({ selected: false });
|
|
}
|
|
}
|
|
|
|
getSubGroupCount(subGroup: any): number {
|
|
return subGroup.makerPerms.length + subGroup.checkerPerms.length;
|
|
}
|
|
|
|
selectAllMaker(perms: { code: string; id: number }[]) {
|
|
const roster = this.formGroup.get('roster') as FormArray;
|
|
for (const p of perms) {
|
|
roster.at(p.id).patchValue({ selected: true });
|
|
}
|
|
}
|
|
|
|
deselectAllMaker(perms: { code: string; id: number }[]) {
|
|
const roster = this.formGroup.get('roster') as FormArray;
|
|
for (const p of perms) {
|
|
roster.at(p.id).patchValue({ selected: false });
|
|
}
|
|
}
|
|
|
|
selectAllChecker(perms: { code: string; id: number }[]) {
|
|
const dialogRef = this.dialog.open(EnableDialogComponent, {
|
|
data: {
|
|
enableContext: this.translateService.instant(
|
|
'labels.text.all Checker permissions for this section. This grants approval authority'
|
|
)
|
|
}
|
|
});
|
|
dialogRef.afterClosed().subscribe((response: any) => {
|
|
if (response?.enable) {
|
|
const roster = this.formGroup.get('roster') as FormArray;
|
|
for (const p of perms) {
|
|
roster.at(p.id).patchValue({ selected: true });
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
deselectAllChecker(perms: { code: string; id: number }[]) {
|
|
const roster = this.formGroup.get('roster') as FormArray;
|
|
for (const p of perms) {
|
|
roster.at(p.id).patchValue({ selected: false });
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Displays the permission for selected role
|
|
* @param grouping Selected Role
|
|
*/
|
|
showPermissions(grouping: string) {
|
|
this.permissions = this.tempPermissionUIData[grouping];
|
|
this.selectedItem = grouping;
|
|
this.previousGrouping = grouping;
|
|
this.buildSubGroups();
|
|
}
|
|
|
|
/**
|
|
* Formats the Role Name
|
|
* @param string String
|
|
*/
|
|
formatName(string: string) {
|
|
if (!string) {
|
|
return string;
|
|
}
|
|
// Try to translate first
|
|
const translationKey = `labels.catalogs.${string}`;
|
|
const translated = this.translateService.instant(translationKey);
|
|
|
|
// If translation exists (and is different from key), use it
|
|
if (translated && translated !== translationKey) {
|
|
return translated;
|
|
}
|
|
|
|
// Otherwise, format the original string
|
|
if (string.indexOf('portfolio_') > -1) {
|
|
string = string.replace('portfolio_', '');
|
|
}
|
|
if (string.indexOf('transaction_') > -1) {
|
|
const temp = string.split('_');
|
|
string = temp[1] + ' ' + temp[0].charAt(0).toUpperCase() + temp[0].slice(1) + 's';
|
|
}
|
|
string = string.charAt(0).toUpperCase() + string.slice(1);
|
|
return string;
|
|
}
|
|
|
|
/**
|
|
* Formats the permission from permission code
|
|
* @param name String
|
|
*/
|
|
permissionName(name: any) {
|
|
name = name || '';
|
|
// replace '_' with ' '
|
|
name = name.replace(/_/g, ' ');
|
|
// for reports replace read with view
|
|
if (this.previousGrouping === 'report') {
|
|
name = name.replace(/READ/g, 'View');
|
|
}
|
|
return name;
|
|
}
|
|
|
|
/**
|
|
* Backups the values
|
|
*/
|
|
backupCheckValues() {
|
|
this.backupform = _.cloneDeep(this.formGroup) as UntypedFormGroup;
|
|
}
|
|
|
|
/**
|
|
* Restores the checkboxes to previous data on clicking cancel
|
|
*/
|
|
restoreCheckboxes() {
|
|
this.formGroup = _.cloneDeep(this.backupform) as UntypedFormGroup;
|
|
}
|
|
|
|
isRoleEnable(value: any) {
|
|
return value;
|
|
}
|
|
|
|
editRoles() {
|
|
this.isDisabled = false;
|
|
this.formGroup.controls.roster.enable();
|
|
}
|
|
|
|
/**
|
|
* Cancel the changes
|
|
*/
|
|
cancel() {
|
|
this.isDisabled = true;
|
|
this.formGroup.controls.roster.disable();
|
|
}
|
|
|
|
/**
|
|
* Submits the modified permissions
|
|
*/
|
|
submit() {
|
|
const value = this.formGroup.get('roster').value;
|
|
const data: { [key: string]: boolean } = {};
|
|
const permissionData = {
|
|
permissions: {}
|
|
};
|
|
for (let i = 0; i < value.length; i++) {
|
|
data[value[i].code] = value[i].selected;
|
|
}
|
|
permissionData.permissions = data;
|
|
this.formGroup.controls.roster.disable();
|
|
this.checkboxesChanged = false;
|
|
this.isDisabled = true;
|
|
this.systemService.updateRolePermission(this.roleId, permissionData).subscribe((response: any) => {
|
|
if (response?.rollbackTransaction) {
|
|
this.alertService.alert({
|
|
type: 'Success',
|
|
message: 'Role permissions update request submitted successfully for approval.'
|
|
});
|
|
}
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Selects all the permission of a particular role
|
|
*/
|
|
selectAll() {
|
|
const roster = this.formGroup.get('roster') as FormArray;
|
|
for (let i = 0; i < this.permissions.permissions.length; i++) {
|
|
roster.at(this.permissions.permissions[i].id).patchValue({
|
|
selected: true
|
|
});
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Deselects all the permissions of a particular role
|
|
*/
|
|
deselectAll() {
|
|
const roster = this.formGroup.get('roster') as FormArray;
|
|
for (let i = 0; i < this.permissions.permissions.length; i++) {
|
|
roster.at(this.permissions.permissions[i].id).patchValue({
|
|
selected: false
|
|
});
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Deletes the Role and redirects to Roles and Permissions.
|
|
*/
|
|
deleteRole() {
|
|
const deleteRoleDialogRef = this.dialog.open(DeleteDialogComponent, {
|
|
data: { deleteContext: this.translateService.instant('labels.inputs.Role') + ' ' + this.roleId }
|
|
});
|
|
deleteRoleDialogRef.afterClosed().subscribe((response: any) => {
|
|
if (response.delete) {
|
|
this.systemService.deleteRole(this.roleId).subscribe((res: any) => {
|
|
if (res?.rollbackTransaction) {
|
|
this.alertService.alert({
|
|
type: 'Success',
|
|
message: 'Role deletion request submitted successfully for approval.'
|
|
});
|
|
} else if (environment.OIDC.oidcServerEnabled) {
|
|
this.authService.deleteRole(this.roleId);
|
|
}
|
|
this.router.navigate(['/system/roles-and-permissions']);
|
|
});
|
|
} else {
|
|
}
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Enables the Role and redirects to Roles and Permissions.
|
|
*/
|
|
enableRolesConfirmation() {
|
|
const enableRoleDialogRef = this.dialog.open(EnableDialogComponent, {
|
|
data: { enableContext: this.translateService.instant('labels.inputs.Role') + ' ' + this.roleId }
|
|
});
|
|
enableRoleDialogRef.afterClosed().subscribe((response: any) => {
|
|
if (response.enable) {
|
|
this.systemService.enableRole(this.roleId).subscribe((res: any) => {
|
|
if (res?.rollbackTransaction) {
|
|
this.alertService.alert({
|
|
type: 'Success',
|
|
message: 'Role enablement request submitted successfully for approval.'
|
|
});
|
|
}
|
|
this.router.navigate(['/system/roles-and-permissions']);
|
|
});
|
|
} else {
|
|
}
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Disables the Role and redirects to Roles and Permissions.
|
|
*/
|
|
disableRolesConfirmation() {
|
|
const deleteRoleDialogRef = this.dialog.open(DisableDialogComponent, {
|
|
data: { disableContext: this.translateService.instant('labels.inputs.Role') + ' ' + this.roleId }
|
|
});
|
|
deleteRoleDialogRef.afterClosed().subscribe((response: any) => {
|
|
if (response.disable) {
|
|
this.systemService.disableRole(this.roleId).subscribe((res: any) => {
|
|
if (res?.rollbackTransaction) {
|
|
this.alertService.alert({
|
|
type: 'Success',
|
|
message: 'Role disablement request submitted successfully for approval.'
|
|
});
|
|
}
|
|
this.router.navigate(['/system/roles-and-permissions']);
|
|
});
|
|
} else {
|
|
}
|
|
});
|
|
}
|
|
}
|