diff --git a/.DS_Store b/.DS_Store index 9d4c452..555e5f6 100644 Binary files a/.DS_Store and b/.DS_Store differ diff --git a/api/v0/get/user_credentials.php b/api/v0/get/user_credentials.php index 09062c9..6168639 100644 --- a/api/v0/get/user_credentials.php +++ b/api/v0/get/user_credentials.php @@ -15,7 +15,7 @@ $user_data = $stmt->fetch(); //Define User data $partnerhierarchy = $user_data['partnerhierarchy']; $permission = userRights($user_data['view']); -$profile= getProfile($user_data['settings'],$permission); +$profile= getUserPermissions($pdo, $user_data['id']); $username = $user_data['username']; $useremail = $user_data['email']; $servicekey = $user_data['service']; diff --git a/api/v1/get/user_credentials.php b/api/v1/get/user_credentials.php index 3f98774..f7fa705 100644 --- a/api/v1/get/user_credentials.php +++ b/api/v1/get/user_credentials.php @@ -17,7 +17,7 @@ if ($stmt->rowCount() == 1) { //Define User data $partnerhierarchy = $user_data['partnerhierarchy']; $permission = userRights($user_data['view']); - $profile= getProfile($user_data['settings'],$permission); + $profile= getUserPermissions($pdo, $user_data['id']); $username = $user_data['username']; $useremail = $user_data['email']; $servicekey = $user_data['service']; diff --git a/api/v2/get/history.php b/api/v2/get/history.php index e433d1d..9994a48 100644 --- a/api/v2/get/history.php +++ b/api/v2/get/history.php @@ -34,6 +34,7 @@ switch ($permission) { //NEW ARRAY $criterias = []; $clause = ''; +$type_check = false; //Check for $_GET variables and build up clause if(isset($get_content) && $get_content!=''){ @@ -117,6 +118,7 @@ if(isset($get_content) && $get_content!=''){ //add new_querystring to clause $clause .= ' AND h.type IN ('.$new_querystring.')'; //remove original key/value from array + $type_check = true; unset($criterias[$v[0]]); } else { @@ -142,6 +144,9 @@ if(isset($criterias['totals']) && $criterias['totals'] ==''){ //Request for total rows $sql ='SELECT count(h.rowID) as historyID FROM equipment_history h LEFT JOIN equipment e ON h.equipmentid = e.rowID '.$whereclause.''; } +elseif($type_check){ + $sql ='SELECT h.rowID as historyID, e.rowID as equipmentID, e.serialnumber, h.type, h.description, h.created, h.createdby FROM equipment_history h LEFT JOIN equipment e ON h.equipmentid = e.rowID '.$whereclause.' ORDER BY h.created DESC'; +} else { //request history $sql ='SELECT h.rowID as historyID, e.rowID as equipmentID, e.serialnumber, h.type, h.description, h.created, h.createdby FROM equipment_history h LEFT JOIN equipment e ON h.equipmentid = e.rowID '.$whereclause.' ORDER BY h.created DESC LIMIT :page,:num_products'; @@ -178,6 +183,12 @@ if(isset($criterias['totals']) && $criterias['totals']==''){ $messages = $stmt->fetch(); $messages = $messages[0]; } +elseif($type_check){ + //Excute Query + $stmt->execute(); + //Get results + $messages = $stmt->fetchAll(PDO::FETCH_ASSOC); +} else { $current_page = isset($criterias['p']) && is_numeric($criterias['p']) ? (int)$criterias['p'] : 1; $stmt->bindValue('page', ($current_page - 1) * $page_rows_history, PDO::PARAM_INT); diff --git a/api/v2/get/software_update.php b/api/v2/get/software_update.php index 883e6a9..98f7cb9 100644 --- a/api/v2/get/software_update.php +++ b/api/v2/get/software_update.php @@ -239,7 +239,6 @@ if (isset($criterias['sn']) && $criterias['sn'] != ''){ JOIN products_software_versions psv ON psa.software_version_id = psv.rowID WHERE psa.product_id = ? AND psa.status = 1 - AND psv.latest = 1 AND (psv.hw_version = ? OR psv.hw_version IS NULL OR psv.hw_version = "")'; $stmt = $pdo->prepare($sql); diff --git a/api/v2/post/access_elements.php b/api/v2/post/access_elements.php index 9b06726..e2d768d 100644 --- a/api/v2/post/access_elements.php +++ b/api/v2/post/access_elements.php @@ -25,12 +25,12 @@ $criterias = []; //ADD STANDARD PARAMETERS TO ARRAY BASED ON INSERT OR UPDATE if ($command == 'update'){ - $post_content['updatedby'] = $username;; + $post_content['updatedby'] = $username; $post_content['updated'] = $date; } elseif ($command == 'insert'){ $post_content['created'] = $date; - $post_content['createdby'] = $username;; + $post_content['createdby'] = $username; } //CREAT NEW ARRAY AND MAP TO CLAUSE diff --git a/assets/admin.js b/assets/admin.js index 27f2927..31e7cde 100644 --- a/assets/admin.js +++ b/assets/admin.js @@ -20,6 +20,66 @@ document.querySelector('.responsive-toggle').onclick = event => { localStorage.setItem('admin_menu', 'closed'); } }; + +// Menu header collapse/expand functionality +document.querySelectorAll('aside .menu-header').forEach(header => { + header.addEventListener('click', function(event) { + event.preventDefault(); + + // Toggle expanded state + this.classList.toggle('expanded'); + + // Find the next sibling .sub element and toggle display + const submenu = this.nextElementSibling; + if (submenu && submenu.classList.contains('sub')) { + submenu.classList.toggle('expanded'); + // Update inline style for display + submenu.style.display = submenu.classList.contains('expanded') ? 'flex' : 'none'; + } + + // Rotate chevron + const chevron = this.querySelector('.menu-chevron'); + if (chevron) { + chevron.style.transform = this.classList.contains('expanded') ? 'rotate(180deg)' : 'rotate(0deg)'; + } + + // Store expanded state in localStorage for persistence + const section = this.dataset.section; + if (section) { + const expandedSections = JSON.parse(localStorage.getItem('menu_expanded') || '{}'); + expandedSections[section] = this.classList.contains('expanded'); + localStorage.setItem('menu_expanded', JSON.stringify(expandedSections)); + } + }); +}); + +// Restore menu expanded states from localStorage on page load +(function restoreMenuState() { + const expandedSections = JSON.parse(localStorage.getItem('menu_expanded') || '{}'); + + document.querySelectorAll('aside .menu-header').forEach(header => { + const section = header.dataset.section; + const submenu = header.nextElementSibling; + const chevron = header.querySelector('.menu-chevron'); + + // If explicitly saved as expanded, apply it + if (section && expandedSections[section] === true) { + header.classList.add('expanded'); + if (submenu && submenu.classList.contains('sub')) { + submenu.classList.add('expanded'); + submenu.style.display = 'flex'; + } + if (chevron) chevron.style.transform = 'rotate(180deg)'; + } + // If has selected child, always expand (override localStorage) + if (submenu && submenu.querySelector('a.selected')) { + header.classList.add('expanded'); + submenu.classList.add('expanded'); + submenu.style.display = 'flex'; + if (chevron) chevron.style.transform = 'rotate(180deg)'; + } + }); +})(); document.querySelectorAll('.tabs a').forEach((element, index) => { element.onclick = event => { event.preventDefault(); diff --git a/assets/functions.php b/assets/functions.php index 25a3eb0..e4592d3 100644 --- a/assets/functions.php +++ b/assets/functions.php @@ -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 .= ''.ucfirst((${$menu_item['main_menu']['name']} ?? 'not specified')).''; - - if (count($menu_item) > 1){ - //SUBMENU - $menu .= '
' . $error_message . '
+An error occurred while loading the page.
+