rowID; //CALL TO API FOR Role Permissions $api_url = '/v2/role_access_permissions/role_id='.$role_id; $permissions = ioServer($api_url,''); //Decode Payload if (!empty($permissions)){$permissions = json_decode($permissions);}else{$permissions = null;} //CALL TO API FOR All Access Elements (no paging) $api_url = '/v2/access_elements/all='; $all_access_elements = ioServer($api_url,''); //Decode Payload if (!empty($all_access_elements)){$all_access_elements = json_decode($all_access_elements);}else{$all_access_elements = null;} // Create lookup array for existing permissions $permission_lookup = []; if (!empty($permissions)){ foreach ($permissions as $perm){ $permission_lookup[$perm->access_id] = $perm; } } //CALL TO API FOR User Role Assignments $api_url = '/v2/user_role_assignments/role_id='.$role_id; $assignments = ioServer($api_url,''); //Decode Payload if (!empty($assignments)){$assignments = json_decode($assignments);}else{$assignments = null;} //CALL TO API FOR All User Roles (for copy dropdown) $api_url = '/v2/user_roles/status=1&all='; $all_roles = ioServer($api_url,''); //Decode Payload if (!empty($all_roles)){$all_roles = json_decode($all_roles);}else{$all_roles = null;} //------------------------------ // Handle POST for inline edit //------------------------------ if (isset($_POST['save_permissions']) && $update_allowed_edit === 1) { // Update role info (name, description, status, system role) $role_data_array = [ 'rowID' => $role_id, 'name' => $_POST['name'] ?? '', 'description' => $_POST['description'] ?? '', 'is_active' => $_POST['is_active'] ?? 1 ]; // Only allow is_system to be changed if user has delete permission on user_roles if ($system_role_allowed === 1) { $role_data_array['is_system'] = isset($_POST['is_system']) ? 1 : 0; } $role_data = json_encode($role_data_array, JSON_UNESCAPED_UNICODE); ioServer('/v2/user_roles', $role_data); // Process permission updates $posted_permissions = $_POST['permissions'] ?? []; // For each access element, update or create permission foreach ($all_access_elements as $element) { $access_id = $element->rowID; $has_permission = isset($posted_permissions[$access_id]); $existing_permission = $permission_lookup[$access_id] ?? null; if ($has_permission) { // Get CRUD values $can_create = isset($posted_permissions[$access_id]['C']) ? 1 : 0; $can_read = isset($posted_permissions[$access_id]['R']) ? 1 : 0; $can_update = isset($posted_permissions[$access_id]['U']) ? 1 : 0; $can_delete = isset($posted_permissions[$access_id]['D']) ? 1 : 0; if ($existing_permission) { // Update existing permission $data = json_encode([ 'rowID' => $existing_permission->rowID, 'role_id' => $role_id, 'access_id' => $access_id, 'can_create' => $can_create, 'can_read' => $can_read, 'can_update' => $can_update, 'can_delete' => $can_delete ], JSON_UNESCAPED_UNICODE); } else { // Insert new permission $data = json_encode([ 'role_id' => $role_id, 'access_id' => $access_id, 'can_create' => $can_create, 'can_read' => $can_read, 'can_update' => $can_update, 'can_delete' => $can_delete ], JSON_UNESCAPED_UNICODE); } ioServer('/v2/role_access_permissions', $data); } else { // If no permission checkboxes selected but had existing permission, delete it if ($existing_permission) { $data = json_encode([ 'rowID' => $existing_permission->rowID, 'delete' => 'delete' ], JSON_UNESCAPED_UNICODE); ioServer('/v2/role_access_permissions', $data); } } } // Redirect to refresh header('Location: index.php?page=user_role&rowID='.$role_id.'&success_msg=2'); exit; } //------------------------------ // Handle POST for delete //------------------------------ if (isset($_POST['delete_role']) && $delete_allowed === 1) { $role_data = json_encode([ 'rowID' => $role_id, 'delete' => 'delete' ], JSON_UNESCAPED_UNICODE); ioServer('/v2/user_roles', $role_data); // Redirect to roles list with success message header('Location: index.php?page='.$_SESSION['origin'].'&success_msg=3'); exit; } //------------------------------ //Variables //------------------------------ $status_text = ($responses->is_active == 1) ? ($enabled ?? 'Active') : ($disabled ?? 'Inactive'); $status_class = ($responses->is_active == 1) ? 'id1' : 'id0'; // Handle success messages if (isset($_GET['success_msg'])) { if ($_GET['success_msg'] == 1) { $success_msg = ($message_role_1 ?? 'Role created successfully'); } if ($_GET['success_msg'] == 2) { $success_msg = ($message_role_2 ?? 'Role updated successfully'); } if ($_GET['success_msg'] == 3) { $success_msg = ($message_role_3 ?? 'Role deleted successfully'); } } template_header(($user_role_title ?? 'User Role'), 'user_role', 'view'); $view = '

