Refactor user permissions handling and enhance menu functionality with collapsible headers
This commit is contained in:
@@ -233,20 +233,19 @@ function routes($urls) {
|
||||
//------------------------------------------
|
||||
// Menu Builder
|
||||
//------------------------------------------
|
||||
/**
|
||||
* @deprecated Use filterMenuByPermissions() instead
|
||||
* Filter menu items based on profile string (legacy)
|
||||
*/
|
||||
function filterMenuByProfile($menu, $profileString) {
|
||||
// Convert profile string to array
|
||||
$profileArray = explode(',', $profileString);
|
||||
|
||||
// Initialize result array
|
||||
$filteredMenu = [];
|
||||
|
||||
// Loop through main menu sections
|
||||
|
||||
foreach ($menu as $sectionKey => $section) {
|
||||
$sectionIncluded = in_array($sectionKey, $profileArray);
|
||||
$submenuFound = false;
|
||||
$firstSubmenuItem = null;
|
||||
|
||||
// First check if any submenu items are in profile
|
||||
|
||||
foreach ($section as $itemKey => $item) {
|
||||
if ($itemKey !== 'main_menu' && in_array($itemKey, $profileArray)) {
|
||||
$submenuFound = true;
|
||||
@@ -255,24 +254,19 @@ function filterMenuByProfile($menu, $profileString) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Include this section if either section key or any submenu is in profile
|
||||
|
||||
if ($sectionIncluded || $submenuFound) {
|
||||
$filteredMenu[$sectionKey] = [];
|
||||
|
||||
// Add main_menu - if section not in profile but submenu found, use first submenu as main_menu
|
||||
|
||||
if (!$sectionIncluded && $submenuFound && $firstSubmenuItem !== null) {
|
||||
// Create hybrid main_menu - keep name and icon from original, but use URL and selected from submenu
|
||||
$hybridMainMenu = $section['main_menu'];
|
||||
$hybridMainMenu['url'] = $firstSubmenuItem['url'];
|
||||
$hybridMainMenu['selected'] = $firstSubmenuItem['selected'];
|
||||
|
||||
$filteredMenu[$sectionKey]['main_menu'] = $hybridMainMenu;
|
||||
} else {
|
||||
$filteredMenu[$sectionKey]['main_menu'] = $section['main_menu'];
|
||||
}
|
||||
|
||||
// Add allowed submenu items
|
||||
|
||||
foreach ($section as $itemKey => $item) {
|
||||
if ($itemKey !== 'main_menu' && in_array($itemKey, $profileArray)) {
|
||||
$filteredMenu[$sectionKey][$itemKey] = $item;
|
||||
@@ -280,17 +274,83 @@ function filterMenuByProfile($menu, $profileString) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return $filteredMenu;
|
||||
}
|
||||
function menu($selected,$selected_child){
|
||||
|
||||
/**
|
||||
* Filter menu items based on user permissions array
|
||||
*
|
||||
* @param array $menu The full menu structure from settingsmenu.php
|
||||
* @param array $permissions The permissions array from $_SESSION['authorization']['permissions']
|
||||
* @return array Filtered menu with only items user has can_read permission for
|
||||
*/
|
||||
function filterMenuByPermissions($menu, $permissions) {
|
||||
$filteredMenu = [];
|
||||
|
||||
foreach ($menu as $sectionKey => $section) {
|
||||
// Get the main_menu's 'selected' path to check permission
|
||||
$mainMenuPath = $section['main_menu']['selected'] ?? $sectionKey;
|
||||
|
||||
// Check if user has read permission for main menu
|
||||
$mainMenuAllowed = isset($permissions[$mainMenuPath]) &&
|
||||
$permissions[$mainMenuPath]['can_read'] == 1;
|
||||
|
||||
$allowedSubmenus = [];
|
||||
$firstAllowedSubmenu = null;
|
||||
|
||||
// Check each submenu item for permission
|
||||
foreach ($section as $itemKey => $item) {
|
||||
if ($itemKey === 'main_menu') {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Get the submenu item's 'selected' path
|
||||
$submenuPath = $item['selected'] ?? $itemKey;
|
||||
|
||||
// Check if user has read permission for this submenu item
|
||||
if (isset($permissions[$submenuPath]) &&
|
||||
$permissions[$submenuPath]['can_read'] == 1) {
|
||||
$allowedSubmenus[$itemKey] = $item;
|
||||
if ($firstAllowedSubmenu === null) {
|
||||
$firstAllowedSubmenu = $item;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Include section if main menu is allowed OR any submenu is allowed
|
||||
if ($mainMenuAllowed || count($allowedSubmenus) > 0) {
|
||||
$filteredMenu[$sectionKey] = [];
|
||||
|
||||
// Handle main_menu entry
|
||||
if (!$mainMenuAllowed && $firstAllowedSubmenu !== null) {
|
||||
// User doesn't have main access but has submenu access
|
||||
// Create hybrid: keep name/icon from main, use URL/selected from first submenu
|
||||
$hybridMainMenu = $section['main_menu'];
|
||||
$hybridMainMenu['url'] = $firstAllowedSubmenu['url'];
|
||||
$hybridMainMenu['selected'] = $firstAllowedSubmenu['selected'];
|
||||
$filteredMenu[$sectionKey]['main_menu'] = $hybridMainMenu;
|
||||
} else {
|
||||
$filteredMenu[$sectionKey]['main_menu'] = $section['main_menu'];
|
||||
}
|
||||
|
||||
// Add allowed submenu items
|
||||
foreach ($allowedSubmenus as $itemKey => $item) {
|
||||
$filteredMenu[$sectionKey][$itemKey] = $item;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $filteredMenu;
|
||||
}
|
||||
function menu($selected, $selected_child){
|
||||
|
||||
include dirname(__FILE__,2).'/settings/settings_redirector.php';
|
||||
|
||||
if(isset($_SESSION['country_code'])){
|
||||
$api_file_language = dirname(__FILE__,2).'/settings/translations/translations_'.strtoupper($_SESSION['country_code']).'.php';
|
||||
if (file_exists($api_file_language)){
|
||||
include $api_file_language; //Include the code
|
||||
if (file_exists($api_file_language)){
|
||||
include $api_file_language;
|
||||
}
|
||||
else {
|
||||
include dirname(__FILE__,2).'/settings/translations/translations_US.php';
|
||||
@@ -298,31 +358,70 @@ function menu($selected,$selected_child){
|
||||
}
|
||||
else {
|
||||
include dirname(__FILE__,2).'/settings/translations/translations_US.php';
|
||||
}
|
||||
|
||||
//Define Menu
|
||||
}
|
||||
|
||||
$menu = '';
|
||||
|
||||
//filter the main_menu array based on profile
|
||||
$filteredMenu = filterMenuByProfile($main_menu, $_SESSION['authorization']['permissions']);
|
||||
// Use permissions array if available, fallback to legacy profile string
|
||||
if (isset($_SESSION['authorization']['permissions']) && !empty($_SESSION['authorization']['permissions'])) {
|
||||
$filteredMenu = filterMenuByPermissions($main_menu, $_SESSION['authorization']['permissions']);
|
||||
} else {
|
||||
$filteredMenu = filterMenuByProfile($main_menu, $_SESSION['authorization']['profile']);
|
||||
}
|
||||
|
||||
foreach ($filteredMenu as $menu_item){
|
||||
//Main Item
|
||||
$menu .= '<a href="index.php?page='.$menu_item['main_menu']['url'].'"' . ($selected == $menu_item['main_menu']['selected'] ? ' class="selected"' : '') . '><i class="'.$menu_item['main_menu']['icon'].'"></i>'.ucfirst((${$menu_item['main_menu']['name']} ?? 'not specified')).'</a>';
|
||||
|
||||
if (count($menu_item) > 1){
|
||||
//SUBMENU
|
||||
$menu .= '<div class="sub" ' . ($selected == $menu_item['main_menu']['selected'] ? ' class="selected"' : '') . '>';
|
||||
foreach ($filteredMenu as $menu_item) {
|
||||
$submenuCount = count($menu_item) - 1; // Exclude main_menu
|
||||
$mainMenu = $menu_item['main_menu'];
|
||||
$menuName = ucfirst((${$mainMenu['name']} ?? ucfirst(str_replace('menu_', '', $mainMenu['name']))));
|
||||
$isMainSelected = ($selected == $mainMenu['selected']);
|
||||
|
||||
foreach ($menu_item as $key => $item){
|
||||
//filter out main_menu
|
||||
if($key !='main_menu'){
|
||||
$menu .= '<a href="index.php?page='.$item['url'].'"' . ($selected == $item['selected'] ? ' class="selected"' : '') . '><span>◼</span>'.ucfirst((${$item['name']}?? 'not specified')).'</a>';
|
||||
// Check if any child is selected (for expanded state)
|
||||
$hasSelectedChild = false;
|
||||
foreach ($menu_item as $key => $item) {
|
||||
if ($key !== 'main_menu' && $selected == $item['selected']) {
|
||||
$hasSelectedChild = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
$menu .= '</div>';
|
||||
}
|
||||
|
||||
if ($submenuCount > 0) {
|
||||
// HAS SUBMENUS: Render as collapsible header (not a link)
|
||||
$expandedClass = ($isMainSelected || $hasSelectedChild) ? ' expanded' : '';
|
||||
$selectedClass = $isMainSelected ? ' selected' : '';
|
||||
|
||||
$menu .= '<div class="menu-header' . $expandedClass . $selectedClass . '" data-section="' . htmlspecialchars($mainMenu['selected']) . '" style="font-size:14px !important;padding:15px 20px !important;cursor:pointer;display:flex;align-items:center;">';
|
||||
$menu .= '<i class="' . $mainMenu['icon'] . '" style="display:inline-block;width:40px;text-align:left;"></i>';
|
||||
$menu .= '<span style="flex:1;">' . $menuName . '</span>';
|
||||
$menu .= '<i class="menu-chevron fas fa-chevron-down" style="font-size:12px;width:20px;text-align:right;"></i>';
|
||||
$menu .= '</div>';
|
||||
|
||||
// SUBMENU container
|
||||
$subExpandedClass = ($isMainSelected || $hasSelectedChild) ? ' expanded' : '';
|
||||
$subDisplayStyle = ($isMainSelected || $hasSelectedChild) ? 'display:flex;' : 'display:none;';
|
||||
$menu .= '<div class="sub' . $subExpandedClass . '" style="' . $subDisplayStyle . 'flex-flow:column;padding:13px 0;">';
|
||||
|
||||
foreach ($menu_item as $key => $item) {
|
||||
if ($key !== 'main_menu') {
|
||||
$itemName = ucfirst((${$item['name']} ?? ucfirst(str_replace('menu_', '', $item['name']))));
|
||||
$itemSelectedClass = ($selected == $item['selected']) ? ' class="selected"' : '';
|
||||
$menu .= '<a href="index.php?page=' . $item['url'] . '"' . $itemSelectedClass . ' style="font-size:14px !important;padding:4px 20px !important;display:flex;align-items:center;">';
|
||||
$menu .= '<span style="display:inline-block;width:40px;font-size:12px;text-align:left;">◼</span>';
|
||||
$menu .= '<span style="flex:1;">' . $itemName . '</span>';
|
||||
$menu .= '</a>';
|
||||
}
|
||||
}
|
||||
$menu .= '</div>';
|
||||
} else {
|
||||
// NO SUBMENUS: Render as direct link
|
||||
$selectedClass = $isMainSelected ? ' class="selected"' : '';
|
||||
$menu .= '<a href="index.php?page=' . $mainMenu['url'] . '"' . $selectedClass . ' style="font-size:14px !important;padding:15px 20px !important;display:flex;align-items:center;">';
|
||||
$menu .= '<i class="' . $mainMenu['icon'] . '" style="display:inline-block;width:40px;text-align:left;"></i>';
|
||||
$menu .= '<span style="flex:1;">' . $menuName . '</span>';
|
||||
$menu .= '<span style="width:20px;"></span>';
|
||||
$menu .= '</a>';
|
||||
}
|
||||
}
|
||||
|
||||
return $menu;
|
||||
}
|
||||
|
||||
@@ -419,19 +518,6 @@ echo <<<EOT
|
||||
|
||||
// Intercept fetch and XMLHttpRequest
|
||||
interceptNetworkRequests();
|
||||
|
||||
|
||||
// Intercept all form submissions
|
||||
function setupFormInterception() {
|
||||
const forms = document.querySelectorAll('form');
|
||||
|
||||
forms.forEach(form => {
|
||||
form.addEventListener('submit', function(e) {
|
||||
// Show loading screen before form submission
|
||||
showLoading();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// Intercept all network requests (fetch and XMLHttpRequest)
|
||||
function interceptNetworkRequests() {
|
||||
@@ -1572,8 +1658,8 @@ function getProfile($profile, $permission){
|
||||
error_log($test, 3, $filelocation);
|
||||
}
|
||||
|
||||
// 1. Check if basic_permission_level is 5 (System) - always allow
|
||||
if ($basic_permission_level !== null && $basic_permission_level == 5) {
|
||||
// 1. Check if basic_permission_level is 4 (System-admin+) - always allow
|
||||
if ($basic_permission_level !== null && $basic_permission_level == 4) {
|
||||
if(debug){
|
||||
$test = "$date - Allowed by system permission (level 5)".PHP_EOL;
|
||||
error_log($test, 3, $filelocation);
|
||||
|
||||
Reference in New Issue
Block a user