add userinfo to ajax calls; combine settings and global-search to one

Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
This commit is contained in:
Michael Kaufmann
2022-03-08 16:57:55 +01:00
parent f758d0d943
commit 218028de2b
4 changed files with 201 additions and 113 deletions

View File

@@ -6,6 +6,7 @@ use Exception;
use Froxlor\Http\HttpClient; use Froxlor\Http\HttpClient;
use Froxlor\PhpHelper; use Froxlor\PhpHelper;
use Froxlor\Settings; use Froxlor\Settings;
use Froxlor\User;
use Froxlor\UI\Panel\UI; use Froxlor\UI\Panel\UI;
use Froxlor\UI\Request; use Froxlor\UI\Request;
@@ -29,6 +30,7 @@ class Ajax
protected string $session; protected string $session;
protected string $action; protected string $action;
protected string $theme; protected string $theme;
protected array $userinfo;
protected array $lng; protected array $lng;
/** /**
@@ -40,6 +42,17 @@ class Ajax
$this->action = $_GET['action'] ?? $_POST['action'] ?? null; $this->action = $_GET['action'] ?? $_POST['action'] ?? null;
$this->theme = $_GET['theme'] ?? 'Froxlor'; $this->theme = $_GET['theme'] ?? 'Froxlor';
UI::sendHeaders();
UI::sendSslHeaders();
ini_set("session.name", "s");
ini_set("url_rewriter.tags", "");
ini_set("session.use_cookies", false);
ini_set("session.cookie_httponly", true);
ini_set("session.cookie_secure", UI::$SSL_REQ);
session_id($this->session);
session_start();
$this->initLang(); $this->initLang();
} }
@@ -97,15 +110,15 @@ class Ajax
*/ */
public function handle() public function handle()
{ {
$session = $this->getValidatedSession(); $this->userinfo = $this->getValidatedSession();
switch ($this->action) { switch ($this->action) {
case 'newsfeed': case 'newsfeed':
return $this->getNewsfeed(); return $this->getNewsfeed();
case 'updatecheck': case 'updatecheck':
return $this->getUpdateCheck(); return $this->getUpdateCheck();
case 'searchsetting': case 'searchglobal':
return $this->searchSetting(); return $this->searchGlobal();
default: default:
return $this->errorResponse('Action not found!'); return $this->errorResponse('Action not found!');
} }
@@ -135,9 +148,9 @@ class Ajax
$timediff = time() - \Froxlor\Settings::Get('session.sessiontimeout'); $timediff = time() - \Froxlor\Settings::Get('session.sessiontimeout');
$sel_stmt = \Froxlor\Database\Database::prepare(" $sel_stmt = \Froxlor\Database\Database::prepare("
SELECT * FROM `" . TABLE_PANEL_SESSIONS . "` SELECT * FROM `" . TABLE_PANEL_SESSIONS . "`
WHERE `hash` = :hash AND `ipaddress` = :ipaddr AND `useragent` = :ua AND `lastactivity` > :timediff WHERE `hash` = :hash AND `ipaddress` = :ipaddr AND `useragent` = :ua AND `lastactivity` > :timediff
"); ");
$session = \Froxlor\Database\Database::pexecute_first($sel_stmt, [ $session = \Froxlor\Database\Database::pexecute_first($sel_stmt, [
'hash' => $this->session, 'hash' => $this->session,
@@ -150,7 +163,27 @@ class Ajax
throw new Exception('Session is not defined!'); throw new Exception('Session is not defined!');
} }
return $session; if ($session['adminsession'] == 1) {
// test for admin
$sel_stmt = \Froxlor\Database\Database::prepare("
SELECT * FROM `" . TABLE_PANEL_ADMINS . "`
WHERE `adminid` = :userid
");
} else {
// test for customer
$sel_stmt = \Froxlor\Database\Database::prepare("
SELECT * FROM `" . TABLE_PANEL_CUSTOMERS . "`
WHERE `customerid` = :userid
");
}
$user = \Froxlor\Database\Database::pexecute_first($sel_stmt, [
'userid' => $session['userid']
]);
if (!$user) {
throw new Exception('Session is not defined!');
}
$user['adminsession'] = $session['adminsession'];
return $user;
} }
/** /**
@@ -237,34 +270,96 @@ class Ajax
} }
} }
private function searchSetting() /**
* @todo $userinfo
*/
private function searchGlobal()
{ {
$searchtext = Request::get('searchtext'); $searchtext = Request::get('searchtext');
$result = []; $result = [];
if ($searchtext && strlen($searchtext) > 2) { if ($searchtext && strlen(trim($searchtext)) > 2) {
$settings_data = PhpHelper::loadConfigArrayDir(\Froxlor\Froxlor::getInstallDir() . '/actions/admin/settings/');
$results = array(); $processed = [];
PhpHelper::recursive_array_search($searchtext, $settings_data, $results);
$processed_setting = array(); $stparts = explode(" ", $searchtext);
foreach ($results as $pathkey) {
$pk = explode(".", $pathkey); foreach ($stparts as $searchtext) {
if (count($pk) > 4) { $searchtext = trim($searchtext);
$settingkey = $pk[0] . '.' . $pk[1] . '.' . $pk[2] . '.' . $pk[3];
if (!array_key_exists($settingkey, $processed_setting)) { // settings (if allowed)
$processed_setting[$settingkey] = true; if (isset($this->userinfo['adminsession']) && $this->userinfo['adminsession'] == 1) {
$sresult = $settings_data[$pk[0]][$pk[1]][$pk[2]][$pk[3]];
if ($sresult['type'] != 'hidden') { if ($this->userinfo['change_serversettings'] == 1) {
$result[] = [ $settings_data = PhpHelper::loadConfigArrayDir(\Froxlor\Froxlor::getInstallDir() . '/actions/admin/settings/');
'title' => (is_array($sresult['label']) ? $sresult['label']['title'] : $sresult['label']), $results = array();
'href' => 'admin_settings.php?page=overview&part=' . $pk[1] . '&em=' . $pk[3] . '&s=' . $this->session, 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') {
$result[] = [
'title' => (is_array($sresult['label']) ? $sresult['label']['title'] : $sresult['label']),
'href' => 'admin_settings.php?page=overview&part=' . $pk[1] . '&em=' . $pk[3] . '&s=' . $this->session,
'category' => 'settings'
];
}
}
}
} }
} }
}
} // 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;
$result[] = [
'title' => User::getCorrectFullUserDetails($cresult),
'href' => 'admin_customers.php?page=customers&action=edit&id=' . $cresult['customerid'] . '&s=' . $this->session,
'category' => 'customer'
];
}
}
}
} // is-admin
} // foreach splitted search-term
} }
header("Content-type: application/json"); header("Content-type: application/json");
echo json_encode(['settings' => $result]); echo json_encode($result);
}
private function searchStringSql(array $searchfields, $searchtext)
{
$result = "(";
foreach ($searchfields as $sf) {
$result .= $sf . " LIKE " . \Froxlor\Database\Database::quote('%' . $searchtext . '%') . " OR ";
}
return substr($result, 0, -3) . ")";
} }
} }

