From 59682ba62041ff7f60d8490b068d821b1c501379 Mon Sep 17 00:00:00 2001 From: Michael Kaufmann Date: Sun, 20 Mar 2022 09:53:30 +0100 Subject: [PATCH] added a few more entities to globalsearch (admin-side) Signed-off-by: Michael Kaufmann --- admin_phpsettings.php | 8 +- lib/Froxlor/Ajax/Ajax.php | 148 +--------- lib/Froxlor/Ajax/GlobalSearch.php | 270 ++++++++++++++++++ lib/Froxlor/UI/Callbacks/Admin.php | 27 ++ lib/Froxlor/UI/Callbacks/PHPConf.php | 36 ++- lib/navigation/00.froxlor.main.php | 2 - .../admin/tablelisting.fpmconfigs.php | 2 + .../admin/tablelisting.phpconfigs.php | 2 + ssl_certificates.php | 1 - 9 files changed, 331 insertions(+), 165 deletions(-) create mode 100644 lib/Froxlor/Ajax/GlobalSearch.php create mode 100644 lib/Froxlor/UI/Callbacks/Admin.php diff --git a/admin_phpsettings.php b/admin_phpsettings.php index 2c53d340..35202887 100644 --- a/admin_phpsettings.php +++ b/admin_phpsettings.php @@ -42,10 +42,10 @@ if ($page == 'overview') { UI::view('user/table.html.twig', [ 'listing' => \Froxlor\UI\Listing::format($collection, $phpconf_list_data['phpconf_list']), - 'actions_links' => [[ + 'actions_links' => (bool)$userinfo['change_serversettings'] ? [[ 'href' => $linker->getLink(['section' => 'phpsettings', 'page' => $page, 'action' => 'add']), 'label' => $lng['admin']['phpsettings']['addnew'] - ]] + ]] : [] ]); } @@ -186,10 +186,10 @@ if ($page == 'overview') { UI::view('user/table.html.twig', [ 'listing' => \Froxlor\UI\Listing::format($collection, $fpmconf_list_data['fpmconf_list']), - 'actions_links' => [[ + 'actions_links' => (bool)$userinfo['change_serversettings'] ? [[ 'href' => $linker->getLink(['section' => 'phpsettings', 'page' => $page, 'action' => 'add']), 'label' => $lng['admin']['fpmsettings']['addnew'] - ]] + ]] : [] ]); } diff --git a/lib/Froxlor/Ajax/Ajax.php b/lib/Froxlor/Ajax/Ajax.php index 177a072f..ef4237bf 100644 --- a/lib/Froxlor/Ajax/Ajax.php +++ b/lib/Froxlor/Ajax/Ajax.php @@ -4,9 +4,7 @@ namespace Froxlor\Ajax; use Exception; use Froxlor\Http\HttpClient; -use Froxlor\PhpHelper; use Froxlor\Settings; -use Froxlor\User; use Froxlor\UI\Panel\UI; use Froxlor\UI\Request; @@ -223,152 +221,16 @@ class Ajax $searchtext = Request::get('searchtext'); $result = []; - if ($searchtext && strlen(trim($searchtext)) > 2) { - $processed = []; + // settings + $result_settings = GlobalSearch::searchSettings($searchtext, $this->userinfo); - $stparts = explode(" ", $searchtext); + // all searchable entities + $result_entities = GlobalSearch::searchGlobal($searchtext, $this->userinfo); - foreach ($stparts as $searchtext) { - $searchtext = trim($searchtext); + $result = array_merge($result_settings, $result_entities); - // settings (if allowed) - if (isset($this->userinfo['adminsession']) && $this->userinfo['adminsession'] == 1) { - - if ($this->userinfo['change_serversettings'] == 1) { - $settings_data = PhpHelper::loadConfigArrayDir(\Froxlor\Froxlor::getInstallDir() . '/actions/admin/settings/'); - $results = array(); - if (!isset($processed['settings'])) { - $processed['settings'] = []; - } - PhpHelper::recursive_array_search($searchtext, $settings_data, $results); - foreach ($results as $pathkey) { - $pk = explode(".", $pathkey); - if (count($pk) > 4) { - $settingkey = $pk[0] . '.' . $pk[1] . '.' . $pk[2] . '.' . $pk[3]; - if (is_array($processed['settings']) && !array_key_exists($settingkey, $processed['settings'])) { - $processed['settings'][$settingkey] = true; - $sresult = $settings_data[$pk[0]][$pk[1]][$pk[2]][$pk[3]]; - if ($sresult['type'] != 'hidden') { - if (!isset($result['settings'])) { - $result['settings'] = []; - } - $result['settings'][] = [ - 'title' => (is_array($sresult['label']) ? $sresult['label']['title'] : $sresult['label']), - 'href' => 'admin_settings.php?page=overview&part=' . $pk[1] . '&em=' . $pk[3] - ]; - } - } - } - } - } - - // customers - $searchfields = [ - 'c.loginname', - 'c.name', - 'c.firstname', - 'c.company', - 'c.street', - 'c.zipcode', - 'c.city', - 'c.email', - 'c.customernumber' - ]; - $collection = (new \Froxlor\UI\Collection(\Froxlor\Api\Commands\Customers::class, $this->userinfo)) - ->addParam(['sql_search' => [ - '_plainsql' => $this->searchStringSql($searchfields, $searchtext) - ]]); - if ($collection->count() > 0) { - if (!isset($processed['customer'])) { - $processed['customer'] = []; - } - foreach ($collection->getList() as $cresult) { - if (is_array($processed['customer']) && !array_key_exists($cresult['customerid'], $processed['customer'])) { - $processed['customer'][$cresult['customerid']] = true; - if (!isset($result['customer'])) { - $result['customer'] = []; - } - $result['customer'][] = [ - 'title' => User::getCorrectFullUserDetails($cresult), - 'href' => 'admin_customers.php?page=customers&action=edit&id=' . $cresult['customerid'] - ]; - } - } - } - - // domains - $searchfields = [ - 'd.domain', - 'd.domain_ace', - 'd.documentroot' - ]; - $collection = (new \Froxlor\UI\Collection(\Froxlor\Api\Commands\Domains::class, $this->userinfo)) - ->addParam(['sql_search' => [ - '_plainsql' => $this->searchStringSql($searchfields, $searchtext) - ]]); - if ($collection->count() > 0) { - if (!isset($processed['domains'])) { - $processed['domains'] = []; - } - foreach ($collection->getList() as $cresult) { - if (is_array($processed['domains']) && !array_key_exists($cresult['id'], $processed['domains'])) { - $processed['domains'][$cresult['id']] = true; - if (!isset($result['domains'])) { - $result['domains'] = []; - } - $result['domains'][] = [ - 'title' => $cresult['domain_ace'], - 'href' => 'admin_domains.php?page=domains&action=edit&id=' . $cresult['id'] - ]; - } - } - } - } // is-admin - else { - // subdomains - $searchfields = [ - 'd.domain', - 'd.domain_ace', - 'd.documentroot' - ]; - $collection = (new \Froxlor\UI\Collection(\Froxlor\Api\Commands\Domains::class, $this->userinfo)) - ->addParam(['sql_search' => [ - '_plainsql' => $this->searchStringSql($searchfields, $searchtext) - ]]); - if ($collection->count() > 0) { - if (!isset($processed['domains'])) { - $processed['domains'] = []; - } - foreach ($collection->getList() as $cresult) { - if (is_array($processed['domains']) && !array_key_exists($cresult['domains'], $processed['domains'])) { - $processed['domains'][$cresult['id']] = true; - if (!isset($result['domains'])) { - $result['domains'] = []; - } - $result['domains'][] = [ - 'title' => $cresult['domain_ace'], - 'href' => 'customer_domains.php?page=domains&action=edit&id=' . $cresult['id'] - ]; - } - } - } - } // is-customer - } // foreach splitted search-term - } header("Content-type: application/json"); echo json_encode($result); } - - private function searchStringSql(array $searchfields, $searchtext) - { - $result = ['sql' => [], 'values' => []]; - $result['sql'] = "("; - foreach ($searchfields as $sf) { - $result['sql'] .= $sf . " LIKE :searchtext OR "; - } - $result['sql'] = substr($result['sql'], 0, -3) . ")"; - $result['values'] = ['searchtext' => '%' . $searchtext . '%']; - return $result; - } } diff --git a/lib/Froxlor/Ajax/GlobalSearch.php b/lib/Froxlor/Ajax/GlobalSearch.php new file mode 100644 index 00000000..7abd6940 --- /dev/null +++ b/lib/Froxlor/Ajax/GlobalSearch.php @@ -0,0 +1,270 @@ + (2010-) + * @license GPLv2 http://files.froxlor.org/misc/COPYING.txt + * @package AJAX + * + */ +class GlobalSearch +{ + protected array $userinfo; + + public static function searchSettings(string $searchtext, array $userinfo): array + { + $result = []; + if ($searchtext && strlen(trim($searchtext)) > 2) { + $processed = []; + $stparts = explode(" ", $searchtext); + foreach ($stparts as $searchtext) { + $searchtext = trim($searchtext); + + // settings (if allowed) + if (isset($userinfo['adminsession']) && $userinfo['adminsession'] == 1 && $userinfo['change_serversettings'] == 1) { + + $settings_data = PhpHelper::loadConfigArrayDir(Froxlor::getInstallDir() . '/actions/admin/settings/'); + $results = array(); + if (!isset($processed['settings'])) { + $processed['settings'] = []; + } + PhpHelper::recursive_array_search($searchtext, $settings_data, $results); + foreach ($results as $pathkey) { + $pk = explode(".", $pathkey); + if (count($pk) > 4) { + $settingkey = $pk[0] . '.' . $pk[1] . '.' . $pk[2] . '.' . $pk[3]; + if (is_array($processed['settings']) && !array_key_exists($settingkey, $processed['settings'])) { + $processed['settings'][$settingkey] = true; + $sresult = $settings_data[$pk[0]][$pk[1]][$pk[2]][$pk[3]]; + if ($sresult['type'] != 'hidden') { + if (!isset($result['settings'])) { + $result['settings'] = []; + } + $result['settings'][] = [ + 'title' => (is_array($sresult['label']) ? $sresult['label']['title'] : $sresult['label']), + 'href' => 'admin_settings.php?page=overview&part=' . $pk[1] . '&em=' . $pk[3] + ]; + } // not hidden + } // if not processed + } // correct settingkey + } // foreach + } // admin + change_serversetting + } // foreach + } // searchtext min 3 chars + return $result; + } + + /** + * + */ + public static function searchGlobal(string $searchtext, array $userinfo): array + { + $result = []; + if ($searchtext && strlen(trim($searchtext)) > 2) { + $processed = []; + + $stparts = explode(" ", $searchtext); + + foreach ($stparts as $searchtext) { + $searchtext = trim($searchtext); + + // admin + if (isset($userinfo['adminsession']) && $userinfo['adminsession'] == 1) { + + $toSearch = [ + // customers + 'customer' => [ + 'class' => \Froxlor\Api\Commands\Customers::class, + 'searchfields' => [ + 'c.loginname', + 'c.name', + 'c.firstname', + 'c.company', + 'c.street', + 'c.zipcode', + 'c.city', + 'c.email', + 'c.customernumber', + 'c.custom_notes' + ], + 'result_key' => 'customerid', + 'result_format' => [ + 'title' => ['\\Froxlor\\User', 'getCorrectFullUserDetails'], + 'href' => 'admin_customers.php?page=customers&action=edit&id=' + ] + ], + // domains + 'domains' => [ + 'class' => \Froxlor\Api\Commands\Domains::class, + 'searchfields' => [ + 'd.domain', + 'd.domain_ace', + 'd.documentroot' + ], + 'result_key' => 'id', + 'result_format' => [ + 'title' => ['self', 'getFieldFromResult'], + 'title_args' => 'domain_ace', + 'href' => 'admin_domains.php?page=domains&action=edit&id=' + ] + ], + // ips and ports + 'ipsandports' => [ + 'class' => \Froxlor\Api\Commands\IpsAndPorts::class, + 'searchfields' => [ + 'ip', + 'vhostcontainer', + 'specialsettings' + ], + 'result_key' => 'id', + 'result_groupkey' => 'ip', + 'result_format' => [ + 'title' => ['self', 'getFieldFromResult'], + 'title_args' => 'ip', + 'href' => 'admin_ipsandports.php?page=ipsandports&action=edit&id=' + ] + ], + // hosting-plans + 'hostingplans' => [ + 'class' => \Froxlor\Api\Commands\HostingPlans::class, + 'searchfields' => [ + 'p.name', + 'p.description' + ], + 'result_key' => 'id', + 'result_format' => [ + 'title' => ['self', 'getFieldFromResult'], + 'title_args' => 'name', + 'href' => 'admin_plans.php?page=overview&action=edit&id=' + ] + ], + // PHP configs + 'phpconfigs' => [ + 'class' => \Froxlor\Api\Commands\PhpSettings::class, + 'searchfields' => [ + 'c.description', + 'fd.description', + 'c.binary' + ], + 'result_key' => 'id', + 'result_format' => [ + 'title' => ['self', 'getFieldFromResult'], + 'title_args' => 'description', + 'href' => ((bool) $userinfo['change_serversettings'] ? 'admin_phpsettings.php?page=overview&action=edit&id=' : 'admin_phpsettings.php?page=overview&sid=') + ] + ], + // FPM daemons + 'fpmconfigs' => [ + 'class' => \Froxlor\Api\Commands\FpmDaemons::class, + 'searchfields' => [ + 'description', + 'reload_cmd' + ], + 'result_key' => 'id', + 'result_format' => [ + 'title' => ['self', 'getFieldFromResult'], + 'title_args' => 'description', + 'href' => ((bool) $userinfo['change_serversettings'] ? 'admin_phpsettings.php?page=fpmdaemons&action=edit&id=' : 'admin_phpsettings.php?page=fpmdaemons&sid=') + ] + ] + ]; + + if ((bool) $userinfo['change_serversettings']) { + // admins + $toSearch['admins'] = [ + 'class' => \Froxlor\Api\Commands\Admins::class, + 'searchfields' => [ + 'loginname', + 'name', + 'email', + 'custom_notes' + ], + 'result_key' => 'adminid', + 'result_format' => [ + 'title' => ['self', 'getFieldFromResult'], + 'title_args' => 'name', + 'href' => 'admin_admins.php?page=admins&action=edit&id=' + ] + ]; + } + } else { + $toSearch = [ + // (sub)domains + 'domains' => [ + 'class' => \Froxlor\Api\Commands\Domains::class, + 'searchfields' => [ + 'd.domain', + 'd.domain_ace', + 'd.documentroot' + ], + 'result_key' => 'id', + 'result_format' => [ + 'title' => ['self', 'getFieldFromResult'], + 'title_args' => 'domain_ace', + 'href' => 'customer_domains.php?page=domains&action=edit&id=' + ] + ] + ]; + } + + foreach ($toSearch as $entity => $edata) { + + $collection = (new Collection($edata['class'], $userinfo)) + ->addParam(['sql_search' => [ + '_plainsql' => self::searchStringSql($edata['searchfields'], $searchtext) + ]]); + if ($collection->count() > 0) { + if (!isset($processed[$entity])) { + $processed[$entity] = []; + } + $group_key = $edata['result_groupkey'] ?? $edata['result_key']; + foreach ($collection->getList() as $cresult) { + if (is_array($processed[$entity]) && !array_key_exists($cresult[$group_key], $processed[$entity])) { + $processed[$entity][$cresult[$group_key]] = true; + if (!isset($result[$entity])) { + $result[$entity] = []; + } + $result[$entity][] = [ + 'title' => call_user_func($edata['result_format']['title'], $cresult, ($edata['result_format']['title_args'] ?? null)), + 'href' => $edata['result_format']['href'] . $cresult[$edata['result_key']] + ]; + } + } + } + } // foreach entity + + } // foreach splitted search-term + } + return $result; + } + + private static function searchStringSql(array $searchfields, $searchtext) + { + $result = ['sql' => [], 'values' => []]; + $result['sql'] = "("; + foreach ($searchfields as $sf) { + $result['sql'] .= $sf . " LIKE :searchtext OR "; + } + $result['sql'] = substr($result['sql'], 0, -3) . ")"; + $result['values'] = ['searchtext' => '%' . $searchtext . '%']; + return $result; + } + + private static function getFieldFromResult(array $resultset, string $field = null) + { + return $resultset[$field] ?? ''; + } +} diff --git a/lib/Froxlor/UI/Callbacks/Admin.php b/lib/Froxlor/UI/Callbacks/Admin.php new file mode 100644 index 00000000..18632ab1 --- /dev/null +++ b/lib/Froxlor/UI/Callbacks/Admin.php @@ -0,0 +1,27 @@ + (2010-) + * @license GPLv2 http://files.froxlor.org/misc/COPYING.txt + * @package Froxlor\UI\Callbacks + * + */ +class Admin +{ + public static function canChangeServerSettings(array $attributes) + { + return (bool)UI::getCurrentUser()['change_serversettings']; + } +} diff --git a/lib/Froxlor/UI/Callbacks/PHPConf.php b/lib/Froxlor/UI/Callbacks/PHPConf.php index fc083e79..8b3cfc6d 100644 --- a/lib/Froxlor/UI/Callbacks/PHPConf.php +++ b/lib/Froxlor/UI/Callbacks/PHPConf.php @@ -32,7 +32,7 @@ class PHPConf if ($subdomains_count == 0 && empty($domains)) { $domains = UI::getLng('admin.phpsettings.notused'); } else { - $domains .= (!empty($domains) ? '+ ' : '') . $subdomains_count . ' ' . UI::getLng(('customer.subdomains')); + $domains .= !empty($subdomains_count) ? ((!empty($domains) ? '+ ' : '') . $subdomains_count . ' ' . UI::getLng('customer.subdomains')) : ''; } return $domains; @@ -49,23 +49,29 @@ class PHPConf public static function isNotDefault(array $attributes) { - return $attributes['fields']['id'] != 1; + if (UI::getCurrentUser()['change_serversettings']) { + return $attributes['fields']['id'] != 1; + } + return false; } public static function fpmConfLink(array $attributes) { - $linker = UI::getLinker(); - return [ - 'macro' => 'link', - 'data' => [ - 'text' => $attributes['data'], - 'href' => $linker->getLink([ - 'section' => 'phpsettings', - 'page' => 'fpmdaemons', - 'action' => 'edit', - 'id' => $attributes['fields']['fpmsettingid'], - ]), - ] - ]; + if (UI::getCurrentUser()['change_serversettings']) { + $linker = UI::getLinker(); + return [ + 'macro' => 'link', + 'data' => [ + 'text' => $attributes['data'], + 'href' => $linker->getLink([ + 'section' => 'phpsettings', + 'page' => 'fpmdaemons', + 'action' => 'edit', + 'id' => $attributes['fields']['fpmsettingid'], + ]), + ] + ]; + } + return $attributes['data']; } } diff --git a/lib/navigation/00.froxlor.main.php b/lib/navigation/00.froxlor.main.php index 755d7286..7260665e 100644 --- a/lib/navigation/00.froxlor.main.php +++ b/lib/navigation/00.froxlor.main.php @@ -240,7 +240,6 @@ return array( ), 'server_php' => array( 'label' => $lng['admin']['server_php'], - 'required_resources' => 'change_serversettings', 'icon' => 'fab fa-php', 'elements' => array( array( @@ -251,7 +250,6 @@ return array( array( 'url' => 'admin_phpsettings.php?page=fpmdaemons', 'label' => $lng['menue']['phpsettings']['fpmdaemons'], - 'required_resources' => 'change_serversettings', 'show_element' => \Froxlor\Settings::Get('phpfpm.enabled') == true ), array( diff --git a/lib/tablelisting/admin/tablelisting.fpmconfigs.php b/lib/tablelisting/admin/tablelisting.fpmconfigs.php index 882be733..6731bfdb 100644 --- a/lib/tablelisting/admin/tablelisting.fpmconfigs.php +++ b/lib/tablelisting/admin/tablelisting.fpmconfigs.php @@ -16,6 +16,7 @@ * */ +use Froxlor\UI\Callbacks\Admin; use Froxlor\UI\Callbacks\PHPConf; use Froxlor\UI\Listing; @@ -62,6 +63,7 @@ return [ 'action' => 'edit', 'id' => ':id' ], + 'visible' => [Admin::class, 'canChangeServerSettings'] ], 'delete' => [ 'icon' => 'fa fa-trash', diff --git a/lib/tablelisting/admin/tablelisting.phpconfigs.php b/lib/tablelisting/admin/tablelisting.phpconfigs.php index af1b9a7f..6e421922 100644 --- a/lib/tablelisting/admin/tablelisting.phpconfigs.php +++ b/lib/tablelisting/admin/tablelisting.phpconfigs.php @@ -16,6 +16,7 @@ * */ +use Froxlor\UI\Callbacks\Admin; use Froxlor\UI\Callbacks\PHPConf; use Froxlor\UI\Listing; use Froxlor\Settings; @@ -67,6 +68,7 @@ return [ 'action' => 'edit', 'id' => ':id' ], + 'visible' => [Admin::class, 'canChangeServerSettings'] ], 'delete' => [ 'icon' => 'fa fa-trash', diff --git a/ssl_certificates.php b/ssl_certificates.php index 524c6c6a..6e641db4 100644 --- a/ssl_certificates.php +++ b/ssl_certificates.php @@ -23,7 +23,6 @@ use Froxlor\FroxlorLogger; use Froxlor\Api\Commands\Certificates; use Froxlor\UI\Collection; use Froxlor\UI\Listing; -use Froxlor\UI\Pagination; use Froxlor\UI\Panel\UI; use Froxlor\UI\Response;