'.($view_role_h2 ?? 'User Role').' - '.$responses->name.'

'; if ($update_allowed_edit === 1){ $view .= '✏️'; $view .= ''; } if ($delete_allowed === 1){ $view .= '🗑️'; } $view .= '
'; if (isset($success_msg)){ $view .= '

'.$success_msg.'

'; } // Delete form (hidden) if ($delete_allowed === 1){ $view .= ''; // Delete confirmation modal $view .= ''; } // Start form wrapper for edit mode $view .= '
'; $view .= '
'; // Role Information Block $view .= '
'.($view_role_information ?? 'Role Information').'

'.($general_status ?? 'Status').'

'.$status_text.'

'.($role_name ?? 'Role Name').'

'.$responses->name.'

'.($role_description ?? 'Description').'

'.($responses->description ?? '-').'

'.($role_system ?? 'System Role').'

'.($responses->is_system == 1 ? ' '.($yes ?? 'Yes') : ' '.($no ?? 'No')).' '.($system_role_allowed === 1 ? '' : '').'

'; // Role Assignments Block $view .='
'.($view_role_assignments ?? 'Assigned Users').'
'; if (!empty($assignments)){ foreach ($assignments as $assignment){ $assignment_status = ($assignment->is_active == 1) ? ($enabled ?? 'Active') : ($disabled ?? 'Inactive'); $view .= '

'.$assignment->username.'

'.$assignment_status.((!empty($assignment->expires_at))? ' - '.($expires ?? 'Expires').': '.$assignment->expires_at : '').'

'; } } else { $view .= '

-

'.($no_users_assigned ?? 'No users assigned to this role').'

