Merge branch '0.11-dev' of github.com:Froxlor/Froxlor into 0.11-dev

This commit is contained in:
envoyr
2022-02-25 21:17:45 +01:00
52 changed files with 1262 additions and 753 deletions

View File

@@ -41,11 +41,15 @@ if ($page == 'admins' && $userinfo['change_serversettings'] == '1') {
\Froxlor\UI\Response::dynamic_error($e->getMessage()); \Froxlor\UI\Response::dynamic_error($e->getMessage());
} }
UI::twigBuffer('user/table.html.twig', [ UI::twigBuffer('user/table.html.twig', [
'listing' => \Froxlor\UI\Listing::format($collection, $admin_list_data['admin_list']), 'listing' => \Froxlor\UI\Listing::format($collection, $admin_list_data['admin_list']),
]); 'actions_links' => [[
UI::twigOutputBuffer(); 'href' => $linker->getLink(['section' => 'admins', 'page' => $page, 'action' => 'add']),
} elseif ($action == 'su') { 'label' => $lng['admin']['admin_add']
]]
]);
UI::twigOutputBuffer();
} elseif ($action == 'su') {
try { try {
$json_result = Admins::getLocal($userinfo, array( $json_result = Admins::getLocal($userinfo, array(

View File

@@ -33,18 +33,27 @@ if ($page == 'customers' && $userinfo['customers'] != '0') {
$log->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_NOTICE, "viewed admin_customers"); $log->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_NOTICE, "viewed admin_customers");
try { try {
$customer_list_data = include_once dirname(__FILE__) . '/lib/tablelisting/admin/tablelisting.customers.php'; $customer_list_data = include_once dirname(__FILE__) . '/lib/tablelisting/admin/tablelisting.customers.php';
$collection = (new \Froxlor\UI\Collection(\Froxlor\Api\Commands\Customers::class, $userinfo)) $collection = (new \Froxlor\UI\Collection(\Froxlor\Api\Commands\Customers::class, $userinfo))
->has('admin', \Froxlor\Api\Commands\Admins::class, 'adminid', 'adminid') ->has('admin', \Froxlor\Api\Commands\Admins::class, 'adminid', 'adminid')
->withPagination($customer_list_data['customer_list']['columns']); ->withPagination($customer_list_data['customer_list']['columns']);
} catch (Exception $e) { } catch (Exception $e) {
\Froxlor\UI\Response::dynamic_error($e->getMessage()); \Froxlor\UI\Response::dynamic_error($e->getMessage());
} }
UI::twigBuffer('user/table.html.twig', [ $actions_links = false;
'listing' => \Froxlor\UI\Listing::format($collection, $customer_list_data['customer_list']), if ($userinfo['customers_used'] < $userinfo['customers'] || $userinfo['customers'] == '-1') {
]); $actions_links = [[
UI::twigOutputBuffer(); 'href' => $linker->getLink(['section' => 'customers', 'page' => $page, 'action' => 'add']),
'label' => $lng['admin']['customer_add']
]];
}
UI::twigBuffer('user/table.html.twig', [
'listing' => \Froxlor\UI\Listing::format($collection, $customer_list_data['customer_list']),
'actions_links' => $actions_links
]);
UI::twigOutputBuffer();
} elseif ($action == 'su' && $id != 0) { } elseif ($action == 'su' && $id != 0) {
try { try {
$json_result = Customers::getLocal($userinfo, array( $json_result = Customers::getLocal($userinfo, array(

View File

@@ -38,14 +38,31 @@ if ($page == 'domains' || $page == 'overview') {
$collection = (new \Froxlor\UI\Collection(\Froxlor\Api\Commands\Domains::class, $userinfo)) $collection = (new \Froxlor\UI\Collection(\Froxlor\Api\Commands\Domains::class, $userinfo))
->has('customer', \Froxlor\Api\Commands\Customers::class, 'customerid', 'customerid') ->has('customer', \Froxlor\Api\Commands\Customers::class, 'customerid', 'customerid')
->withPagination($domain_list_data['domain_list']['columns']); ->withPagination($domain_list_data['domain_list']['columns']);
$customerCollection = (new \Froxlor\UI\Collection(Customers::class, $userinfo));
} catch (Exception $e) { } catch (Exception $e) {
\Froxlor\UI\Response::dynamic_error($e->getMessage()); \Froxlor\UI\Response::dynamic_error($e->getMessage());
} }
UI::twigBuffer('user/table.html.twig', [ $actions_links = false;
'listing' => \Froxlor\UI\Listing::format($collection, $domain_list_data['domain_list']), if (($userinfo['domains_used'] < $userinfo['domains'] || $userinfo['domains'] == '-1') && $customerCollection->count() != 0) {
]); $actions_links = [];
UI::twigOutputBuffer(); $actions_links[] = [
'href' => $linker->getLink(['section' => 'domains', 'page' => $page, 'action' => 'add']),
'label' => $lng['admin']['domain_add']
];
$actions_links[] = [
'href' => $linker->getLink(['section' => 'domains', 'page' => $page, 'action' => 'import']),
'label' => $lng['domains']['domain_import'],
'icon' => 'fa-solid fa-file-import',
'class' => 'btn-secondary'
];
}
UI::twigBuffer('user/table.html.twig', [
'listing' => \Froxlor\UI\Listing::format($collection, $domain_list_data['domain_list']),
'actions_links' => $actions_links
]);
UI::twigOutputBuffer();
} elseif ($action == 'delete' && $id != 0) { } elseif ($action == 'delete' && $id != 0) {
try { try {

View File

@@ -39,10 +39,14 @@ if ($page == 'ipsandports' || $page == 'overview') {
\Froxlor\UI\Response::dynamic_error($e->getMessage()); \Froxlor\UI\Response::dynamic_error($e->getMessage());
} }
UI::twigBuffer('user/table.html.twig', [ UI::twigBuffer('user/table.html.twig', [
'listing' => \Froxlor\UI\Listing::format($collection, $ipsandports_list_data['ipsandports_list']), 'listing' => \Froxlor\UI\Listing::format($collection, $ipsandports_list_data['ipsandports_list']),
]); 'actions_links' => [[
UI::twigOutputBuffer(); 'href' => $linker->getLink(['section' => 'ipsandports', 'page' => $page, 'action' => 'add']),
'label' => $lng['admin']['ipsandports']['add']
]]
]);
UI::twigOutputBuffer();
} elseif ($action == 'delete' && $id != 0) { } elseif ($action == 'delete' && $id != 0) {
try { try {
$json_result = IpsAndPorts::getLocal($userinfo, array( $json_result = IpsAndPorts::getLocal($userinfo, array(

View File

@@ -40,10 +40,14 @@ if ($page == '' || $page == 'overview') {
\Froxlor\UI\Response::dynamic_error($e->getMessage()); \Froxlor\UI\Response::dynamic_error($e->getMessage());
} }
UI::twigBuffer('user/table.html.twig', [ UI::twigBuffer('user/table.html.twig', [
'listing' => \Froxlor\UI\Listing::format($collection, $plan_list_data['plan_list']), 'listing' => \Froxlor\UI\Listing::format($collection, $plan_list_data['plan_list']),
]); 'actions_links' => [[
UI::twigOutputBuffer(); 'href' => $linker->getLink(['section' => 'plans', 'page' => $page, 'action' => 'add']),
'label' => $lng['admin']['plans']['add']
]]
]);
UI::twigOutputBuffer();
} elseif ($action == 'delete' && $id != 0) { } elseif ($action == 'delete' && $id != 0) {
try { try {

View File

@@ -33,75 +33,40 @@ if (Settings::IsInList('panel.customer_hide_options', 'domains')) {
$id = (int) Request::get('id'); $id = (int) Request::get('id');
if ($page == 'overview') { if ($page == 'overview' || $page == 'domains') {
$log->logAction(\Froxlor\FroxlorLogger::USR_ACTION, LOG_NOTICE, "viewed customer_domains");
eval("echo \"" . \Froxlor\UI\Template::getTemplate("domains/domains") . "\";");
} elseif ($page == 'domains') {
if ($action == '') { if ($action == '') {
$log->logAction(\Froxlor\FroxlorLogger::USR_ACTION, LOG_NOTICE, "viewed customer_domains::domains"); $log->logAction(\Froxlor\FroxlorLogger::USR_ACTION, LOG_NOTICE, "viewed customer_domains::domains");
$fields = array(
'd.domain_ace' => $lng['domains']['domainname'], $parentdomain_id = (int) Request::get('pid', '0');
'd.aliasdomain' => $lng['domains']['aliasdomain']
);
try { try {
// get total count $domain_list_data = include_once dirname(__FILE__) . '/lib/tablelisting/customer/tablelisting.domains.php';
$json_result = SubDomains::getLocal($userinfo)->listingCount(); $list = (new \Froxlor\UI\Collection(\Froxlor\Api\Commands\SubDomains::class, $userinfo))
$result = json_decode($json_result, true)['data']; //->addParam(['sql_search' => ['d.parentdomainid' => $parentdomain_id]])
// initialize pagination and filtering ->withPagination($domain_list_data['domain_list']['columns'])
$paging = new \Froxlor\UI\Pagination($userinfo, $fields, $result); ->getList();
// get list
$json_result = SubDomains::getLocal($userinfo, $paging->getApiCommandParams())->listing();
} catch (Exception $e) { } catch (Exception $e) {
\Froxlor\UI\Response::dynamic_error($e->getMessage()); \Froxlor\UI\Response::dynamic_error($e->getMessage());
} }
$json_result = SubDomains::getLocal($userinfo, ['sql_search' => ['d.parentdomainid' => 0]])->listing();
$result = json_decode($json_result, true)['data']; $result = json_decode($json_result, true)['data'];
$parentdomains_count = $result['count'];
$sortcode = $paging->getHtmlSortCode($lng); $actions_links = false;
$arrowcode = $paging->getHtmlArrowCode($filename . '?page=' . $page . '&s=' . $s); if (($userinfo['subdomains_used'] < $userinfo['subdomains'] || $userinfo['subdomains'] == '-1') && $parentdomains_count != 0) {
$searchcode = $paging->getHtmlSearchCode($lng); $actions_links = [[
$pagingcode = $paging->getHtmlPagingCode($filename . '?page=' . $page . '&s=' . $s); 'href' => $linker->getLink(['section' => 'domains', 'page' => 'domains', 'action' => 'add']),
$domains = ''; 'label' => $lng['domains']['subdomain_add']
$parentdomains_count = 0; ]];
$domains_count = $paging->getEntries();
$domain_array = array();
foreach ($result['list'] as $row) {
formatDomainEntry($row, $idna_convert);
if ($row['parentdomainid'] == '0' && $row['caneditdomain'] == '1') {
$parentdomains_count++;
}
$domain_array[$row['parentdomainname']][] = $row;
} }
foreach ($domain_array as $parentdomain => $sdomains) { UI::twigBuffer('user/table.html.twig', [
// PARENTDOMAIN 'listing' => \Froxlor\UI\Listing::format($list, $domain_list_data['domain_list']),
if (Settings::Get('system.awstats_enabled') == '1') { 'actions_links' => $actions_links,
$statsapp = 'awstats'; 'entity_info' => $lng['domains']['description']
} else { ]);
$statsapp = 'webalizer'; UI::twigOutputBuffer();
}
$row = [
'domain' => $idna_convert->decode($parentdomain)
];
eval("\$domains.=\"" . \Froxlor\UI\Template::getTemplate("domains/domains_delimiter") . "\";");
foreach ($sdomains as $domain) {
$row = \Froxlor\PhpHelper::htmlentitiesArray($domain);
// show docroot nicely
if (strpos($row['documentroot'], $userinfo['documentroot']) === 0) {
$row['documentroot'] = \Froxlor\FileDir::makeCorrectDir(str_replace($userinfo['documentroot'], "/", $row['documentroot']));
}
// get ssl-ips if activated
$show_ssledit = false;
if (Settings::Get('system.use_ssl') == '1' && \Froxlor\Domain\Domain::domainHasSslIpPort($row['id']) && $row['caneditdomain'] == '1' && $row['letsencrypt'] == 0) {
$show_ssledit = true;
}
eval("\$domains.=\"" . \Froxlor\UI\Template::getTemplate("domains/domains_domain") . "\";");
}
}
eval("echo \"" . \Froxlor\UI\Template::getTemplate("domains/domainlist") . "\";");
} elseif ($action == 'delete' && $id != 0) { } elseif ($action == 'delete' && $id != 0) {
try { try {
$json_result = SubDomains::getLocal($userinfo, array( $json_result = SubDomains::getLocal($userinfo, array(

View File

@@ -34,97 +34,18 @@ if (Settings::IsInList('panel.customer_hide_options', 'email')) {
$id = (int) Request::get('id'); $id = (int) Request::get('id');
if ($page == 'overview') { if ($page == 'overview' || $page == 'emails') {
$log->logAction(\Froxlor\FroxlorLogger::USR_ACTION, LOG_NOTICE, "viewed customer_email");
eval("echo \"" . \Froxlor\UI\Template::getTemplate("email/email") . "\";");
} elseif ($page == 'emails') {
if ($action == '') { if ($action == '') {
$log->logAction(\Froxlor\FroxlorLogger::USR_ACTION, LOG_NOTICE, "viewed customer_email::emails"); $log->logAction(\Froxlor\FroxlorLogger::USR_ACTION, LOG_NOTICE, "viewed customer_email::emails");
$fields = array(
'd.domain_ace' => $lng['domains']['domainname'],
'm.email_full' => $lng['emails']['emailaddress'],
'm.destination' => $lng['emails']['forwarders']
);
try { try {
// get total count $email_list_data = include_once dirname(__FILE__) . '/lib/tablelisting/customer/tablelisting.emails.php';
$json_result = Emails::getLocal($userinfo)->listingCount(); $list = (new \Froxlor\UI\Collection(\Froxlor\Api\Commands\Emails::class, $userinfo))
$result = json_decode($json_result, true)['data']; ->withPagination($email_list_data['email_list']['columns'])
// initialize pagination and filtering ->getList();
$paging = new \Froxlor\UI\Pagination($userinfo, $fields, $result);
// get list
$json_result = Emails::getLocal($userinfo, $paging->getApiCommandParams())->listing();
} catch (Exception $e) { } catch (Exception $e) {
\Froxlor\UI\Response::dynamic_error($e->getMessage()); \Froxlor\UI\Response::dynamic_error($e->getMessage());
} }
$result = json_decode($json_result, true)['data'];
$sortcode = $paging->getHtmlSortCode($lng);
$arrowcode = $paging->getHtmlArrowCode($filename . '?page=' . $page . '&s=' . $s);
$searchcode = $paging->getHtmlSearchCode($lng);
$pagingcode = $paging->getHtmlPagingCode($filename . '?page=' . $page . '&s=' . $s);
$emails = array();
$emailscount = $paging->getEntries();
foreach ($result['list'] as $row) {
if (! isset($emails[$row['domain']]) || ! is_array($emails[$row['domain']])) {
$emails[$row['domain']] = array();
}
$emails[$row['domain']][$row['email_full']] = $row;
}
if ($paging->sortfield == 'd.domain_ace' && $paging->sortorder == 'desc') {
krsort($emails);
} else {
ksort($emails);
}
$count = 0;
$accounts = '';
$emails_count = 0;
$domainname = '';
foreach ($emails as $domainid => $emailaddresses) {
if ($paging->sortfield == 'm.email_full' && $paging->sortorder == 'desc') {
krsort($emailaddresses);
} else {
ksort($emailaddresses);
}
foreach ($emailaddresses as $row) {
if ($domainname != $idna_convert->decode($row['domain'])) {
$domainname = $idna_convert->decode($row['domain']);
eval("\$accounts.=\"" . \Froxlor\UI\Template::getTemplate("email/emails_domain") . "\";");
}
$emails_count ++;
$row['email'] = $idna_convert->decode($row['email']);
$row['email_full'] = $idna_convert->decode($row['email_full']);
$row['destination'] = explode(' ', $row['destination']);
uasort($row['destination'], 'strcasecmp');
$dest_list = $row['destination'];
foreach ($dest_list as $dest_id => $destination) {
$row['destination'][$dest_id] = $idna_convert->decode($row['destination'][$dest_id]);
if ($row['destination'][$dest_id] == $row['email_full']) {
unset($row['destination'][$dest_id]);
}
}
$destinations_count = count($row['destination']);
$row['destination'] = implode(', ', $row['destination']);
if (strlen($row['destination']) > 35) {
$row['destination'] = substr($row['destination'], 0, 32) . '... (' . $destinations_count . ')';
}
$row['mboxsize'] = \Froxlor\PhpHelper::sizeReadable($row['mboxsize'], 'GiB', 'bi', '%01.' . (int) Settings::Get('panel.decimal_places') . 'f %s');
$row = \Froxlor\PhpHelper::htmlentitiesArray($row);
eval("\$accounts.=\"" . \Froxlor\UI\Template::getTemplate("email/emails_email") . "\";");
$count ++;
}
}
$result_stmt = Database::prepare(" $result_stmt = Database::prepare("
SELECT COUNT(`id`) as emaildomains SELECT COUNT(`id`) as emaildomains
@@ -136,7 +57,20 @@ if ($page == 'overview') {
)); ));
$emaildomains_count = $result2['emaildomains']; $emaildomains_count = $result2['emaildomains'];
eval("echo \"" . \Froxlor\UI\Template::getTemplate("email/emails") . "\";"); $actions_links = false;
if (($userinfo['emails_used'] < $userinfo['emails'] || $userinfo['emails'] == '-1') && $emaildomains_count !=0) {
$actions_links = [[
'href' => $linker->getLink(['section' => 'email', 'page' => $page, 'action' => 'add']),
'label' => $lng['emails']['emails_add']
]];
}
UI::twigBuffer('user/table.html.twig', [
'listing' => \Froxlor\UI\Listing::format($list, $email_list_data['email_list']),
'actions_links' => $actions_links,
'entity_info' => $lng['emails']['description']
]);
UI::twigOutputBuffer();
} elseif ($action == 'delete' && $id != 0) { } elseif ($action == 'delete' && $id != 0) {
try { try {
$json_result = Emails::getLocal($userinfo, array( $json_result = Emails::getLocal($userinfo, array(

View File

@@ -33,10 +33,7 @@ if (Settings::IsInList('panel.customer_hide_options', 'extras')) {
$id = (int) Request::get('id'); $id = (int) Request::get('id');
if ($page == 'overview') { if ($page == 'overview' || $page == 'htpasswds') {
$log->logAction(\Froxlor\FroxlorLogger::USR_ACTION, LOG_NOTICE, "viewed customer_extras");
eval("echo \"" . \Froxlor\UI\Template::getTemplate("extras/extras") . "\";");
} elseif ($page == 'htpasswds') {
// redirect if this customer sub-page is hidden via settings // redirect if this customer sub-page is hidden via settings
if (Settings::IsInList('panel.customer_hide_options', 'extras.directoryprotection')) { if (Settings::IsInList('panel.customer_hide_options', 'extras.directoryprotection')) {
@@ -50,36 +47,23 @@ if ($page == 'overview') {
'path' => $lng['panel']['path'] 'path' => $lng['panel']['path']
); );
try { try {
// get total count $htpasswd_list_data = include_once dirname(__FILE__) . '/lib/tablelisting/customer/tablelisting.htpasswd.php';
$json_result = DirProtections::getLocal($userinfo)->listingCount(); $list = (new \Froxlor\UI\Collection(\Froxlor\Api\Commands\DirProtections::class, $userinfo))
$result = json_decode($json_result, true)['data']; ->withPagination($htpasswd_list_data['htpasswd_list']['columns'])
// initialize pagination and filtering ->getList();
$paging = new \Froxlor\UI\Pagination($userinfo, $fields, $result);
// get list
$json_result = DirProtections::getLocal($userinfo, $paging->getApiCommandParams())->listing();
} catch (Exception $e) { } catch (Exception $e) {
\Froxlor\UI\Response::dynamic_error($e->getMessage()); \Froxlor\UI\Response::dynamic_error($e->getMessage());
} }
$result = json_decode($json_result, true)['data'];
$sortcode = $paging->getHtmlSortCode($lng); UI::twigBuffer('user/table.html.twig', [
$arrowcode = $paging->getHtmlArrowCode($filename . '?page=' . $page . '&s=' . $s); 'listing' => \Froxlor\UI\Listing::format($list, $htpasswd_list_data['htpasswd_list']),
$searchcode = $paging->getHtmlSearchCode($lng); 'actions_links' => [[
$pagingcode = $paging->getHtmlPagingCode($filename . '?page=' . $page . '&s=' . $s); 'href' => $linker->getLink(['section' => 'extras', 'page' => 'htpasswds', 'action' => 'add']),
$count = 0; 'label' => $lng['extras']['directoryprotection_add']
$htpasswds = ''; ]],
'entity_info' => $lng['extras']['description']
foreach ($result['list'] as $row) { ]);
if (strpos($row['path'], $userinfo['documentroot']) === 0) { UI::twigOutputBuffer();
$row['path'] = str_replace($userinfo['documentroot'], "/", $row['path']);
}
$row['path'] = \Froxlor\FileDir::makeCorrectDir($row['path']);
$row = \Froxlor\PhpHelper::htmlentitiesArray($row);
eval("\$htpasswds.=\"" . \Froxlor\UI\Template::getTemplate("extras/htpasswds_htpasswd") . "\";");
$count ++;
}
eval("echo \"" . \Froxlor\UI\Template::getTemplate("extras/htpasswds") . "\";");
} elseif ($action == 'delete' && $id != 0) { } elseif ($action == 'delete' && $id != 0) {
try { try {
$json_result = DirProtections::getLocal($userinfo, array( $json_result = DirProtections::getLocal($userinfo, array(
@@ -181,51 +165,27 @@ if ($page == 'overview') {
if ($action == '') { if ($action == '') {
$log->logAction(\Froxlor\FroxlorLogger::USR_ACTION, LOG_NOTICE, "viewed customer_extras::htaccess"); $log->logAction(\Froxlor\FroxlorLogger::USR_ACTION, LOG_NOTICE, "viewed customer_extras::htaccess");
$fields = array(
'path' => $lng['panel']['path'],
'options_indexes' => $lng['extras']['view_directory'],
'error404path' => $lng['extras']['error404path'],
'error403path' => $lng['extras']['error403path'],
'error500path' => $lng['extras']['error500path'],
'options_cgi' => $lng['extras']['execute_perl']
);
try {
// get total count
$json_result = DirOptions::getLocal($userinfo)->listingCount();
$result = json_decode($json_result, true)['data'];
// initialize pagination and filtering
$paging = new \Froxlor\UI\Pagination($userinfo, $fields, $result);
// get list
$json_result = DirOptions::getLocal($userinfo, $paging->getApiCommandParams())->listing();
} catch (Exception $e) {
\Froxlor\UI\Response::dynamic_error($e->getMessage());
}
$result = json_decode($json_result, true)['data'];
$sortcode = $paging->getHtmlSortCode($lng);
$arrowcode = $paging->getHtmlArrowCode($filename . '?page=' . $page . '&s=' . $s);
$searchcode = $paging->getHtmlSearchCode($lng);
$pagingcode = $paging->getHtmlPagingCode($filename . '?page=' . $page . '&s=' . $s);
$count = 0;
$htaccess = '';
$cperlenabled = \Froxlor\Customer\Customer::customerHasPerlEnabled($userinfo['customerid']); $cperlenabled = \Froxlor\Customer\Customer::customerHasPerlEnabled($userinfo['customerid']);
foreach ($result['list'] as $row) { try {
if (strpos($row['path'], $userinfo['documentroot']) === 0) { $htaccess_list_data = include_once dirname(__FILE__) . '/lib/tablelisting/customer/tablelisting.htaccess.php';
$row['path'] = str_replace($userinfo['documentroot'], "/", $row['path']); $list = (new \Froxlor\UI\Collection(\Froxlor\Api\Commands\DirOptions::class, $userinfo))
} ->withPagination($htaccess_list_data['htaccess_list']['columns'])
$row['path'] = \Froxlor\FileDir::makeCorrectDir($row['path']); ->getList();
$row['options_indexes'] = str_replace('1', $lng['panel']['yes'], $row['options_indexes']); } catch (Exception $e) {
$row['options_indexes'] = str_replace('0', $lng['panel']['no'], $row['options_indexes']); \Froxlor\UI\Response::dynamic_error($e->getMessage());
$row['options_cgi'] = str_replace('1', $lng['panel']['yes'], $row['options_cgi']);
$row['options_cgi'] = str_replace('0', $lng['panel']['no'], $row['options_cgi']);
$row = \Froxlor\PhpHelper::htmlentitiesArray($row);
eval("\$htaccess.=\"" . \Froxlor\UI\Template::getTemplate("extras/htaccess_htaccess") . "\";");
$count ++;
} }
eval("echo \"" . \Froxlor\UI\Template::getTemplate("extras/htaccess") . "\";"); UI::twigBuffer('user/table.html.twig', [
'listing' => \Froxlor\UI\Listing::format($list, $htaccess_list_data['htaccess_list']),
'add_link' => [
'href' => $linker->getLink(['section' => 'extras', 'page' => 'htaccess', 'action' => 'add']),
'label' => $lng['extras']['pathoptions_add']
],
'entity_info' => $lng['extras']['description']
]);
UI::twigOutputBuffer();
} elseif ($action == 'delete' && $id != 0) { } elseif ($action == 'delete' && $id != 0) {
try { try {
$json_result = DirOptions::getLocal($userinfo, array( $json_result = DirOptions::getLocal($userinfo, array(
@@ -363,7 +323,7 @@ if ($page == 'overview') {
\Froxlor\UI\Response::standard_success('backupscheduled'); \Froxlor\UI\Response::standard_success('backupscheduled');
} else { } else {
if (! empty($existing_backupJob)) { if (!empty($existing_backupJob)) {
$action = "abort"; $action = "abort";
$row = $existing_backupJob['data']; $row = $existing_backupJob['data'];
@@ -371,18 +331,19 @@ if ($page == 'overview') {
$row['backup_web'] = ($row['backup_web'] == '1') ? $lng['panel']['yes'] : $lng['panel']['no']; $row['backup_web'] = ($row['backup_web'] == '1') ? $lng['panel']['yes'] : $lng['panel']['no'];
$row['backup_mail'] = ($row['backup_mail'] == '1') ? $lng['panel']['yes'] : $lng['panel']['no']; $row['backup_mail'] = ($row['backup_mail'] == '1') ? $lng['panel']['yes'] : $lng['panel']['no'];
$row['backup_dbs'] = ($row['backup_dbs'] == '1') ? $lng['panel']['yes'] : $lng['panel']['no']; $row['backup_dbs'] = ($row['backup_dbs'] == '1') ? $lng['panel']['yes'] : $lng['panel']['no'];
}
$pathSelect = \Froxlor\FileDir::makePathfield($userinfo['documentroot'], $userinfo['guid'], $userinfo['guid']);
$backup_data = include_once dirname(__FILE__) . '/lib/formfields/customer/extras/formfield.backup.php';
$backup_form = \Froxlor\UI\HtmlForm::genHTMLForm($backup_data);
$title = $backup_data['backup']['title'];
$image = $backup_data['backup']['image'];
if (! empty($existing_backupJob)) {
// overwrite backup_form after we took everything from it we needed // overwrite backup_form after we took everything from it we needed
eval("\$backup_form = \"" . \Froxlor\UI\Template::getTemplate("extras/backup_listexisting") . "\";"); eval("\$backup_form = \"" . \Froxlor\UI\Template::getTemplate("extras/backup_listexisting") . "\";");
} }
eval("echo \"" . \Froxlor\UI\Template::getTemplate("extras/backup") . "\";");
$pathSelect = \Froxlor\FileDir::makePathfield($userinfo['documentroot'], $userinfo['guid'], $userinfo['guid']);
$backup_data = include_once dirname(__FILE__) . '/lib/formfields/customer/extras/formfield.backup.php';
UI::twigBuffer('user/form.html.twig', [
'formaction' => $linker->getLink(array('section' => 'extras')),
'formdata' => $backup_data['backup']
]);
UI::twigOutputBuffer();
} }
} }
} else { } else {

View File

@@ -32,50 +32,32 @@ if (Settings::IsInList('panel.customer_hide_options', 'ftp')) {
$id = (int) Request::get('id', 0); $id = (int) Request::get('id', 0);
if ($page == 'overview') { if ($page == 'overview' || $page == 'accounts') {
$log->logAction(\Froxlor\FroxlorLogger::USR_ACTION, LOG_NOTICE, "viewed customer_ftp");
eval("echo \"" . \Froxlor\UI\Template::getTemplate('ftp/ftp') . "\";");
} elseif ($page == 'accounts') {
if ($action == '') { if ($action == '') {
$log->logAction(\Froxlor\FroxlorLogger::USR_ACTION, LOG_NOTICE, "viewed customer_ftp::accounts"); $log->logAction(\Froxlor\FroxlorLogger::USR_ACTION, LOG_NOTICE, "viewed customer_ftp::accounts");
$fields = array(
'username' => $lng['login']['username'],
'homedir' => $lng['panel']['path'],
'description' => $lng['panel']['ftpdesc']
);
try { try {
// get total count $ftp_list_data = include_once dirname(__FILE__) . '/lib/tablelisting/customer/tablelisting.ftps.php';
$json_result = Ftps::getLocal($userinfo)->listingCount(); $list = (new \Froxlor\UI\Collection(\Froxlor\Api\Commands\Ftps::class, $userinfo))
$result = json_decode($json_result, true)['data']; ->withPagination($ftp_list_data['ftp_list']['columns'])
// initialize pagination and filtering ->getList();
$paging = new \Froxlor\UI\Pagination($userinfo, $fields, $result);
// get list
$json_result = Ftps::getLocal($userinfo, $paging->getApiCommandParams())->listing();
} catch (Exception $e) { } catch (Exception $e) {
\Froxlor\UI\Response::dynamic_error($e->getMessage()); \Froxlor\UI\Response::dynamic_error($e->getMessage());
} }
$result = json_decode($json_result, true)['data'];
$ftps_count = $paging->getEntries();
$sortcode = $paging->getHtmlSortCode($lng);
$arrowcode = $paging->getHtmlArrowCode($filename . '?page=' . $page . '&s=' . $s);
$searchcode = $paging->getHtmlSearchCode($lng);
$pagingcode = $paging->getHtmlPagingCode($filename . '?page=' . $page . '&s=' . $s);
$count = 0;
$accounts = '';
foreach ($result['list'] as $row) { $actions_links = false;
if (strpos($row['homedir'], $userinfo['documentroot']) === 0) { if ($userinfo['ftps_used'] < $userinfo['ftps'] || $userinfo['ftps'] == '-1') {
$row['documentroot'] = str_replace($userinfo['documentroot'], "/", $row['homedir']); $actions_links = [[
} else { 'href' => $linker->getLink(['section' => 'ftp', 'page' => 'accounts', 'action' => 'add']),
$row['documentroot'] = $row['homedir']; 'label' => $lng['ftp']['account_add']
} ]];
$row['documentroot'] = \Froxlor\FileDir::makeCorrectDir($row['documentroot']);
$row = \Froxlor\PhpHelper::htmlentitiesArray($row);
eval("\$accounts.=\"" . \Froxlor\UI\Template::getTemplate('ftp/accounts_account') . "\";");
$count++;
} }
eval("echo \"" . \Froxlor\UI\Template::getTemplate('ftp/accounts') . "\";"); UI::twigBuffer('user/table.html.twig', [
'listing' => \Froxlor\UI\Listing::format($list, $ftp_list_data['ftp_list']),
'actions_links' => $actions_links,
'entity_info' => $lng['ftp']['description']
]);
UI::twigOutputBuffer();
} elseif ($action == 'delete' && $id != 0) { } elseif ($action == 'delete' && $id != 0) {
try { try {
$json_result = Ftps::getLocal($userinfo, array( $json_result = Ftps::getLocal($userinfo, array(

View File

@@ -38,65 +38,41 @@ Database::needRoot(false);
$id = (int) Request::get('id'); $id = (int) Request::get('id');
if ($page == 'overview') { if ($page == 'overview' || $page == 'mysqls') {
$log->logAction(\Froxlor\FroxlorLogger::USR_ACTION, LOG_NOTICE, "viewed customer_mysql");
Database::needSqlData();
$sql = Database::getSqlData();
$lng['mysql']['description'] = str_replace('<SQL_HOST>', $sql['host'], $lng['mysql']['description']);
eval("echo \"" . \Froxlor\UI\Template::getTemplate('mysql/mysql') . "\";");
} elseif ($page == 'mysqls') {
if ($action == '') { if ($action == '') {
$log->logAction(\Froxlor\FroxlorLogger::USR_ACTION, LOG_NOTICE, "viewed customer_mysql::mysqls"); $log->logAction(\Froxlor\FroxlorLogger::USR_ACTION, LOG_NOTICE, "viewed customer_mysql::mysqls");
$fields = array(
'databasename' => $lng['mysql']['databasename'],
'description' => $lng['mysql']['databasedescription']
);
try {
// get total count
$json_result = Mysqls::getLocal($userinfo)->listingCount();
$result = json_decode($json_result, true)['data'];
// initialize pagination and filtering
$paging = new \Froxlor\UI\Pagination($userinfo, $fields, $result);
// get list
$json_result = Mysqls::getLocal($userinfo, $paging->getApiCommandParams())->listing();
} catch (Exception $e) {
\Froxlor\UI\Response::dynamic_error($e->getMessage());
}
$result = json_decode($json_result, true)['data'];
$mysqls_count = $paging->getEntries();
$sortcode = $paging->getHtmlSortCode($lng);
$arrowcode = $paging->getHtmlArrowCode($filename . '?page=' . $page . '&s=' . $s);
$searchcode = $paging->getHtmlSearchCode($lng);
$pagingcode = $paging->getHtmlPagingCode($filename . '?page=' . $page . '&s=' . $s);
$count = 0;
$mysqls = '';
$dbservers_stmt = Database::query("SELECT COUNT(DISTINCT `dbserver`) as numservers FROM `" . TABLE_PANEL_DATABASES . "`"); $dbservers_stmt = Database::query("SELECT COUNT(DISTINCT `dbserver`) as numservers FROM `" . TABLE_PANEL_DATABASES . "`");
$dbserver = $dbservers_stmt->fetch(PDO::FETCH_ASSOC); $dbserver = $dbservers_stmt->fetch(PDO::FETCH_ASSOC);
$count_mysqlservers = $dbserver['numservers']; $count_mysqlservers = $dbserver['numservers'];
// Begin root-session try {
Database::needRoot(true); $mysql_list_data = include_once dirname(__FILE__) . '/lib/tablelisting/customer/tablelisting.mysqls.php';
foreach ($result['list'] as $row) { $list = (new \Froxlor\UI\Collection(\Froxlor\Api\Commands\Mysqls::class, $userinfo))
$row = \Froxlor\PhpHelper::htmlentitiesArray($row); ->withPagination($mysql_list_data['mysql_list']['columns'])
$mbdata_stmt = Database::prepare("SELECT SUM(data_length + index_length) as MB FROM information_schema.TABLES ->getList();
WHERE table_schema = :table_schema } catch (Exception $e) {
GROUP BY table_schema"); \Froxlor\UI\Response::dynamic_error($e->getMessage());
$mbdata = Database::pexecute_first($mbdata_stmt, array(
"table_schema" => $row['databasename']
));
if (!$mbdata) {
$mbdata = array('MB' => 0);
}
$row['size'] = \Froxlor\PhpHelper::sizeReadable($mbdata['MB'], 'GiB', 'bi', '%01.' . (int) Settings::Get('panel.decimal_places') . 'f %s');
eval("\$mysqls.=\"" . \Froxlor\UI\Template::getTemplate('mysql/mysqls_database') . "\";");
$count++;
} }
Database::needRoot(false);
// End root-session
eval("echo \"" . \Froxlor\UI\Template::getTemplate('mysql/mysqls') . "\";"); Database::needSqlData();
$sql = Database::getSqlData();
$lng['mysql']['description'] = str_replace('<SQL_HOST>', $sql['host'], $lng['mysql']['description']);
$actions_links = false;
if ($userinfo['mysqls_used'] < $userinfo['mysqls'] || $userinfo['mysqls'] == '-1') {
$actions_links = [[
'href' => $linker->getLink(['section' => 'mysql', 'page' => 'mysqls', 'action' => 'add']),
'label' => $lng['mysql']['database_create']
]];
}
UI::twigBuffer('user/table.html.twig', [
'listing' => \Froxlor\UI\Listing::format($list, $mysql_list_data['mysql_list']),
'actions_links' => $actions_links,
'entity_info' => $lng['mysql']['description']
]);
UI::twigOutputBuffer();
} elseif ($action == 'delete' && $id != 0) { } elseif ($action == 'delete' && $id != 0) {
try { try {

View File

@@ -19,13 +19,13 @@ if (! defined('AREA')) {
* *
*/ */
use Froxlor\Api\Commands\DomainZones as DomainZones; use Froxlor\Api\Commands\DomainZones;
use Froxlor\UI\Request; use Froxlor\UI\Request;
// This file is being included in admin_domains and customer_domains // This file is being included in admin_domains and customer_domains
// and therefore does not need to require lib/init.php // and therefore does not need to require lib/init.php
$domain_id = (int) Request::get(['domain_id']); $domain_id = (int) Request::get('domain_id');
$record = isset($_POST['record']['record']) ? trim($_POST['record']['record']) : null; $record = isset($_POST['record']['record']) ? trim($_POST['record']['record']) : null;
$type = isset($_POST['record']['type']) ? $_POST['record']['type'] : 'A'; $type = isset($_POST['record']['type']) ? $_POST['record']['type'] : 'A';

View File

@@ -545,6 +545,6 @@ class DomainZones extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour
\Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::REBUILD_DNS); \Froxlor\System\Cronjob::inserttask(\Froxlor\Cron\TaskId::REBUILD_DNS);
return $this->response(true); return $this->response(true);
} }
return $this->response(null, 204); return $this->response(true, 304);
} }
} }

View File

@@ -3,7 +3,6 @@
namespace Froxlor\Api; namespace Froxlor\Api;
use Exception; use Exception;
use voku\helper\AntiXSS;
/** /**
* This file is part of the Froxlor project. * This file is part of the Froxlor project.
@@ -23,110 +22,111 @@ use voku\helper\AntiXSS;
*/ */
class FroxlorRPC class FroxlorRPC
{ {
/** /**
* validate a given request * validate a given request
* *
* @param $request * @param $request
* @return array * @return array
* @throws Exception * @throws Exception
*/ */
public static function validateRequest($request): array public static function validateRequest($request): array
{ {
// make basic authentication // make basic authentication
if (!isset($_SERVER['PHP_AUTH_USER']) || !self::validateAuth($_SERVER['PHP_AUTH_USER'], $_SERVER['PHP_AUTH_PW'])) { if (!isset($_SERVER['PHP_AUTH_USER']) || !self::validateAuth($_SERVER['PHP_AUTH_USER'], $_SERVER['PHP_AUTH_PW'])) {
header('WWW-Authenticate: Basic realm="API"'); if (@php_sapi_name() !== 'cli') {
throw new Exception('Unauthenticated. Please provide api user credentials.', 401); header('WWW-Authenticate: Basic realm="API"');
} }
throw new Exception('Unauthenticated. Please provide api user credentials.', 401);
}
// check if present // check if present
if (empty($request)) { if (empty($request)) {
throw new Exception('Empty request body.', 400); throw new Exception('Empty request body.', 400);
} }
// decode json request // decode json request
$decoded_request = json_decode($request, true); $decoded_request = json_decode($request, true);
// is it valid? // is it valid?
if (is_null($decoded_request)) { if (is_null($decoded_request)) {
throw new Exception('Invalid JSON Format.', 400); throw new Exception('Invalid JSON Format.', 400);
} }
return self::validateBody($decoded_request); return self::validateBody($decoded_request);
} }
/** /**
* validates the given api credentials * validates the given api credentials
* *
* @param string $key * @param string $key
* @param string $secret * @param string $secret
* @return boolean * @return boolean
*/ */
private static function validateAuth(string $key, string $secret): bool private static function validateAuth(string $key, string $secret): bool
{ {
$sel_stmt = \Froxlor\Database\Database::prepare( $sel_stmt = \Froxlor\Database\Database::prepare(
" "
SELECT ak.*, a.api_allowed as admin_api_allowed, c.api_allowed as cust_api_allowed, c.deactivated SELECT ak.*, a.api_allowed as admin_api_allowed, c.api_allowed as cust_api_allowed, c.deactivated
FROM `api_keys` ak FROM `api_keys` ak
LEFT JOIN `panel_admins` a ON a.adminid = ak.adminid LEFT JOIN `panel_admins` a ON a.adminid = ak.adminid
LEFT JOIN `panel_customers` c ON c.customerid = ak.customerid LEFT JOIN `panel_customers` c ON c.customerid = ak.customerid
WHERE `apikey` = :ak AND `secret` = :as WHERE `apikey` = :ak AND `secret` = :as
" "
); );
$result = \Froxlor\Database\Database::pexecute_first($sel_stmt, array( $result = \Froxlor\Database\Database::pexecute_first($sel_stmt, array(
'ak' => $key, 'ak' => $key,
'as' => $secret 'as' => $secret
), true, true); ), true, true);
if ($result) { if ($result) {
if ($result['apikey'] == $key && $result['secret'] == $secret && ($result['valid_until'] == -1 || $result['valid_until'] >= time( if ($result['apikey'] == $key && $result['secret'] == $secret && ($result['valid_until'] == -1 || $result['valid_until'] >= time()) && (($result['customerid'] == 0 && $result['admin_api_allowed'] == 1) || ($result['customerid'] > 0 && $result['cust_api_allowed'] == 1 && $result['deactivated'] == 0))) {
)) && (($result['customerid'] == 0 && $result['admin_api_allowed'] == 1) || ($result['customerid'] > 0 && $result['cust_api_allowed'] == 1 && $result['deactivated'] == 0))) { // get user to check whether api call is allowed
// get user to check whether api call is allowed if (!empty($result['allowed_from'])) {
if (!empty($result['allowed_from'])) { // @todo allow specification and validating of whole subnets later
// @todo allow specification and validating of whole subnets later $ip_list = explode(",", $result['allowed_from']);
$ip_list = explode(",", $result['allowed_from']); $access_ip = inet_ntop(inet_pton($_SERVER['REMOTE_ADDR']));
$access_ip = inet_ntop(inet_pton($_SERVER['REMOTE_ADDR'])); if (in_array($access_ip, $ip_list)) {
if (in_array($access_ip, $ip_list)) { return true;
return true; }
} } else {
} else { return true;
return true; }
} }
} }
} throw new Exception('Invalid authorization credentials', 403);
return false; }
}
/** /**
* validates the given command * validates the given command
* *
* @param array $request * @param array $request
* *
* @return array * @return array
* @throws Exception * @throws Exception
*/ */
private static function validateBody($request) private static function validateBody($request)
{ {
// check command exists // check command exists
if (empty($request['command'])) { if (empty($request['command'])) {
throw new Exception("Please provide a command.", 400); throw new Exception("Please provide a command.", 400);
} }
$command = explode(".", $request['command']); $command = explode(".", $request['command']);
if (count($command) != 2) { if (count($command) != 2) {
throw new Exception("The given command is invalid.", 400); throw new Exception("The given command is invalid.", 400);
} }
// simply check for file-existance, as we do not want to use our autoloader because this way // simply check for file-existance, as we do not want to use our autoloader because this way
// it will recognize non-api classes+methods as valid commands // it will recognize non-api classes+methods as valid commands
$apiclass = '\\Froxlor\\Api\\Commands\\' . $command[0]; $apiclass = '\\Froxlor\\Api\\Commands\\' . $command[0];
if (!class_exists($apiclass) || !@method_exists($apiclass, $command[1])) { if (!class_exists($apiclass) || !@method_exists($apiclass, $command[1])) {
throw new Exception("Unknown command", 400); throw new Exception("Unknown command", 400);
} }
return array( return array(
'command' => array( 'command' => array(
'class' => $command[0], 'class' => $command[0],
'method' => $command[1] 'method' => $command[1]
), ),
'params' => $request['params'] ?? null 'params' => $request['params'] ?? null
); );
} }
} }

View File

@@ -0,0 +1,47 @@
<?php
namespace Froxlor\UI\Callbacks;
use Froxlor\UI\Panel\UI;
/**
* This file is part of the Froxlor project.
* Copyright (c) 2010 the Froxlor Team (see authors).
*
* For the full copyright and license information, please view the COPYING
* file that was distributed with this source code. You can also view the
* COPYING file online at http://files.froxlor.org/misc/COPYING.txt
*
* @copyright (c) the authors
* @author Froxlor team <team@froxlor.org> (2010-)
* @license GPLv2 http://files.froxlor.org/misc/COPYING.txt
* @package Listing
*
*/
class Domain
{
public static function domainTarget(string $data, array $attributes): mixed
{
if (empty($attributes['aliasdomain'])) {
// path or redirect
if (preg_match('/^https?\:\/\//', $attributes['documentroot'])) {
return [
'type' => 'link',
'data' => [
'text' => $attributes['documentroot'],
'href' => $attributes['documentroot'],
'target' => '_blank'
]
];
} else {
// show docroot nicely
if (strpos($attributes['documentroot'], UI::getCurrentUser()['documentroot']) === 0) {
$attributes['documentroot'] = \Froxlor\FileDir::makeCorrectDir(str_replace(UI::getCurrentUser()['documentroot'], "/", $attributes['documentroot']));
}
return $attributes['documentroot'];
}
}
return UI::getLng('domains.aliasdomain') . ' ' . $attributes['aliasdomain'];
}
}

View File

@@ -0,0 +1,35 @@
<?php
namespace Froxlor\UI\Callbacks;
use Froxlor\Settings;
use Froxlor\PhpHelper;
/**
* This file is part of the Froxlor project.
* Copyright (c) 2010 the Froxlor Team (see authors).
*
* For the full copyright and license information, please view the COPYING
* file that was distributed with this source code. You can also view the
* COPYING file online at http://files.froxlor.org/misc/COPYING.txt
*
* @copyright (c) the authors
* @author Froxlor team <team@froxlor.org> (2010-)
* @license GPLv2 http://files.froxlor.org/misc/COPYING.txt
* @package Listing
*
*/
class Email
{
public static function account(string $data, array $attributes): mixed
{
return [
'type' => 'booleanWithInfo',
'data' => [
'checked' => $data != 0,
'info' => $data != 0 ? PhpHelper::sizeReadable($attributes['mboxsize'], 'GiB', 'bi', '%01.' . (int) Settings::Get('panel.decimal_places') . 'f %s') : ''
]
];
}
}

View File

@@ -0,0 +1,33 @@
<?php
namespace Froxlor\UI\Callbacks;
use Froxlor\UI\Panel\UI;
/**
* This file is part of the Froxlor project.
* Copyright (c) 2010 the Froxlor Team (see authors).
*
* For the full copyright and license information, please view the COPYING
* file that was distributed with this source code. You can also view the
* COPYING file online at http://files.froxlor.org/misc/COPYING.txt
*
* @copyright (c) the authors
* @author Froxlor team <team@froxlor.org> (2010-)
* @license GPLv2 http://files.froxlor.org/misc/COPYING.txt
* @package Listing
*
*/
class Ftp
{
public static function pathRelative(string $data, array $attributes): string
{
if (strpos($data, UI::getCurrentUser()['documentroot']) === 0) {
$data = str_replace(UI::getCurrentUser()['documentroot'], "/", $data);
}
$data = \Froxlor\FileDir::makeCorrectDir($data);
return $data;
}
}

View File

@@ -1,4 +1,5 @@
<?php <?php
namespace Froxlor\UI\Callbacks; namespace Froxlor\UI\Callbacks;
use Froxlor\UI\Panel\UI; use Froxlor\UI\Panel\UI;
@@ -21,38 +22,41 @@ use Froxlor\UI\Panel\UI;
class Impersonate class Impersonate
{ {
public static function admin(string $data, array $attributes): array public static function admin(string $data, array $attributes): mixed
{ {
$linker = UI::getLinker(); if (UI::getCurrentUser()['adminid'] != $attributes['adminid']) {
return [ $linker = UI::getLinker();
'type' => 'link', return [
'data' => [ 'type' => 'link',
'text' => $data, 'data' => [
'href' => $linker->getLink([ 'text' => $data,
'section' => 'admins', 'href' => $linker->getLink([
'page' => 'admins', 'section' => 'admins',
'action' => 'su', 'page' => 'admins',
'id' => $attributes['adminid'], 'action' => 'su',
]), 'id' => $attributes['adminid'],
] ]),
]; ]
} ];
}
return $data;
}
public static function customer(string $data, array $attributes): array public static function customer(string $data, array $attributes): array
{ {
$linker = UI::getLinker(); $linker = UI::getLinker();
return [ return [
'type' => 'link', 'type' => 'link',
'data' => [ 'data' => [
'text' => $data, 'text' => $data,
'href' => $linker->getLink([ 'href' => $linker->getLink([
'section' => 'customers', 'section' => 'customers',
'page' => 'customers', 'page' => 'customers',
'action' => 'su', 'action' => 'su',
'sort' => $attributes['loginname'], 'sort' => $attributes['loginname'],
'id' => $attributes['customerid'], 'id' => $attributes['customerid'],
]), ]),
] ]
]; ];
} }
} }

View File

@@ -0,0 +1,34 @@
<?php
namespace Froxlor\UI\Callbacks;
use Froxlor\Database\Database;
/**
* This file is part of the Froxlor project.
* Copyright (c) 2010 the Froxlor Team (see authors).
*
* For the full copyright and license information, please view the COPYING
* file that was distributed with this source code. You can also view the
* COPYING file online at http://files.froxlor.org/misc/COPYING.txt
*
* @copyright (c) the authors
* @author Froxlor team <team@froxlor.org> (2010-)
* @license GPLv2 http://files.froxlor.org/misc/COPYING.txt
* @package Listing
*
*/
class Mysql
{
public static function dbserver(string $data, array $attributes): string
{
// get sql-root access data
Database::needRoot(true, (int) $data);
Database::needSqlData();
$sql_root = Database::getSqlData();
Database::needRoot(false);
return $sql_root['caption'] . '<br><small>' . $sql_root['host'] . '</small>';
}
}

View File

@@ -1,6 +1,9 @@
<?php <?php
namespace Froxlor\UI\Callbacks; namespace Froxlor\UI\Callbacks;
use Froxlor\PhpHelper;
/** /**
* This file is part of the Froxlor project. * This file is part of the Froxlor project.
* Copyright (c) 2010 the Froxlor Team (see authors). * Copyright (c) 2010 the Froxlor Team (see authors).
@@ -18,22 +21,32 @@ namespace Froxlor\UI\Callbacks;
*/ */
class Text class Text
{ {
public static function boolean(?string $data): array public static function boolean(?string $data): array
{ {
return [ return [
'type' => 'boolean', 'type' => 'boolean',
'data' => (bool) $data 'data' => (bool) $data
]; ];
} }
public static function domainWithSan(string $data, array $attributes): array public static function domainWithSan(string $data, array $attributes): array
{ {
return [ return [
'type' => 'domainWithSan', 'type' => 'domainWithSan',
'data' => [ 'data' => [
'domain' => $data, 'domain' => $data,
'san' => implode(', ', $attributes['san'] ?? []), 'san' => implode(', ', $attributes['san'] ?? []),
] ]
]; ];
} }
public static function customerfullname(string $data, array $attributes): string
{
return \Froxlor\User::getCorrectFullUserDetails($attributes);
}
public static function size(string $data, array $attributes): string
{
return PhpHelper::sizeReadable($data, null, 'bi');
}
} }

View File

@@ -87,16 +87,23 @@ class Collection
public function has(string $column, string $class, string $parentKey = 'id', string $childKey = 'id', array $params = []): Collection public function has(string $column, string $class, string $parentKey = 'id', string $childKey = 'id', array $params = []): Collection
{ {
$this->has[] = [ $this->has[] = [
'column' => $column, 'column' => $column,
'class' => $class, 'class' => $class,
'parentKey' => $parentKey, 'parentKey' => $parentKey,
'childKey' => $childKey, 'childKey' => $childKey,
'params' => $params 'params' => $params
]; ];
return $this; return $this;
} }
public function addParam(array $keyval): Collection
{
$this->params = array_merge($this->params, $keyval);
return $this;
}
public function withPagination(array $columns): Collection public function withPagination(array $columns): Collection
{ {
// Get only searchable columns // Get only searchable columns

View File

@@ -12,10 +12,10 @@ use Froxlor\Settings;
* COPYING file online at http://files.froxlor.org/misc/COPYING.txt * COPYING file online at http://files.froxlor.org/misc/COPYING.txt
* *
* @copyright (c) the authors * @copyright (c) the authors
* @author Froxlor team <team@froxlor.org> (2010-) * @author Froxlor team <team@froxlor.org> (2010-)
* @license GPLv2 http://files.froxlor.org/misc/COPYING.txt * @license GPLv2 http://files.froxlor.org/misc/COPYING.txt
* @package API * @package API
* @since 0.10.0 * @since 0.10.0
* *
*/ */

View File

@@ -35,6 +35,13 @@ class UI
*/ */
private static $linker = null; private static $linker = null;
/**
* current logged in user
*
* @var array
*/
private static $userinfo = [];
/** /**
* default fallback theme * default fallback theme
* *
@@ -224,6 +231,16 @@ class UI
return self::$linker; return self::$linker;
} }
public static function setCurrentUser($userinfo = null)
{
self::$userinfo = $userinfo;
}
public static function getCurrentUser(): array
{
return self::$userinfo;
}
public static function setLng($lng = array()) public static function setLng($lng = array())
{ {
self::$lng = $lng; self::$lng = $lng;

View File

@@ -24,7 +24,7 @@ class User
$returnval = $userinfo['name'] . ', ' . $userinfo['firstname']; $returnval = $userinfo['name'] . ', ' . $userinfo['firstname'];
} else { } else {
if ($userinfo['name'] != '' && $userinfo['firstname'] != '') { if ($userinfo['name'] != '' && $userinfo['firstname'] != '') {
$returnval = $userinfo['name'] . ', ' . $userinfo['firstname'] . ' | ' . $userinfo['company']; $returnval = $userinfo['name'] . ', ' . $userinfo['firstname'] . '<br><small>' . $userinfo['company'] . '</small>';
} else { } else {
$returnval = $userinfo['company']; $returnval = $userinfo['company'];
} }

View File

@@ -14,6 +14,9 @@
* @package Formfields * @package Formfields
* *
*/ */
use Froxlor\Settings;
return array( return array(
'domain_add' => array( 'domain_add' => array(
'title' => $lng['domains']['subdomain_add'], 'title' => $lng['domains']['subdomain_add'],
@@ -41,19 +44,19 @@ return array(
), ),
'path' => array( 'path' => array(
'label' => $lng['panel']['path'], 'label' => $lng['panel']['path'],
'desc' => (\Froxlor\Settings::Get('panel.pathedit') != 'Dropdown' ? $lng['panel']['pathDescriptionSubdomain'] : null), 'desc' => (Settings::Get('panel.pathedit') != 'Dropdown' ? $lng['panel']['pathDescriptionSubdomain'] : null),
'type' => $pathSelect['type'], 'type' => $pathSelect['type'],
'select_var' => $pathSelect['select_var'] ?? '', 'select_var' => $pathSelect['select_var'] ?? '',
'value' => $pathSelect['value'], 'value' => $pathSelect['value'],
'note' => $pathSelect['note'] ?? '', 'note' => $pathSelect['note'] ?? '',
), ),
'url' => array( 'url' => array(
'visible' => (\Froxlor\Settings::Get('panel.pathedit') == 'Dropdown' ? true : false), 'visible' => (Settings::Get('panel.pathedit') == 'Dropdown' ? true : false),
'label' => $lng['panel']['urloverridespath'], 'label' => $lng['panel']['urloverridespath'],
'type' => 'text' 'type' => 'text'
), ),
'redirectcode' => array( 'redirectcode' => array(
'visible' => (\Froxlor\Settings::Get('customredirect.enabled') == '1' ? true : false), 'visible' => (Settings::Get('customredirect.enabled') == '1' ? true : false),
'label' => $lng['domains']['redirectifpathisurl'], 'label' => $lng['domains']['redirectifpathisurl'],
'desc' => $lng['domains']['redirectifpathisurlinfo'], 'desc' => $lng['domains']['redirectifpathisurlinfo'],
'type' => 'select', 'type' => 'select',
@@ -71,18 +74,18 @@ return array(
'select_var' => $openbasedir 'select_var' => $openbasedir
), ),
'phpsettingid' => array( 'phpsettingid' => array(
'visible' => (((int) \Froxlor\Settings::Get('system.mod_fcgid') == 1 || (int) \Froxlor\Settings::Get('phpfpm.enabled') == 1) && count($phpconfigs) > 0 ? true : false), 'visible' => (((int) Settings::Get('system.mod_fcgid') == 1 || (int) Settings::Get('phpfpm.enabled') == 1) && count($phpconfigs) > 0 ? true : false),
'label' => $lng['admin']['phpsettings']['title'], 'label' => $lng['admin']['phpsettings']['title'],
'type' => 'select', 'type' => 'select',
'select_var' => $phpconfigs, 'select_var' => $phpconfigs,
'selected' => (int) Settings::Get('phpfpm.enabled') == 1) ? Settings::Get('phpfpm.defaultini') : Settings::Get('system.mod_fcgid_defaultini') 'selected' => (int) Settings::Get('phpfpm.enabled') == 1 ? Settings::Get('phpfpm.defaultini') : Settings::Get('system.mod_fcgid_defaultini')
) )
) )
), ),
'section_bssl' => array( 'section_bssl' => array(
'title' => $lng['admin']['webserversettings_ssl'], 'title' => $lng['admin']['webserversettings_ssl'],
'image' => 'icons/domain_add.png', 'image' => 'icons/domain_add.png',
'visible' => \Froxlor\Settings::Get('system.use_ssl') == '1' ? ($ssl_ipsandports ? true : false) : false, 'visible' => Settings::Get('system.use_ssl') == '1' ? ($ssl_ipsandports ? true : false) : false,
'fields' => array( 'fields' => array(
'sslenabled' => array( 'sslenabled' => array(
'label' => $lng['admin']['domain_sslenabled'], 'label' => $lng['admin']['domain_sslenabled'],
@@ -98,7 +101,7 @@ return array(
'checked' => false 'checked' => false
), ),
'letsencrypt' => array( 'letsencrypt' => array(
'visible' => (\Froxlor\Settings::Get('system.leenabled') == '1' ? true : false), 'visible' => (Settings::Get('system.leenabled') == '1' ? true : false),
'label' => $lng['customer']['letsencrypt']['title'], 'label' => $lng['customer']['letsencrypt']['title'],
'desc' => $lng['customer']['letsencrypt']['description'], 'desc' => $lng['customer']['letsencrypt']['description'],
'type' => 'checkbox', 'type' => 'checkbox',
@@ -106,7 +109,7 @@ return array(
'checked' => false 'checked' => false
), ),
'http2' => array( 'http2' => array(
'visible' => ($ssl_ipsandports ? true : false) && \Froxlor\Settings::Get('system.webserver') != 'lighttpd' && \Froxlor\Settings::Get('system.http2_support') == '1', 'visible' => ($ssl_ipsandports ? true : false) && Settings::Get('system.webserver') != 'lighttpd' && Settings::Get('system.http2_support') == '1',
'label' => $lng['admin']['domain_http2']['title'], 'label' => $lng['admin']['domain_http2']['title'],
'desc' => $lng['admin']['domain_http2']['description'], 'desc' => $lng['admin']['domain_http2']['description'],
'type' => 'checkbox', 'type' => 'checkbox',

View File

@@ -23,7 +23,7 @@ return array(
'title' => $lng['emails']['account_add'], 'title' => $lng['emails']['account_add'],
'image' => 'icons/email_add.png', 'image' => 'icons/email_add.png',
'fields' => array( 'fields' => array(
'email_full' => array( 'emailaddr' => array(
'label' => $lng['emails']['emailaddress'], 'label' => $lng['emails']['emailaddress'],
'type' => 'label', 'type' => 'label',
'value' => $result['email_full'] 'value' => $result['email_full']

View File

@@ -23,7 +23,7 @@ return array(
'title' => $lng['emails']['forwarder_add'], 'title' => $lng['emails']['forwarder_add'],
'image' => 'icons/autoresponder_add.png', 'image' => 'icons/autoresponder_add.png',
'fields' => array( 'fields' => array(
'email_full' => array( 'emailaddr' => array(
'label' => $lng['emails']['from'], 'label' => $lng['emails']['from'],
'type' => 'label', 'type' => 'label',
'value' => $result['email_full'] 'value' => $result['email_full']

View File

@@ -17,7 +17,7 @@
return array( return array(
'backup' => array( 'backup' => array(
'title' => $lng['extras']['backup'], 'title' => $lng['extras']['backup'],
'image' => 'icons/backup_big.png', 'image' => 'fa-solid fa-server',
'sections' => array( 'sections' => array(
'section_a' => array( 'section_a' => array(
'title' => $lng['extras']['backup'], 'title' => $lng['extras']['backup'],
@@ -33,8 +33,9 @@ return array(
), ),
'path_protection_info' => array( 'path_protection_info' => array(
'label' => $lng['extras']['path_protection_label'], 'label' => $lng['extras']['path_protection_label'],
'type' => 'label', 'type' => 'infotext',
'value' => $lng['extras']['path_protection_info'] 'value' => $lng['extras']['path_protection_info'],
'classes' => 'fw-bold text-danger'
), ),
'backup_web' => array( 'backup_web' => array(
'label' => $lng['extras']['backup_web'], 'label' => $lng['extras']['backup_web'],

View File

@@ -17,7 +17,7 @@
return array( return array(
'htaccess_add' => array( 'htaccess_add' => array(
'title' => $lng['extras']['pathoptions_add'], 'title' => $lng['extras']['pathoptions_add'],
'image' => 'icons/htpasswd_add.png', 'image' => 'fa-solid fa-folder',
'sections' => array( 'sections' => array(
'section_a' => array( 'section_a' => array(
'title' => $lng['extras']['pathoptions_add'], 'title' => $lng['extras']['pathoptions_add'],

View File

@@ -17,7 +17,7 @@
return array( return array(
'htaccess_edit' => array( 'htaccess_edit' => array(
'title' => $lng['extras']['pathoptions_edit'], 'title' => $lng['extras']['pathoptions_edit'],
'image' => 'icons/htpasswd_edit.png', 'image' => 'fa-solid fa-folder',
'sections' => array( 'sections' => array(
'section_a' => array( 'section_a' => array(
'title' => $lng['extras']['pathoptions_edit'], 'title' => $lng['extras']['pathoptions_edit'],

View File

@@ -17,7 +17,7 @@
return array( return array(
'htpasswd_add' => array( 'htpasswd_add' => array(
'title' => $lng['extras']['directoryprotection_add'], 'title' => $lng['extras']['directoryprotection_add'],
'image' => 'icons/htpasswd_add.png', 'image' => 'fa-solid fa-lock',
'sections' => array( 'sections' => array(
'section_a' => array( 'section_a' => array(
'title' => $lng['extras']['directoryprotection_add'], 'title' => $lng['extras']['directoryprotection_add'],

View File

@@ -17,7 +17,7 @@
return array( return array(
'htpasswd_edit' => array( 'htpasswd_edit' => array(
'title' => $lng['extras']['directoryprotection_edit'], 'title' => $lng['extras']['directoryprotection_edit'],
'image' => 'icons/htpasswd_edit.png', 'image' => 'fa-solid fa-lock',
'sections' => array( 'sections' => array(
'section_a' => array( 'section_a' => array(
'title' => $lng['extras']['directoryprotection_edit'], 'title' => $lng['extras']['directoryprotection_edit'],

View File

@@ -362,6 +362,7 @@ if ($nosession == 1 && AREA != 'login') {
} }
UI::twig()->addGlobal('userinfo', ($userinfo ?? [])); UI::twig()->addGlobal('userinfo', ($userinfo ?? []));
UI::setCurrentUser($userinfo);
/** /**
* Logic moved out of lng-file * Logic moved out of lng-file

View File

@@ -83,7 +83,7 @@ return array(
'url' => 'customer_ftp.php', 'url' => 'customer_ftp.php',
'label' => $lng['menue']['ftp']['ftp'], 'label' => $lng['menue']['ftp']['ftp'],
'show_element' => (! \Froxlor\Settings::IsInList('panel.customer_hide_options', 'ftp')), 'show_element' => (! \Froxlor\Settings::IsInList('panel.customer_hide_options', 'ftp')),
'icon' => 'fa fa-transfer', 'icon' => 'fa fa-users',
'elements' => array( 'elements' => array(
array( array(
'url' => 'customer_ftp.php?page=accounts', 'url' => 'customer_ftp.php?page=accounts',

View File

@@ -16,81 +16,74 @@
* *
*/ */
use Froxlor\UI\Callbacks\Text;
use Froxlor\UI\Callbacks\Impersonate; use Froxlor\UI\Callbacks\Impersonate;
use Froxlor\UI\Callbacks\ProgressBar; use Froxlor\UI\Callbacks\ProgressBar;
use Froxlor\UI\Listing; use Froxlor\UI\Listing;
return [ return [
'customer_list' => [ 'customer_list' => [
'title' => $lng['admin']['customers'], 'title' => $lng['admin']['customers'],
'icon' => 'fa-solid fa-user', 'icon' => 'fa-solid fa-user',
'columns' => [ 'columns' => [
'c.loginname' => [ 'c.name' => [
'label' => $lng['login']['username'], 'label' => $lng['customer']['name'],
'column' => 'loginname', 'column' => 'name',
'format_callback' => [Impersonate::class, 'customer'], 'format_callback' => [Text::class, 'customerfullname'],
], ],
'a.loginname' => [ 'c.loginname' => [
'label' => $lng['admin']['admin'], 'label' => $lng['login']['username'],
'column' => 'admin.loginname', 'column' => 'loginname',
'format_callback' => [Impersonate::class, 'admin'], 'format_callback' => [Impersonate::class, 'customer'],
], ],
'c.name' => [ 'a.loginname' => [
'label' => $lng['customer']['name'], 'label' => $lng['admin']['admin'],
'column' => 'name', 'column' => 'admin.loginname',
], 'format_callback' => [Impersonate::class, 'admin'],
'c.email' => [ ],
'label' => $lng['customer']['email'], 'c.email' => [
'column' => 'email', 'label' => $lng['customer']['email'],
], 'column' => 'email',
'c.firstname' => [ ],
'label' => $lng['customer']['firstname'], 'c.diskspace' => [
'column' => 'firstname', 'label' => $lng['customer']['diskspace'],
], 'column' => 'diskspace',
'c.company' => [ 'format_callback' => [ProgressBar::class, 'diskspace'],
'label' => $lng['customer']['company'], ],
'column' => 'company', 'c.traffic' => [
], 'label' => $lng['customer']['traffic'],
'c.diskspace' => [ 'column' => 'traffic',
'label' => $lng['customer']['diskspace'], 'format_callback' => [ProgressBar::class, 'traffic'],
'column' => 'diskspace', ],
'format_callback' => [ProgressBar::class, 'diskspace'], ],
], 'visible_columns' => Listing::getVisibleColumnsForListing('customer_list', [
'c.traffic' => [ 'c.name',
'label' => $lng['customer']['traffic'], 'c.loginname',
'column' => 'traffic', 'a.loginname',
'format_callback' => [ProgressBar::class, 'traffic'], 'c.email',
], 'c.diskspace',
], 'c.traffic',
'visible_columns' => Listing::getVisibleColumnsForListing('customer_list', [ ]),
'c.loginname', 'actions' => [
'a.loginname', 'edit' => [
'c.email', 'icon' => 'fa fa-edit',
'c.firstname', 'href' => [
'c.company', 'section' => 'customers',
'c.diskspace', 'page' => 'customers',
'c.traffic', 'action' => 'edit',
]), 'id' => ':customerid'
'actions' => [ ],
'edit' => [ ],
'icon' => 'fa fa-edit', 'delete' => [
'href' => [ 'icon' => 'fa fa-trash',
'section' => 'customers', 'class' => 'text-danger',
'page' => 'customers', 'href' => [
'action' => 'edit', 'section' => 'customers',
'id' => ':customerid' 'page' => 'customers',
], 'action' => 'delete',
], 'id' => ':customerid'
'delete' => [ ],
'icon' => 'fa fa-trash', ],
'class' => 'text-danger', ],
'href' => [ ]
'section' => 'customers',
'page' => 'customers',
'action' => 'delete',
'id' => ':customerid'
],
],
],
]
]; ];

View File

@@ -16,86 +16,76 @@
* *
*/ */
use Froxlor\UI\Callbacks\Text;
use Froxlor\UI\Callbacks\Impersonate; use Froxlor\UI\Callbacks\Impersonate;
use Froxlor\UI\Listing; use Froxlor\UI\Listing;
return [ return [
'domain_list' => [ 'domain_list' => [
'title' => $lng['admin']['domains'], 'title' => $lng['admin']['domains'],
'icon' => 'fa-solid fa-user', 'icon' => 'fa-solid fa-user',
'columns' => [ 'columns' => [
'd.domain_ace' => [ 'd.domain_ace' => [
'label' => $lng['domains']['domainname'], 'label' => $lng['domains']['domainname'],
'column' => 'domain_ace', 'column' => 'domain_ace',
'sortable' => true, ],
], 'c.name' => [
'c.name' => [ 'label' => $lng['customer']['name'],
'label' => $lng['customer']['name'], 'column' => 'customer.name',
'column' => 'customer.name', 'format_callback' => [Text::class, 'customerfullname'],
], ],
'c.firstname' => [ 'c.loginname' => [
'label' => $lng['customer']['firstname'], 'label' => $lng['login']['username'],
'column' => 'customer.firstname', 'column' => 'customer.loginname',
], 'format_callback' => [Impersonate::class, 'customer'],
'c.company' => [ ],
'label' => $lng['customer']['company'], 'd.aliasdomain' => [
'column' => 'customer.company', 'label' => $lng['domains']['aliasdomain'],
], 'column' => 'aliasdomain',
'c.loginname' => [ ],
'label' => $lng['login']['username'], ],
'column' => 'customer.loginname', 'visible_columns' => Listing::getVisibleColumnsForListing('domain_list', [
'format_callback' => [Impersonate::class, 'customer'], 'd.domain_ace',
'sortable' => true, 'c.name',
], 'c.loginname',
'd.aliasdomain' => [ 'd.aliasdomain',
'label' => $lng['domains']['aliasdomain'], ]),
'column' => 'aliasdomain', 'actions' => [
], 'edit' => [
], 'icon' => 'fa fa-edit',
'visible_columns' => Listing::getVisibleColumnsForListing('domain_list', [ 'href' => [
'd.domain_ace', 'section' => 'domains',
'c.name', 'page' => 'domains',
'c.firstname', 'action' => 'edit',
'c.company', 'id' => ':id'
'c.loginname', ],
'd.aliasdomain', ],
]), 'logfiles' => [
'actions' => [ 'icon' => 'fa fa-file',
'edit' => [ 'href' => [
'icon' => 'fa fa-edit', 'section' => 'domains',
'href' => [ 'page' => 'logfiles',
'section' => 'domains', 'domain_id' => ':id'
'page' => 'domains', ],
'action' => 'edit', ],
'id' => ':id' 'domaindnseditor' => [
], 'icon' => 'fa fa-globe',
], 'href' => [
'logfiles' => [ 'section' => 'domains',
'icon' => 'fa fa-file', 'page' => 'domaindnseditor',
'href' => [ 'domain_id' => ':id'
'section' => 'domains', ],
'page' => 'logfiles', ],
'domain_id' => ':id' 'delete' => [
], 'icon' => 'fa fa-trash',
], 'class' => 'text-danger',
'domaindnseditor' => [ 'href' => [
'icon' => 'fa fa-globe', 'section' => 'domains',
'href' => [ 'page' => 'domains',
'section' => 'domains', 'action' => 'delete',
'page' => 'domaindnseditor', 'id' => ':id'
'domain_id' => ':id' ],
], ]
], ]
'delete' => [ ]
'icon' => 'fa fa-trash',
'class' => 'text-danger',
'href' => [
'section' => 'domains',
'page' => 'domains',
'action' => 'delete',
'id' => ':id'
],
],
]
]
]; ];

View File

@@ -21,7 +21,7 @@ use Froxlor\UI\Listing;
return [ return [
'plan_list' => [ 'plan_list' => [
'title' => $lng['domains']['ssl_certificates'], 'title' => $lng['admin']['plans']['plans'],
'icon' => 'fa-solid fa-user', 'icon' => 'fa-solid fa-user',
'columns' => [ 'columns' => [
'p.name' => [ 'p.name' => [

View File

@@ -0,0 +1,79 @@
<?php
/**
* This file is part of the Froxlor project.
* Copyright (c) 2010 the Froxlor Team (see authors).
*
* For the full copyright and license information, please view the COPYING
* file that was distributed with this source code. You can also view the
* COPYING file online at http://files.froxlor.org/misc/COPYING.txt
*
* @copyright (c) the authors
* @author Froxlor team <team@froxlor.org> (2010-)
* @author Maurice Preuß <hello@envoyr.com>
* @license GPLv2 http://files.froxlor.org/misc/COPYING.txt
* @package Tabellisting
*
*/
use Froxlor\UI\Callbacks\Domain;
use Froxlor\UI\Listing;
return [
'domain_list' => [
'title' => $lng['admin']['domains'],
'icon' => 'fa-solid fa-user',
'columns' => [
'd.domain_ace' => [
'label' => $lng['domains']['domainname'],
'column' => 'domain_ace',
],
'd.documentroot' => [
'label' => $lng['panel']['path'],
'column' => 'documentroot',
'format_callback' => [Domain::class, 'domainTarget'],
]
],
'visible_columns' => Listing::getVisibleColumnsForListing('domain_list', [
'd.domain_ace',
'd.documentroot'
]),
'actions' => [
'edit' => [
'icon' => 'fa fa-edit',
'href' => [
'section' => 'domains',
'page' => 'domains',
'action' => 'edit',
'id' => ':id'
],
],
'logfiles' => [
'icon' => 'fa fa-file',
'href' => [
'section' => 'domains',
'page' => 'logfiles',
'domain_id' => ':id'
],
],
'domaindnseditor' => [
'icon' => 'fa fa-globe',
'href' => [
'section' => 'domains',
'page' => 'domaindnseditor',
'domain_id' => ':id'
],
],
'delete' => [
'icon' => 'fa fa-trash',
'class' => 'text-danger',
'href' => [
'section' => 'domains',
'page' => 'domains',
'action' => 'delete',
'id' => ':id'
],
]
]
]
];

View File

@@ -0,0 +1,83 @@
<?php
/**
* This file is part of the Froxlor project.
* Copyright (c) 2010 the Froxlor Team (see authors).
*
* For the full copyright and license information, please view the COPYING
* file that was distributed with this source code. You can also view the
* COPYING file online at http://files.froxlor.org/misc/COPYING.txt
*
* @copyright (c) the authors
* @author Froxlor team <team@froxlor.org> (2010-)
* @author Maurice Preuß <hello@envoyr.com>
* @license GPLv2 http://files.froxlor.org/misc/COPYING.txt
* @package Tabellisting
*
*/
use Froxlor\UI\Callbacks\Email;
use Froxlor\UI\Callbacks\Text;
use Froxlor\UI\Listing;
return [
'email_list' => [
'title' => $lng['menue']['email']['emails'],
'icon' => 'fa-solid fa-envelope',
'columns' => [
'm.email_full' => [
'label' => $lng['emails']['emailaddress'],
'column' => 'email_full',
],
'm.destination' => [
'label' => $lng['emails']['forwarders'],
'column' => 'destination',
// @todo formatting
],
'm.popaccountid' => [
'label' => $lng['emails']['account'],
'column' => 'popaccountid',
'format_callback' => [Email::class, 'account'],
],
'm.iscatchall' => [
'label' => $lng['emails']['catchall'],
'column' => 'iscatchall',
'format_callback' => [Text::class, 'boolean'],
'visible' => \Froxlor\Settings::Get('catchall.catchall_enabled') == '1'
],
'm.quota' => [
'label' => $lng['emails']['quota'],
'column' => 'quota',
'visible' => \Froxlor\Settings::Get('system.mail_quota_enabled') == '1'
]
],
'visible_columns' => Listing::getVisibleColumnsForListing('email_list', [
'm.email_full',
'm.destination',
'm.popaccountid',
'm.iscatchall',
'm.quota'
]),
'actions' => [
'edit' => [
'icon' => 'fa fa-edit',
'href' => [
'section' => 'email',
'page' => 'emails',
'action' => 'edit',
'id' => ':id'
],
],
'delete' => [
'icon' => 'fa fa-trash',
'class' => 'text-danger',
'href' => [
'section' => 'email',
'page' => 'emails',
'action' => 'delete',
'id' => ':id'
],
]
]
]
];

View File

@@ -0,0 +1,74 @@
<?php
/**
* This file is part of the Froxlor project.
* Copyright (c) 2010 the Froxlor Team (see authors).
*
* For the full copyright and license information, please view the COPYING
* file that was distributed with this source code. You can also view the
* COPYING file online at http://files.froxlor.org/misc/COPYING.txt
*
* @copyright (c) the authors
* @author Froxlor team <team@froxlor.org> (2010-)
* @author Maurice Preuß <hello@envoyr.com>
* @license GPLv2 http://files.froxlor.org/misc/COPYING.txt
* @package Tabellisting
*
*/
use Froxlor\UI\Callbacks\Ftp;
use Froxlor\UI\Listing;
return [
'ftp_list' => [
'title' => $lng['menue']['ftp']['accounts'],
'icon' => 'fa-solid fa-users',
'columns' => [
'username' => [
'label' => $lng['login']['username'],
'column' => 'username',
],
'description' => [
'label' => $lng['panel']['ftpdesc'],
'column' => 'description'
],
'homedir' => [
'label' => $lng['panel']['path'],
'column' => 'homedir',
'format_callback' => [Ftp::class, 'pathRelative']
],
'shell' => [
'label' => $lng['panel']['shell'],
'column' => 'shell',
'visible' => \Froxlor\Settings::Get('system.allow_customer_shell') == '1'
]
],
'visible_columns' => Listing::getVisibleColumnsForListing('ftp_list', [
'username',
'description',
'homedir',
'shell'
]),
'actions' => [
'edit' => [
'icon' => 'fa fa-edit',
'href' => [
'section' => 'ftp',
'page' => 'ftps',
'action' => 'edit',
'id' => ':id'
],
],
'delete' => [
'icon' => 'fa fa-trash',
'class' => 'text-danger',
'href' => [
'section' => 'ftp',
'page' => 'ftps',
'action' => 'delete',
'id' => ':id'
],
]
]
]
];

View File

@@ -0,0 +1,87 @@
<?php
/**
* This file is part of the Froxlor project.
* Copyright (c) 2010 the Froxlor Team (see authors).
*
* For the full copyright and license information, please view the COPYING
* file that was distributed with this source code. You can also view the
* COPYING file online at http://files.froxlor.org/misc/COPYING.txt
*
* @copyright (c) the authors
* @author Froxlor team <team@froxlor.org> (2010-)
* @author Maurice Preuß <hello@envoyr.com>
* @license GPLv2 http://files.froxlor.org/misc/COPYING.txt
* @package Tabellisting
*
*/
use Froxlor\UI\Callbacks\Ftp;
use Froxlor\UI\Callbacks\Text;
use Froxlor\UI\Listing;
return [
'htaccess_list' => [
'title' => $lng['menue']['extras']['pathoptions'],
'icon' => 'fa-solid fa-folder',
'columns' => [
'path' => [
'label' => $lng['panel']['path'],
'column' => 'path',
'format_callback' => [Ftp::class, 'pathRelative']
],
'option_indexes' => [
'label' => $lng['extras']['view_directory'],
'column' => 'option_indexes',
'format_callback' => [Text::class, 'boolean']
],
'error404path' => [
'label' => $lng['extras']['error404path'],
'column' => 'error404path'
],
'error403path' => [
'label' => $lng['extras']['error403path'],
'column' => 'error403path'
],
'error500path' => [
'label' => $lng['extras']['error500path'],
'column' => 'error500path'
],
'options_cgi' => [
'label' => $lng['extras']['execute_perl'],
'column' => 'options_cgi',
'format_callback' => [Text::class, 'boolean'],
'visible' => $cperlenabled
]
],
'visible_columns' => Listing::getVisibleColumnsForListing('htaccess_list', [
'path',
'option_indexes',
'error404path',
'error403path',
'error500path',
'options_cgi'
]),
'actions' => [
'edit' => [
'icon' => 'fa fa-edit',
'href' => [
'section' => 'extras',
'page' => 'htaccess',
'action' => 'edit',
'id' => ':id'
],
],
'delete' => [
'icon' => 'fa fa-trash',
'class' => 'text-danger',
'href' => [
'section' => 'extras',
'page' => 'htaccess',
'action' => 'delete',
'id' => ':id'
],
]
]
]
];

View File

@@ -0,0 +1,63 @@
<?php
/**
* This file is part of the Froxlor project.
* Copyright (c) 2010 the Froxlor Team (see authors).
*
* For the full copyright and license information, please view the COPYING
* file that was distributed with this source code. You can also view the
* COPYING file online at http://files.froxlor.org/misc/COPYING.txt
*
* @copyright (c) the authors
* @author Froxlor team <team@froxlor.org> (2010-)
* @author Maurice Preuß <hello@envoyr.com>
* @license GPLv2 http://files.froxlor.org/misc/COPYING.txt
* @package Tabellisting
*
*/
use Froxlor\UI\Callbacks\Ftp;
use Froxlor\UI\Listing;
return [
'htpasswd_list' => [
'title' => $lng['menue']['extras']['directoryprotection'],
'icon' => 'fa-solid fa-lock',
'columns' => [
'username' => [
'label' => $lng['login']['username'],
'column' => 'username'
],
'path' => [
'label' => $lng['panel']['path'],
'column' => 'path',
'format_callback' => [Ftp::class, 'pathRelative']
]
],
'visible_columns' => Listing::getVisibleColumnsForListing('htpasswd_list', [
'username',
'path'
]),
'actions' => [
'edit' => [
'icon' => 'fa fa-edit',
'href' => [
'section' => 'extras',
'page' => 'htpasswds',
'action' => 'edit',
'id' => ':id'
],
],
'delete' => [
'icon' => 'fa fa-trash',
'class' => 'text-danger',
'href' => [
'section' => 'extras',
'page' => 'htpasswds',
'action' => 'delete',
'id' => ':id'
],
]
]
]
];

View File

@@ -0,0 +1,76 @@
<?php
/**
* This file is part of the Froxlor project.
* Copyright (c) 2010 the Froxlor Team (see authors).
*
* For the full copyright and license information, please view the COPYING
* file that was distributed with this source code. You can also view the
* COPYING file online at http://files.froxlor.org/misc/COPYING.txt
*
* @copyright (c) the authors
* @author Froxlor team <team@froxlor.org> (2010-)
* @author Maurice Preuß <hello@envoyr.com>
* @license GPLv2 http://files.froxlor.org/misc/COPYING.txt
* @package Tabellisting
*
*/
use Froxlor\UI\Callbacks\Mysql;
use Froxlor\UI\Callbacks\Text;
use Froxlor\UI\Listing;
return [
'mysql_list' => [
'title' => $lng['menue']['mysql']['databases'],
'icon' => 'fa-solid fa-database',
'columns' => [
'databasename' => [
'label' => $lng['mysql']['databasename'],
'column' => 'databasename',
],
'description' => [
'label' => $lng['mysql']['databasedescription'],
'column' => 'description'
],
'size' => [
'label' => $lng['mysql']['size'],
'column' => 'size',
'format_callback' => [Text::class, 'size']
],
'dbserver' => [
'label' => $lng['mysql']['mysql_server'],
'column' => 'dbserver',
'format_callback' => [Mysql::class, 'dbserver'],
'visible' => $count_mysqlservers > 1
]
],
'visible_columns' => Listing::getVisibleColumnsForListing('mysql_list', [
'databasename',
'description',
'size',
'dbserver'
]),
'actions' => [
'edit' => [
'icon' => 'fa fa-edit',
'href' => [
'section' => 'mysql',
'page' => 'mysqls',
'action' => 'edit',
'id' => ':id'
],
],
'delete' => [
'icon' => 'fa fa-trash',
'class' => 'text-danger',
'href' => [
'section' => 'mysql',
'page' => 'mysqls',
'action' => 'delete',
'id' => ':id'
],
]
]
]
];

View File

@@ -1893,8 +1893,8 @@ $lng['crondesc']['cron_backup'] = 'Process backup jobs';
$lng['error']['backupfunctionnotenabled'] = 'The backup function is not enabled'; $lng['error']['backupfunctionnotenabled'] = 'The backup function is not enabled';
$lng['serversettings']['backupenabled']['title'] = "Enable backup for customers"; $lng['serversettings']['backupenabled']['title'] = "Enable backup for customers";
$lng['serversettings']['backupenabled']['description'] = "If activated, the customer will be able to schedule backup jobs (cron-backup) which generates an archive within his docroot (subdirectory chosable by customer)"; $lng['serversettings']['backupenabled']['description'] = "If activated, the customer will be able to schedule backup jobs (cron-backup) which generates an archive within his docroot (subdirectory chosable by customer)";
$lng['extras']['path_protection_label'] = '<strong class="red">Important</strong>'; $lng['extras']['path_protection_label'] = '<strong class="text-danger">Important</strong>';
$lng['extras']['path_protection_info'] = '<strong class="red">We strongly recommend protecting the given path, see "Extras" -> "Directory protection"</strong>'; $lng['extras']['path_protection_info'] = 'We strongly recommend protecting the given path, see "Extras" -> "Directory protection"';
$lng['tasks']['CREATE_CUSTOMER_BACKUP'] = 'Backup job for customer %loginname%'; $lng['tasks']['CREATE_CUSTOMER_BACKUP'] = 'Backup job for customer %loginname%';
$lng['error']['dns_domain_nodns'] = 'DNS is not enabled for this domain'; $lng['error']['dns_domain_nodns'] = 'DNS is not enabled for this domain';

View File

@@ -1543,8 +1543,8 @@ $lng['crondesc']['cron_backup'] = 'Ausstehende Sicherungen erstellen';
$lng['error']['backupfunctionnotenabled'] = 'Die Sicherungs-Funktion is nicht aktiviert'; $lng['error']['backupfunctionnotenabled'] = 'Die Sicherungs-Funktion is nicht aktiviert';
$lng['serversettings']['backupenabled']['title'] = "Backup für Kunden aktivieren"; $lng['serversettings']['backupenabled']['title'] = "Backup für Kunden aktivieren";
$lng['serversettings']['backupenabled']['description'] = "Wenn dies aktiviert ist, kann der Kunde Sicherungen planen (cron-backup) welche ein Archiv in sein Heimatverzeichnis ablegt (Unterordner vom Kunden wählbar)"; $lng['serversettings']['backupenabled']['description'] = "Wenn dies aktiviert ist, kann der Kunde Sicherungen planen (cron-backup) welche ein Archiv in sein Heimatverzeichnis ablegt (Unterordner vom Kunden wählbar)";
$lng['extras']['path_protection_label'] = '<strong class="red">Wichtig</strong>'; $lng['extras']['path_protection_label'] = '<strong class="text-danger">Wichtig</strong>';
$lng['extras']['path_protection_info'] = '<strong class="red">Wir raten dringend dazu den angegebenen Pfad zu schützen, siehe "Extras" -> "Verzeichnisschutz"</strong>'; $lng['extras']['path_protection_info'] = 'Wir raten dringend dazu den angegebenen Pfad zu schützen, siehe "Extras" -> "Verzeichnisschutz"';
$lng['tasks']['CREATE_CUSTOMER_BACKUP'] = 'Datensicherung für Kunde %loginname%'; $lng['tasks']['CREATE_CUSTOMER_BACKUP'] = 'Datensicherung für Kunde %loginname%';
$lng['error']['dns_domain_nodns'] = 'DNS ist für diese Domain nicht aktiviert'; $lng['error']['dns_domain_nodns'] = 'DNS ist für diese Domain nicht aktiviert';

View File

@@ -19,15 +19,13 @@ if (! defined('AREA')) {
* *
*/ */
use Froxlor\Api\Commands\SubDomains as SubDomains; use Froxlor\Api\Commands\SubDomains;
use Froxlor\Settings; use Froxlor\Settings;
use Froxlor\UI\Request; use Froxlor\UI\Request;
// This file is being included in admin_domains and customer_domains // This file is being included in admin_domains and customer_domains
// and therefore does not need to require lib/init.php // and therefore does not need to require lib/init.php
// TODO get domain related settings for logfile (speciallogfile)
$domain_id = (int) Request::get('domain_id'); $domain_id = (int) Request::get('domain_id');
$last_n = (int) Request::get('number_of_lines', 100); $last_n = (int) Request::get('number_of_lines', 100);

View File

@@ -6,7 +6,7 @@
{% if field.desc is defined and field.desc is not empty %}<br><small>{{ field.desc|raw }}</small> {% if field.desc is defined and field.desc is not empty %}<br><small>{{ field.desc|raw }}</small>
{% endif %} {% endif %}
</label> </label>
<div class="col-sm-8"> <div class="col-sm-8{% if field.type == 'infotext' %} d-flex align-items-center{% endif %}">
{% endif %} {% endif %}
{% if field.type == 'text' or field.type == 'password' or field.type == 'number' or field.type == 'file' or field.type == 'email' or field.type == 'hidden' %} {% if field.type == 'text' or field.type == 'password' or field.type == 'number' or field.type == 'file' or field.type == 'email' or field.type == 'hidden' %}
{{ _self.input(id, field) }} {{ _self.input(id, field) }}
@@ -24,6 +24,8 @@
{{ _self.link(id, field) }} {{ _self.link(id, field) }}
{% elseif field.type == 'itemlist' %} {% elseif field.type == 'itemlist' %}
{{ _self.itemlist(id, field) }} {{ _self.itemlist(id, field) }}
{% elseif field.type == 'infotext' %}
{{ _self.infotext(id, field) }}
{% endif %} {% endif %}
{% if norow == false and field.type != 'hidden' %} {% if norow == false and field.type != 'hidden' %}
</div> </div>
@@ -49,11 +51,27 @@
{% endif %} {% endif %}
{% endmacro %} {% endmacro %}
{% macro infotext(id, field) %}
{% if field.next_to is defined %}
<div class="input-group">
{% endif %}
<span {% if field.classes is defined %} class="{{ field.classes }}" {% endif %}>{{ field.value }}</span>
{% if field.next_to is defined %}
{% for nid, nfield in field.next_to %}
{% if nfield.next_to_prefix is defined %}
<span class="input-group-text">{{ nfield.next_to_prefix }}</span>
{% endif %}
{{ _self.fieldrow(nid, nfield, true) }}
{% endfor %}
</div>
{% endif %}
{% endmacro %}
{% macro plain(id, field) %} {% macro plain(id, field) %}
{% if field.next_to is defined %} {% if field.next_to is defined %}
<div class="input-group"> <div class="input-group">
{% endif %} {% endif %}
<input type="text" readonly class="form-control-plaintext" id="{{ id }}" value="{{ field.value }}"> <input type="text" readonly class="form-control-plaintext" id="{{ id }}" name="{{ id }}" value="{{ field.value }}">
{% if field.next_to is defined %} {% if field.next_to is defined %}
{% for nid, nfield in field.next_to %} {% for nid, nfield in field.next_to %}
{% if nfield.next_to_prefix is defined %} {% if nfield.next_to_prefix is defined %}
@@ -74,7 +92,7 @@
<input type="text" readonly class="form-control-plaintext" value="{{ field.display }}"> <input type="text" readonly class="form-control-plaintext" value="{{ field.display }}">
{% endif %} {% endif %}
{% if field.note is defined and field.note is not empty %} {% if field.note is defined and field.note is not empty %}
<div class="invalid-feedback">{{ field.note|raw }}</div> <div class="invalid-feedback">{{ field.note|raw }}</div>
{% endif %} {% endif %}
{% if field.next_to is defined %} {% if field.next_to is defined %}
{% for nid, nfield in field.next_to %} {% for nid, nfield in field.next_to %}

View File

@@ -18,6 +18,17 @@
{% endif %} {% endif %}
{% endmacro %} {% endmacro %}
{% macro booleanWithInfo(data) %}
{% if (data.checked) %}
<i class="fa fa-check-circle text-success"></i>
{% else %}
<i class="fa fa-times-circle text-danger"></i>
{% endif %}
{% if data.info is not empty %}
{{ data.info }}
{% endif %}
{% endmacro %}
{% macro link(data) %} {% macro link(data) %}
{% apply spaceless %} {% apply spaceless %}
<a href="{{ data.href }}" {% if data.class is defined %}class="{{ data.class }}"{% endif %} {% if data.target is defined %}target="{{ data.target }}"{% endif %}> <a href="{{ data.href }}" {% if data.class is defined %}class="{{ data.class }}"{% endif %} {% if data.target is defined %}target="{{ data.target }}"{% endif %}>

View File

@@ -32,6 +32,8 @@
{{ callbacks.progressbar(td.data.data) }} {{ callbacks.progressbar(td.data.data) }}
{% elseif td.data.type == 'boolean' %} {% elseif td.data.type == 'boolean' %}
{{ callbacks.boolean(td.data.data) }} {{ callbacks.boolean(td.data.data) }}
{% elseif td.data.type == 'booleanWithInfo' %}
{{ callbacks.booleanWithInfo(td.data.data) }}
{% elseif td.data.type == 'link' %} {% elseif td.data.type == 'link' %}
{{ callbacks.link(td.data.data) }} {{ callbacks.link(td.data.data) }}
{% elseif td.data.type == 'domainWithSan' %} {% elseif td.data.type == 'domainWithSan' %}

View File

@@ -1,9 +1,26 @@
{% extends "Froxlor/userarea.html.twig" %} {% extends "Froxlor/userarea.html.twig" %}
{% block content %} {% block content %}
<div class="row">
{% import "Froxlor/table/table.html.twig" as table %} <div class="col-12 {% if actions_links is iterable or (entity_info is defined and entity_info is not empty) %}col-md-10 order-2 order-md-1{% endif %}">
{% import "Froxlor/table/table.html.twig" as table %}
{{ table.table(listing) }} {{ table.table(listing) }}
</div>
{% if actions_links is iterable or (entity_info is defined and entity_info is not empty) %}
<div class="col-12 col-md-2 order-1 order-md-2">
{% if actions_links is iterable %}
{% for link in actions_links %}
<a class="btn {{ link.class|default('btn-success') }} d-block mb-2" href="{{ link.href|raw }}">
<i class="{{ link.icon|default('fa-solid fa-plus-circle') }} me-1"></i>
{{ link.label }}</a>
{% endfor %}
{% endif %}
{% if entity_info is defined and entity_info is not empty %}
<div class="alert alert-info" role="alert">
{{ entity_info|raw }}
</div>
{% endif %}
</div>
{% endif %}
</div>
{% endblock %} {% endblock %}

View File

@@ -43,7 +43,7 @@
</li> </li>
<li class="nav-item dropdown me-2"> <li class="nav-item dropdown me-2">
<a class="btn btn-secondary btn-sm d-block dropdown-toggle" href="#" id="navbarOpts" role="button" data-bs-toggle="dropdown" aria-expanded="false"> <a class="btn btn-secondary btn-sm d-block dropdown-toggle" href="#" id="navbarOpts" role="button" data-bs-toggle="dropdown" aria-expanded="false">
<i class="fa fa-wrench"></i> {{ lng('panel.options') }} <i class="fa fa-gears"></i> {{ lng('panel.options') }}
</a> </a>
<ul class="dropdown-menu" aria-labelledby="navbarOpts"> <ul class="dropdown-menu" aria-labelledby="navbarOpts">
<li> <li>

View File

@@ -929,7 +929,7 @@ class DomainZonesTest extends TestCase
$json_result = DomainZones::getLocal($customer_userdata, $data)->delete(); $json_result = DomainZones::getLocal($customer_userdata, $data)->delete();
$result = json_decode($json_result, true); $result = json_decode($json_result, true);
$this->assertTrue($result['data']); $this->assertTrue($result['data']);
$this->assertEquals(200, $result['status']); $this->assertEquals(200, http_response_code());
} }
public function testCustomerDomainZonesDeleteUnmodified() public function testCustomerDomainZonesDeleteUnmodified()
@@ -949,6 +949,6 @@ class DomainZonesTest extends TestCase
$json_result = DomainZones::getLocal($customer_userdata, $data)->delete(); $json_result = DomainZones::getLocal($customer_userdata, $data)->delete();
$result = json_decode($json_result, true); $result = json_decode($json_result, true);
$this->assertTrue($result['data']); $this->assertTrue($result['data']);
$this->assertEquals(304, $result['status']); $this->assertEquals(304, http_response_code());
} }
} }

View File

@@ -11,32 +11,20 @@ use Froxlor\Api\FroxlorRPC;
class FroxlorRpcTest extends TestCase class FroxlorRpcTest extends TestCase
{ {
public function testInvalidRequestHeader()
{
$this->expectExceptionCode(400);
$this->expectExceptionMessage("Invalid request header");
FroxlorRPC::validateRequest(array());
}
public function testNoCredentialsGiven() public function testNoCredentialsGiven()
{ {
$this->expectExceptionCode(400); $this->expectExceptionCode(401);
$this->expectExceptionMessage("No authorization credentials given"); $this->expectExceptionMessage("Unauthenticated. Please provide api user credentials.");
FroxlorRPC::validateRequest(array( FroxlorRPC::validateRequest("");
'header' => 'asd'
));
} }
public function testValidateAuthInvalid() public function testValidateAuthInvalid()
{ {
$this->expectExceptionCode(403); $this->expectExceptionCode(403);
$this->expectExceptionMessage("Invalid authorization credentials"); $this->expectExceptionMessage("Invalid authorization credentials");
FroxlorRPC::validateRequest(array( $_SERVER['PHP_AUTH_USER'] = 'asd';
'header' => [ $_SERVER['PHP_AUTH_PW'] = 'asd';
'apikey' => 'asd', FroxlorRPC::validateRequest("");
'secret' => 'asd'
]
));
} }
public function testValidateAuthAllowFromInvalid() public function testValidateAuthAllowFromInvalid()
@@ -45,81 +33,62 @@ class FroxlorRpcTest extends TestCase
Database::query("UPDATE `api_keys` SET `allowed_from` = '123.123.123.123';"); Database::query("UPDATE `api_keys` SET `allowed_from` = '123.123.123.123';");
$this->expectExceptionCode(403); $this->expectExceptionCode(403);
$this->expectExceptionMessage("Invalid authorization credentials"); $this->expectExceptionMessage("Invalid authorization credentials");
FroxlorRPC::validateRequest(array( $_SERVER['PHP_AUTH_USER'] = 'test';
'header' => [ $_SERVER['PHP_AUTH_PW'] = 'test';
'apikey' => 'test', FroxlorRPC::validateRequest("");
'secret' => 'test'
]
));
} }
public function testInvalidRequestBody() public function testEmptyRequestBody()
{ {
Database::query("UPDATE `api_keys` SET `allowed_from` = '';"); Database::query("UPDATE `api_keys` SET `allowed_from` = '';");
$this->expectExceptionCode(400); $this->expectExceptionCode(400);
$this->expectExceptionMessage("Invalid request body"); $this->expectExceptionMessage("Empty request body.");
FroxlorRPC::validateRequest(array( $_SERVER['PHP_AUTH_USER'] = 'test';
'header' => [ $_SERVER['PHP_AUTH_PW'] = 'test';
'apikey' => 'test', FroxlorRPC::validateRequest("");
'secret' => 'test' }
]
)); public function testInvalidJSON()
{
$this->expectExceptionCode(400);
$this->expectExceptionMessage("Invalid JSON Format.");
$_SERVER['PHP_AUTH_USER'] = 'test';
$_SERVER['PHP_AUTH_PW'] = 'test';
FroxlorRPC::validateRequest('asd');
} }
public function testNoCommandGiven() public function testNoCommandGiven()
{ {
$this->expectExceptionCode(400); $this->expectExceptionCode(400);
$this->expectExceptionMessage("No command given"); $this->expectExceptionMessage("Please provide a command.");
FroxlorRPC::validateRequest(array( $_SERVER['PHP_AUTH_USER'] = 'test';
'header' => [ $_SERVER['PHP_AUTH_PW'] = 'test';
'apikey' => 'test', FroxlorRPC::validateRequest(json_encode(['cmd' => 'test']));
'secret' => 'test'
],
'body' => 'asd'
));
} }
public function testInvalidCommandGiven() public function testInvalidCommandGiven()
{ {
$this->expectExceptionCode(400); $this->expectExceptionCode(400);
$this->expectExceptionMessage("Invalid command"); $this->expectExceptionMessage("The given command is invalid.");
FroxlorRPC::validateRequest(array( $_SERVER['PHP_AUTH_USER'] = 'test';
'header' => [ $_SERVER['PHP_AUTH_PW'] = 'test';
'apikey' => 'test', FroxlorRPC::validateRequest(json_encode(['command' => 'Froxlor']));
'secret' => 'test'
],
'body' => [
'command' => 'Froxlor'
]
));
} }
public function testUnknownCommandGiven() public function testUnknownCommandGiven()
{ {
$this->expectExceptionCode(400); $this->expectExceptionCode(400);
$this->expectExceptionMessage("Unknown command"); $this->expectExceptionMessage("Unknown command");
FroxlorRPC::validateRequest(array( $_SERVER['PHP_AUTH_USER'] = 'test';
'header' => [ $_SERVER['PHP_AUTH_PW'] = 'test';
'apikey' => 'test', FroxlorRPC::validateRequest(json_encode(['command' => 'SomeModule.cmd']));
'secret' => 'test'
],
'body' => [
'command' => 'SomeModule.cmd'
]
));
} }
public function testCommandOk() public function testCommandOk()
{ {
$result = FroxlorRPC::validateRequest(array( $_SERVER['PHP_AUTH_USER'] = 'test';
'header' => [ $_SERVER['PHP_AUTH_PW'] = 'test';
'apikey' => 'test', $result = FroxlorRPC::validateRequest(json_encode(['command' => 'Froxlor.listFunctions']));
'secret' => 'test'
],
'body' => [
'command' => 'Froxlor.listFunctions'
]
));
$this->assertEquals('Froxlor', $result['command']['class']); $this->assertEquals('Froxlor', $result['command']['class']);
$this->assertEquals('listFunctions', $result['command']['method']); $this->assertEquals('listFunctions', $result['command']['method']);
$this->assertNull($result['params']); $this->assertNull($result['params']);
@@ -129,16 +98,14 @@ class FroxlorRpcTest extends TestCase
{ {
$key = $this->generateKey(); $key = $this->generateKey();
$request = array( $request = array(
'body' => [ 'command' => 'Froxlor.listFunctions',
'command' => 'Froxlor.listFunctions', 'params' => $key
'params' => $key
]
); );
$json_request = json_encode($request); $json_request = json_encode($request);
$decoded_request = json_decode($json_request, true); $decoded_request = json_decode($json_request, true);
$decoded_request = $this->stripcslashes_deep($decoded_request); $decoded_request = $this->stripcslashes_deep($decoded_request);
$this->assertEquals($key['key'], $decoded_request['body']['params']['key']); $this->assertEquals($key['key'], $decoded_request['params']['key']);
$this->assertEquals($key['cert'], $decoded_request['body']['params']['cert']); $this->assertEquals($key['cert'], $decoded_request['params']['cert']);
} }
private function stripcslashes_deep($value) private function stripcslashes_deep($value)