View File

@@ -1,4 +1,5 @@
<?php <?php
namespace Froxlor\Api; namespace Froxlor\Api;
/** /**
@@ -110,9 +111,9 @@ abstract class ApiCommand extends ApiParameter
$this->dbversion = \Froxlor\Froxlor::DBVERSION; $this->dbversion = \Froxlor\Froxlor::DBVERSION;
$this->branding = \Froxlor\Froxlor::BRANDING; $this->branding = \Froxlor\Froxlor::BRANDING;
if (! empty($header)) { if (!empty($header)) {
$this->readUserData($header); $this->readUserData($header);
} elseif (! empty($userinfo)) { } elseif (!empty($userinfo)) {
$this->user_data = $userinfo; $this->user_data = $userinfo;
$this->is_admin = (isset($userinfo['adminsession']) && $userinfo['adminsession'] == 1 && $userinfo['adminid'] > 0) ? true : false; $this->is_admin = (isset($userinfo['adminsession']) && $userinfo['adminsession'] == 1 && $userinfo['adminid'] > 0) ? true : false;
} else { } else {
@@ -272,7 +273,7 @@ abstract class ApiCommand extends ApiParameter
{ {
$search = $this->getParam('sql_search', true, array()); $search = $this->getParam('sql_search', true, array());
$condition = ''; $condition = '';
if (! empty($search)) { if (!empty($search)) {
if ($append == true) { if ($append == true) {
$condition = ' AND '; $condition = ' AND ';
} else { } else {
@@ -285,43 +286,47 @@ abstract class ApiCommand extends ApiParameter
); );
$first = true; $first = true;
foreach ($search as $field => $valoper) { foreach ($search as $field => $valoper) {
$cleanfield = str_replace(".", "", $field); if ($field == '_plainsql') {
$sortfield = explode('.', $field); $condition .= $valoper;
foreach ($sortfield as $id => $sfield) {
if (substr($sfield, - 1, 1) != '`') {
$sfield .= '`';
}
if ($sfield[0] != '`') {
$sfield = '`' . $sfield;
}
$sortfield[$id] = $sfield;
}
$field = implode('.', $sortfield);
if (! $first) {
$condition .= ' AND ';
}
if (! is_array($valoper) || ! isset($valoper['op']) || empty($valoper['op'])) {
$condition .= $field . ' LIKE :' . $cleanfield;
if (! is_array($valoper)) {
$query_fields[':' . $cleanfield] = '%' . $valoper . '%';
} else {
$query_fields[':' . $cleanfield] = '%' . $valoper['value'] . '%';
}
} elseif (in_array($valoper['op'], $ops)) {
$condition .= $field . ' ' . $valoper['op'] . ':' . $cleanfield;
$query_fields[':' . $cleanfield] = $valoper['value'] ?? '';
} elseif (strtolower($valoper['op']) == 'in' && is_array($valoper['value']) && count($valoper['value']) > 0) {
$condition .= $field . ' ' . $valoper['op'] . ' (';
foreach ($valoper['value'] as $incnt => $invalue) {
$condition .= ":" . $cleanfield . $incnt . ", ";
$query_fields[':' . $cleanfield . $incnt] = $invalue ?? '';
}
$condition = substr($condition, 0, - 2) . ')';
} else { } else {
continue; $cleanfield = str_replace(".", "", $field);
} $sortfield = explode('.', $field);
if ($first) { foreach ($sortfield as $id => $sfield) {
$first = false; if (substr($sfield, -1, 1) != '`') {
$sfield .= '`';
}
if ($sfield[0] != '`') {
$sfield = '`' . $sfield;
}
$sortfield[$id] = $sfield;
}
$field = implode('.', $sortfield);
if (!$first) {
$condition .= ' AND ';
}
if (!is_array($valoper) || !isset($valoper['op']) || empty($valoper['op'])) {
$condition .= $field . ' LIKE :' . $cleanfield;
if (!is_array($valoper)) {
$query_fields[':' . $cleanfield] = '%' . $valoper . '%';
} else {
$query_fields[':' . $cleanfield] = '%' . $valoper['value'] . '%';
}
} elseif (in_array($valoper['op'], $ops)) {
$condition .= $field . ' ' . $valoper['op'] . ':' . $cleanfield;
$query_fields[':' . $cleanfield] = $valoper['value'] ?? '';
} elseif (strtolower($valoper['op']) == 'in' && is_array($valoper['value']) && count($valoper['value']) > 0) {
$condition .= $field . ' ' . $valoper['op'] . ' (';
foreach ($valoper['value'] as $incnt => $invalue) {
$condition .= ":" . $cleanfield . $incnt . ", ";
$query_fields[':' . $cleanfield . $incnt] = $invalue ?? '';
}
$condition = substr($condition, 0, -2) . ')';
} else {
continue;
}
if ($first) {
$first = false;
}
} }
} }
} }
@@ -343,10 +348,10 @@ abstract class ApiCommand extends ApiParameter
$limit = $this->getParam('sql_limit', true, 0); $limit = $this->getParam('sql_limit', true, 0);
$offset = $this->getParam('sql_offset', true, 0); $offset = $this->getParam('sql_offset', true, 0);
if (! is_numeric($limit)) { if (!is_numeric($limit)) {
$limit = 0; $limit = 0;
} }
if (! is_numeric($offset)) { if (!is_numeric($offset)) {
$offset = 0; $offset = 0;
} }
@@ -371,7 +376,7 @@ abstract class ApiCommand extends ApiParameter
{ {
$orderby = $this->getParam('sql_orderby', true, array()); $orderby = $this->getParam('sql_orderby', true, array());
$order = ""; $order = "";
if (! empty($orderby)) { if (!empty($orderby)) {
if ($append) { if ($append) {
$order .= ", "; $order .= ", ";
} else { } else {
@@ -389,7 +394,7 @@ abstract class ApiCommand extends ApiParameter
foreach ($orderby as $field => $by) { foreach ($orderby as $field => $by) {
$sortfield = explode('.', $field); $sortfield = explode('.', $field);
foreach ($sortfield as $id => $sfield) { foreach ($sortfield as $id => $sfield) {
if (substr($sfield, - 1, 1) != '`') { if (substr($sfield, -1, 1) != '`') {
$sfield .= '`'; $sfield .= '`';
} }
if ($sfield[0] != '`') { if ($sfield[0] != '`') {
@@ -399,7 +404,7 @@ abstract class ApiCommand extends ApiParameter
} }
$field = implode('.', $sortfield); $field = implode('.', $sortfield);
$by = strtoupper($by); $by = strtoupper($by);
if (! in_array($by, [ if (!in_array($by, [
'ASC', 'ASC',
'DESC' 'DESC'
])) { ])) {
@@ -417,7 +422,7 @@ abstract class ApiCommand extends ApiParameter
$order .= $field . " " . $by . ", "; $order .= $field . " " . $by . ", ";
} }
} }
$order = substr($order, 0, - 2); $order = substr($order, 0, -2);
} }
return $order; return $order;
@@ -463,16 +468,16 @@ abstract class ApiCommand extends ApiParameter
return json_decode($json_result, true)['data']; return json_decode($json_result, true)['data'];
} }
/** /**
* return api-compatible response in JSON format and send corresponding http-header * return api-compatible response in JSON format and send corresponding http-header
* *
* @param mixed $data * @param mixed $data
* @param int $response_code * @param int $response_code
* @return string json-encoded response message * @return string json-encoded response message
*/ */
protected function response($data = null, int $response_code = 200) protected function response($data = null, int $response_code = 200)
{ {
return \Froxlor\Api\Response::jsonDataResponse($data, $response_code); return \Froxlor\Api\Response::jsonDataResponse($data, $response_code);
} }
/** /**
@@ -493,7 +498,7 @@ abstract class ApiCommand extends ApiParameter
$customerid = $this->getParam('customerid', true, 0); $customerid = $this->getParam('customerid', true, 0);
$loginname = $this->getParam('loginname', true, ''); $loginname = $this->getParam('loginname', true, '');
if (! empty($customerid) || ! empty($loginname)) { if (!empty($customerid) || !empty($loginname)) {
$_result = $this->apiCall('Customers.get', array( $_result = $this->apiCall('Customers.get', array(
'id' => $customerid, 'id' => $customerid,
'loginname' => $loginname 'loginname' => $loginname
@@ -509,7 +514,7 @@ abstract class ApiCommand extends ApiParameter
$customer_ids[] = $customer['customerid']; $customer_ids[] = $customer['customerid'];
} }
} else { } else {
if (! $this->isInternal() && ! empty($customer_hide_option) && \Froxlor\Settings::IsInList('panel.customer_hide_options', $customer_hide_option)) { if (!$this->isInternal() && !empty($customer_hide_option) && \Froxlor\Settings::IsInList('panel.customer_hide_options', $customer_hide_option)) {
throw new \Exception("You cannot access this resource", 405); throw new \Exception("You cannot access this resource", 405);
} }
$customer_ids = array( $customer_ids = array(
@@ -545,7 +550,7 @@ abstract class ApiCommand extends ApiParameter
'loginname' => $loginname 'loginname' => $loginname
)); ));
// check whether the customer has enough resources // check whether the customer has enough resources
if (! empty($customer_resource_check) && $customer[$customer_resource_check . '_used'] >= $customer[$customer_resource_check] && $customer[$customer_resource_check] != '-1') { if (!empty($customer_resource_check) && $customer[$customer_resource_check . '_used'] >= $customer[$customer_resource_check] && $customer[$customer_resource_check] != '-1') {
throw new \Exception("Customer has no more resources available", 406); throw new \Exception("Customer has no more resources available", 406);
} }
} else { } else {

View File

@@ -1,11 +1,9 @@
<?php <?php
namespace Froxlor; namespace Froxlor;
use Exception; use Exception;
use Froxlor\Ajax\Ajax; use Froxlor\Ajax\Ajax;
use Twig\Error\LoaderError;
use Twig\Error\RuntimeError;
use Twig\Error\SyntaxError;
/** /**
* This file is part of the Froxlor project. * This file is part of the Froxlor project.
@@ -27,14 +25,14 @@ require_once dirname(__DIR__) . '/vendor/autoload.php';
// Load the user settings // Load the user settings
if (!file_exists('./userdata.inc.php')) { if (!file_exists('./userdata.inc.php')) {
die(); die();
} }
require './userdata.inc.php'; require './userdata.inc.php';
require './tables.inc.php'; require './tables.inc.php';
// Return response // Return response
try { try {
echo (new Ajax)->handle(); echo (new Ajax)->handle();
} catch (Exception $e) { } catch (Exception $e) {
echo \Froxlor\Api\Response::jsonErrorResponse($e->getMessage(), 500); echo \Froxlor\Api\Response::jsonErrorResponse($e->getMessage(), 500);
} }

View File

@@ -1,30 +1,20 @@
$(document).ready(function () { $(document).ready(function () {
console.log('included search'); console.log('included search');
$.typeahead({ $('input[class=js-typeahead-search_v1]').on('change keyup keydown', function () {
input: '.js-typeahead-search_v1', $.ajax({
order: "desc", url: "lib/ajax.php?action=searchglobal&theme=" + window.$theme + "&s=" + window.$session,
dynamic: true, type: "POST",
display: ['title'], data: {
href: "{{href}}", searchtext: $(this).val()
emptyTemplate: "No results for {{query}}",
debug: true,
source: {
settings: {
ajax: {
method: "post",
url: "lib/ajax.php?action=searchsetting&theme=" + window.$theme + "&s=" + window.$session,
path: "settings",
data: {
searchtext: '{{query}}'
},
}
}, },
}, dataType: "json",
callback: { success: function (data) {
onInit: function (node) { console.log(data);
console.log('Typeahead Initiated'); },
error: function (a, b) {
console.log(a, b);
} }
} });
}); });
}); });