'; } $view .= '
'; $view .= '
'; // Close content-block-wrapper // Permissions Table Block $view .= '
'.($view_role_permissions ?? 'Role Permissions').'
'; if (!empty($all_access_elements)){ foreach ($all_access_elements as $element){ $access_id = $element->rowID; $existing_perm = $permission_lookup[$access_id] ?? null; // Determine current permission values $has_create = ($existing_perm && $existing_perm->can_create == 1); $has_read = ($existing_perm && $existing_perm->can_read == 1); $has_update = ($existing_perm && $existing_perm->can_update == 1); $has_delete = ($existing_perm && $existing_perm->can_delete == 1); $has_any_permission = ($has_create || $has_read || $has_update || $has_delete); // Row class - hide unassigned rows in view mode $row_class = $has_any_permission ? '' : ' class="edit-only-row" style="display:none;"'; // View mode icons $icon_create = $has_create ? '' : ''; $icon_read = $has_read ? '' : ''; $icon_update = $has_update ? '' : ''; $icon_delete = $has_delete ? '' : ''; // Edit mode checkboxes $cb_create_checked = $has_create ? ' checked' : ''; $cb_read_checked = $has_read ? ' checked' : ''; $cb_update_checked = $has_update ? ' checked' : ''; $cb_delete_checked = $has_delete ? ' checked' : ''; $view .= ' '; } } else { $view .= ''; } $view .= '
'.($access_element_name ?? 'Access Element').' '.($access_element_path ?? 'Path').' '.($access_element_group ?? 'Group').' '.($permission_create ?? 'C').' '.($permission_read ?? 'R').' '.($permission_update ?? 'U').' '.($permission_delete ?? 'D').'
'.$element->access_name.' '.$element->access_path.' '.($element->access_group ?? '-').' '.$icon_create.' '.$icon_read.' '.$icon_update.' '.$icon_delete.'
'.($no_access_elements ?? 'No access elements found').'
'; // Metadata Block $view .= '
'.($tab3 ?? 'Details').'
'.($general_created ?? 'Created').' '.getRelativeTime($responses->created).'
'.($general_updated ?? 'Updated').' '.getRelativeTime($responses->updated).'
'; //OUTPUT echo $view; $js = 'var permissionsEditMode = false; function togglePermissionsEdit() { permissionsEditMode = !permissionsEditMode; var editBtn = document.getElementById("editBtn"); var saveBtn = document.getElementById("saveBtn"); var viewElements = document.querySelectorAll(".view-mode"); var editElements = document.querySelectorAll(".edit-mode"); var editBlockElements = document.querySelectorAll(".edit-mode-block"); var editOnlyRows = document.querySelectorAll(".edit-only-row"); var i; if (permissionsEditMode) { for (i = 0; i < viewElements.length; i++) { viewElements[i].style.display = "none"; } for (i = 0; i < editElements.length; i++) { editElements[i].style.display = "inline"; } for (i = 0; i < editBlockElements.length; i++) { editBlockElements[i].style.display = "block"; } for (i = 0; i < editOnlyRows.length; i++) { editOnlyRows[i].style.display = "table-row"; } editBtn.style.display = "none"; saveBtn.style.display = "inline-block"; } else { for (i = 0; i < viewElements.length; i++) { viewElements[i].style.display = "inline"; } for (i = 0; i < editElements.length; i++) { editElements[i].style.display = "none"; } for (i = 0; i < editBlockElements.length; i++) { editBlockElements[i].style.display = "none"; } for (i = 0; i < editOnlyRows.length; i++) { editOnlyRows[i].style.display = "none"; } editBtn.style.display = "inline-block"; saveBtn.style.display = "none"; } } function toggleColumn(type) { var checkboxes = document.querySelectorAll("input[name$=\\"[" + type + "]\\"]"); var allChecked = true; for (var i = 0; i < checkboxes.length; i++) { if (!checkboxes[i].checked) { allChecked = false; break; } } for (var i = 0; i < checkboxes.length; i++) { checkboxes[i].checked = !allChecked; } } async function copyPermissionsFromRole(roleId) { if (!roleId) return; if (!confirm("'.($confirm_copy_permissions ?? 'This will override all current permission settings. Continue?').'")) { document.getElementById("copyFromRole").value = ""; return; } try { // Call PHP page which will use ioServer to get permissions const response = await fetch("index.php?page=user_role&action=get_role_permissions&source_role_id=" + roleId); if (!response.ok) throw new Error("Failed to fetch"); const permissions = await response.json(); // Create a lookup map of permissions by access_id var permMap = {}; if (permissions && permissions.length > 0) { for (var i = 0; i < permissions.length; i++) { permMap[permissions[i].access_id] = permissions[i]; } } // Get all permission checkboxes and reset them var allCheckboxes = document.querySelectorAll("input[type=checkbox][name^=\\"permissions[\\"]"); for (var i = 0; i < allCheckboxes.length; i++) { allCheckboxes[i].checked = false; } // Apply copied permissions for (var accessId in permMap) { var perm = permMap[accessId]; var cbCreate = document.querySelector("input[name=\\"permissions[" + accessId + "][C]\\"]"); var cbRead = document.querySelector("input[name=\\"permissions[" + accessId + "][R]\\"]"); var cbUpdate = document.querySelector("input[name=\\"permissions[" + accessId + "][U]\\"]"); var cbDelete = document.querySelector("input[name=\\"permissions[" + accessId + "][D]\\"]"); if (cbCreate && perm.can_create == 1) cbCreate.checked = true; if (cbRead && perm.can_read == 1) cbRead.checked = true; if (cbUpdate && perm.can_update == 1) cbUpdate.checked = true; if (cbDelete && perm.can_delete == 1) cbDelete.checked = true; } // Reset dropdown document.getElementById("copyFromRole").value = ""; } catch (error) { console.error("Error copying permissions:", error); alert("'.($error_copy_permissions ?? 'Failed to copy permissions. Please try again.').'"); document.getElementById("copyFromRole").value = ""; } } function confirmDeleteRole() { document.getElementById("deleteModal").style.display = "flex"; } function closeDeleteModal() { document.getElementById("deleteModal").style.display = "none"; } function executeDeleteRole() { document.getElementById("deleteRoleForm").submit(); }'; template_footer($js);