From 56f51703c704742cde5e4be477fdbb7105d2aabf Mon Sep 17 00:00:00 2001 From: Michael Kaufmann Date: Thu, 3 Mar 2022 19:19:18 +0100 Subject: [PATCH] testing api-key listing Signed-off-by: Michael Kaufmann --- api_keys.php | 92 ++++++----------------- lib/Froxlor/UI/Callbacks/Impersonate.php | 34 +++++++++ lib/Froxlor/UI/Callbacks/Style.php | 12 +++ lib/Froxlor/UI/Callbacks/Text.php | 10 +++ lib/Froxlor/UI/Listing.php | 16 +++- lib/tablelisting/tablelisting.apikeys.php | 85 +++++++++++++++++++++ 6 files changed, 179 insertions(+), 70 deletions(-) create mode 100644 lib/tablelisting/tablelisting.apikeys.php diff --git a/api_keys.php b/api_keys.php index cebfe772..6d30636b 100644 --- a/api_keys.php +++ b/api_keys.php @@ -1,5 +1,5 @@ $ip) { @@ -101,8 +102,8 @@ if ($action == 'delete') { $allowed_from = implode(",", array_unique($ip_list)); } - if ($valid_until <= 0 || ! is_numeric($valid_until)) { - $valid_until = - 1; + if ($valid_until <= 0 || !is_numeric($valid_until)) { + $valid_until = -1; } $upd_stmt = Database::prepare(" @@ -128,7 +129,7 @@ if ($action == 'delete') { $log->logAction(\Froxlor\FroxlorLogger::USR_ACTION, LOG_NOTICE, "viewed api::api_keys"); -// select all my (accessible) certificates +// select all my (accessible) api-keys $keys_stmt_query = "SELECT ak.*, c.loginname, a.loginname as adminname FROM `" . TABLE_API_KEYS . "` ak LEFT JOIN `" . TABLE_PANEL_CUSTOMERS . "` c ON `c`.`customerid` = `ak`.`customerid` @@ -158,13 +159,11 @@ if (AREA == 'admin' && $userinfo['customers_see_all'] == '0') { ); } -$paging = new \Froxlor\UI\Paging($userinfo, TABLE_API_KEYS, $fields); -$keys_stmt_query .= $paging->getSqlWhere(true) . " " . $paging->getSqlOrderBy() . " " . $paging->getSqlLimit(); +//$keys_stmt_query .= $paging->getSqlWhere(true) . " " . $paging->getSqlOrderBy() . " " . $paging->getSqlLimit(); $keys_stmt = Database::prepare($keys_stmt_query); Database::pexecute($keys_stmt, $qry_params); $all_keys = $keys_stmt->fetchAll(PDO::FETCH_ASSOC); -$apikeys = ""; if (count($all_keys) == 0) { $count = 0; @@ -173,64 +172,19 @@ if (count($all_keys) == 0) { $searchcode = ""; $pagingcode = ""; eval("\$apikeys.=\"" . \Froxlor\UI\Template::getTemplate("api_keys/keys_error", true) . "\";"); -} else { - $count = count($all_keys); - $paging->setEntries($count); - $sortcode = $paging->getHtmlSortCode($lng); - $arrowcode = $paging->getHtmlArrowCode($filename . '?page=' . $page . '&s=' . $s); - $searchcode = $paging->getHtmlSearchCode($lng); - $pagingcode = $paging->getHtmlPagingCode($filename . '?page=' . $page . '&s=' . $s); - - foreach ($all_keys as $idx => $key) { - if ($paging->checkDisplay($idx)) { - - // my own key - $isMyKey = false; - if ($key['adminid'] == $userinfo['adminid'] && ((AREA == 'admin' && $key['customerid'] == 0) || (AREA == 'customer' && $key['customerid'] == $userinfo['customerid']))) { - // this is mine - $isMyKey = true; - } - - $adminCustomerLink = ""; - if (AREA == 'admin') { - if ($isMyKey) { - $adminCustomerLink = $key['adminname']; - } else { - $adminCustomerLink = '' . (empty($key['customerid']) ? $key['adminname'] : $key['loginname']) . ''; - } - } else { - // customer do not need links - $adminCustomerLink = $key['loginname']; - } - - // escape stuff - $row = \Froxlor\PhpHelper::htmlentitiesArray($key); - - // shorten keys - $row['_apikey'] = substr($row['apikey'], 0, 20) . '...'; - $row['_secret'] = substr($row['secret'], 0, 20) . '...'; - - // check whether the api key is not valid anymore - $isValid = true; - if ($row['valid_until'] >= 0) { - if ($row['valid_until'] < time()) { - $isValid = false; - } - // format - $row['valid_until'] = date('Y-m-d', $row['valid_until']); - } else { - // infinity - $row['valid_until'] = ""; - } - eval("\$apikeys.=\"" . \Froxlor\UI\Template::getTemplate("api_keys/keys_key", true) . "\";"); - } else { - continue; - } - } } -eval("echo \"" . \Froxlor\UI\Template::getTemplate("api_keys/keys_list", true) . "\";"); + +$apikeys_list_data = include_once dirname(__FILE__) . '/lib/tablelisting/tablelisting.apikeys.php'; +$collection = [ + 'data' => $all_keys, + 'pagination' => [] +]; + +UI::twigBuffer('user/table.html.twig', [ + 'listing' => \Froxlor\UI\Listing::formatFromArray($collection, $apikeys_list_data['apikeys_list']), + 'actions_links' => (int)$userinfo['api_allowed'] == 1 ? [[ + 'href' => $linker->getLink(['section' => 'index', 'page' => $page, 'action' => 'add']), + 'label' => $lng['apikeys']['key_add'] + ]] : null +]); +UI::twigOutputBuffer(); diff --git a/lib/Froxlor/UI/Callbacks/Impersonate.php b/lib/Froxlor/UI/Callbacks/Impersonate.php index 24e45218..74d4f557 100644 --- a/lib/Froxlor/UI/Callbacks/Impersonate.php +++ b/lib/Froxlor/UI/Callbacks/Impersonate.php @@ -58,4 +58,38 @@ class Impersonate ] ]; } + + public static function apiAdminCustomerLink(array $attributes) + { + // my own key + $isMyKey = false; + if ( + $attributes['fields']['adminid'] == UI::getCurrentUser()['adminid'] + && ((AREA == 'admin' && $attributes['fields']['customerid'] == 0) + || (AREA == 'customer' && $attributes['fields']['customerid'] == UI::getCurrentUser()['customerid']) + ) + ) { + // this is mine + $isMyKey = true; + } + + $adminCustomerLink = ""; + if (AREA == 'admin') { + if ($isMyKey) { + $adminCustomerLink = $attributes['fields']['adminname']; + } else { + if (empty($attributes['fields']['customerid'])) { + $adminCustomerLink = self::admin($attributes); + } else { + $attributes['data'] = $attributes['fields']['loginname']; + $adminCustomerLink = self::customer($attributes); + } + } + } else { + // customer do not need links + $adminCustomerLink = $attributes['fields']['loginname']; + } + + return $adminCustomerLink; + } } diff --git a/lib/Froxlor/UI/Callbacks/Style.php b/lib/Froxlor/UI/Callbacks/Style.php index 34d3af15..ee9d7ba3 100644 --- a/lib/Froxlor/UI/Callbacks/Style.php +++ b/lib/Froxlor/UI/Callbacks/Style.php @@ -29,6 +29,18 @@ class Style return $attributes['fields']['deactivated'] ? 'bg-danger' : ''; } + public static function invalidApiKey(array $attributes): string + { + // check whether the api key is not valid anymore + $isValid = true; + if ($attributes['fields']['valid_until'] >= 0) { + if ($attributes['fields']['valid_until'] < time()) { + $isValid = false; + } + } + return $isValid ? '' : 'bg-danger'; + } + public static function diskspaceWarning(array $attributes): string { return self::getWarningStyle('diskspace', $attributes['fields'], (int)Settings::Get('system.report_webmax')); diff --git a/lib/Froxlor/UI/Callbacks/Text.php b/lib/Froxlor/UI/Callbacks/Text.php index 90d832cf..c5518d46 100644 --- a/lib/Froxlor/UI/Callbacks/Text.php +++ b/lib/Froxlor/UI/Callbacks/Text.php @@ -47,8 +47,18 @@ class Text return (int)$attributes['data'] > 0 ? date('d.m.Y H:i', (int)$attributes['data']) : UI::getLng('panel.never'); } + public static function timestampUntil(array $attributes): string + { + return (int)$attributes['data'] > 0 ? date('d.m.Y H:i', (int)$attributes['data']) : UI::getLng('panel.unlimited'); + } + public static function crondesc(array $attributes): string { return UI::getLng('crondesc.' . $attributes['data']); } + + public static function shorten(array $attributes): string + { + return substr($attributes['data'], 0, 20) . '...'; + } } diff --git a/lib/Froxlor/UI/Listing.php b/lib/Froxlor/UI/Listing.php index f43cbafb..210113d6 100644 --- a/lib/Froxlor/UI/Listing.php +++ b/lib/Froxlor/UI/Listing.php @@ -38,6 +38,20 @@ class Listing ]; } + public static function formatFromArray(array $collection, array $tabellisting): array + { + return [ + 'title' => $tabellisting['title'], + 'icon' => $tabellisting['icon'], + 'table' => [ + 'th' => self::generateTableHeadings($tabellisting), + 'tr' => self::generateTableRows($collection['data'], $tabellisting), + ], + 'pagination' => $collection['pagination'], + 'empty_msg' => $tabellisting['empty_msg'] ?? null + ]; + } + private static function generateTableHeadings(array $tabellisting): array { $heading = []; @@ -92,7 +106,7 @@ class Listing } elseif ($field) { $rows[$row]['td'][$col]['data'] = $data; } else { - throw new Exception('The visible column "'. $visible_column .'" has neither a "callback" nor a "field" set.'); + throw new Exception('The visible column "' . $visible_column . '" has neither a "callback" nor a "field" set.'); } // Set class for table-row if defined diff --git a/lib/tablelisting/tablelisting.apikeys.php b/lib/tablelisting/tablelisting.apikeys.php new file mode 100644 index 00000000..9c72cfc6 --- /dev/null +++ b/lib/tablelisting/tablelisting.apikeys.php @@ -0,0 +1,85 @@ + (2010-) + * @license GPLv2 http://files.froxlor.org/misc/COPYING.txt + * @package Tabellisting + * + */ + +use Froxlor\UI\Callbacks\Impersonate; +use Froxlor\UI\Callbacks\Style; +use Froxlor\UI\Callbacks\Text; +use Froxlor\UI\Listing; + +return [ + 'apikeys_list' => [ + 'title' => $lng['menue']['main']['apikeys'], + 'icon' => 'fa-solid fa-key', + 'columns' => [ + 'a.loginname' => [ + 'label' => $lng['login']['username'], + 'field' => 'loginname', + 'callback' => [Impersonate::class, 'apiAdminCustomerLink'] + ], + 'ak.apikey' => [ + 'label' => 'API-key', + 'field' => 'apikey', + 'callback' => [Text::class, 'shorten'], + ], + 'ak.secret' => [ + 'label' => 'Secret', + 'field' => 'secret', + 'callback' => [Text::class, 'shorten'], + ], + 'ak.allowed_from' => [ + 'label' => $lng['apikeys']['allowed_from'], + 'field' => 'allowed_from', + ], + 'ak.valid_until' => [ + 'label' => $lng['apikeys']['valid_until'], + 'field' => 'valid_until', + 'callback' => [Text::class, 'timestampUntil'], + ] + ], + 'visible_columns' => Listing::getVisibleColumnsForListing('apikeys_list', [ + 'a.loginname', + 'ak.apikey', + 'ak.secret', + 'ak.allowed_from', + 'ak.valid_until' + ]), + 'actions' => [ + 'show' => [ + 'icon' => 'fa fa-eye', + 'title' => $lng['apikeys']['clicktoview'], + 'href' => [ + 'page' => 'apikeys', + 'action' => '#', + 'id' => ':id' + ], + ], + 'delete' => [ + 'icon' => 'fa fa-trash', + 'title' => $lng['panel']['delete'], + 'class' => 'text-danger', + 'href' => [ + 'page' => 'apikeys', + 'action' => 'delete', + 'id' => ':id' + ], + ], + ], + 'callback' => [ + [Style::class, 'invalidApiKey'] + ] + ] +];