From 1b2c186c0738e75d55a2687473688962a3accef3 Mon Sep 17 00:00:00 2001 From: Michael Kaufmann Date: Sat, 2 Nov 2019 10:58:52 +0100 Subject: [PATCH] introduce search, limit, offset and orderby possibilities for (almost) all API listing() functions; added listingCount() function in preparation to replace the old UI\Paging class later on Signed-off-by: Michael Kaufmann --- composer.lock | 95 ++++++------ lib/Froxlor/Api/ApiCommand.php | 145 +++++++++++++++++++ lib/Froxlor/Api/Commands/Admins.php | 38 ++++- lib/Froxlor/Api/Commands/Certificates.php | 48 +++++- lib/Froxlor/Api/Commands/Cronjobs.php | 36 ++++- lib/Froxlor/Api/Commands/CustomerBackups.php | 48 +++++- lib/Froxlor/Api/Commands/Customers.php | 43 +++++- lib/Froxlor/Api/Commands/DirOptions.php | 49 ++++++- lib/Froxlor/Api/Commands/DirProtections.php | 46 +++++- lib/Froxlor/Api/Commands/DomainZones.php | 59 +++++++- lib/Froxlor/Api/Commands/Domains.php | 45 +++++- lib/Froxlor/Api/Commands/EmailAccounts.php | 13 +- lib/Froxlor/Api/Commands/EmailForwarders.php | 9 ++ lib/Froxlor/Api/Commands/Emails.php | 44 +++++- lib/Froxlor/Api/Commands/FpmDaemons.php | 45 ++++-- lib/Froxlor/Api/Commands/Ftps.php | 42 +++++- lib/Froxlor/Api/Commands/HostingPlans.php | 41 +++++- lib/Froxlor/Api/Commands/IpsAndPorts.php | 39 ++++- lib/Froxlor/Api/Commands/Mysqls.php | 44 +++++- lib/Froxlor/Api/Commands/PhpSettings.php | 45 +++++- lib/Froxlor/Api/Commands/SubDomains.php | 98 +++++++++++-- lib/Froxlor/Api/Commands/Traffic.php | 10 ++ lib/Froxlor/Api/ResourceEntity.php | 2 + tests/Admins/AdminsTest.php | 45 ++++++ tests/Backup/CustomerBackupsTest.php | 4 + tests/Certificates/CertificatesTest.php | 12 ++ tests/Cronjobs/CronjobsTest.php | 4 + tests/Customers/CustomersTest.php | 13 +- tests/Customers/HostingPlansTest.php | 13 +- tests/DomainZones/DomainZonesTest.php | 4 + tests/Domains/DomainsTest.php | 26 ++++ tests/Emails/EmailsTest.php | 4 + tests/Extras/DirOptionsTest.php | 4 + tests/Extras/DirProtectionsTest.php | 4 + tests/Ftps/FtpsTest.php | 12 ++ tests/IpsAndPorts/IpsAndPortsTest.php | 8 + tests/Mysqls/MysqlsTest.php | 4 + tests/PhpAndFpm/FpmDaemonsTest.php | 8 + tests/PhpAndFpm/PhpSettingsTest.php | 8 + tests/SubDomains/SubDomainsTest.php | 14 ++ tests/Traffic/TrafficTest.php | 8 + 41 files changed, 1149 insertions(+), 130 deletions(-) diff --git a/composer.lock b/composer.lock index f8c7a813..feb411a8 100644 --- a/composer.lock +++ b/composer.lock @@ -200,16 +200,16 @@ }, { "name": "psr/log", - "version": "1.1.0", + "version": "1.1.2", "source": { "type": "git", "url": "https://github.com/php-fig/log.git", - "reference": "6c001f1daafa3a3ac1d8ff69ee4db8e799a654dd" + "reference": "446d54b4cb6bf489fc9d75f55843658e6f25d801" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/log/zipball/6c001f1daafa3a3ac1d8ff69ee4db8e799a654dd", - "reference": "6c001f1daafa3a3ac1d8ff69ee4db8e799a654dd", + "url": "https://api.github.com/repos/php-fig/log/zipball/446d54b4cb6bf489fc9d75f55843658e6f25d801", + "reference": "446d54b4cb6bf489fc9d75f55843658e6f25d801", "shasum": "" }, "require": { @@ -218,7 +218,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0.x-dev" + "dev-master": "1.1.x-dev" } }, "autoload": { @@ -243,7 +243,7 @@ "psr", "psr-3" ], - "time": "2018-11-20T15:27:04+00:00" + "time": "2019-11-01T11:05:21+00:00" }, { "name": "robthree/twofactorauth", @@ -404,16 +404,16 @@ }, { "name": "nikic/php-parser", - "version": "v4.2.4", + "version": "v4.2.5", "source": { "type": "git", "url": "https://github.com/nikic/PHP-Parser.git", - "reference": "97e59c7a16464196a8b9c77c47df68e4a39a45c4" + "reference": "b76bbc3c51f22c570648de48e8c2d941ed5e2cf2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/97e59c7a16464196a8b9c77c47df68e4a39a45c4", - "reference": "97e59c7a16464196a8b9c77c47df68e4a39a45c4", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/b76bbc3c51f22c570648de48e8c2d941ed5e2cf2", + "reference": "b76bbc3c51f22c570648de48e8c2d941ed5e2cf2", "shasum": "" }, "require": { @@ -421,6 +421,7 @@ "php": ">=7.0" }, "require-dev": { + "ircmaxell/php-yacc": "0.0.4", "phpunit/phpunit": "^6.5 || ^7.0 || ^8.0" }, "bin": [ @@ -451,7 +452,7 @@ "parser", "php" ], - "time": "2019-09-01T07:51:21+00:00" + "time": "2019-10-25T18:33:07+00:00" }, { "name": "pdepend/pdepend", @@ -597,16 +598,16 @@ }, { "name": "phpcompatibility/php-compatibility", - "version": "9.3.1", + "version": "9.3.2", "source": { "type": "git", "url": "https://github.com/PHPCompatibility/PHPCompatibility.git", - "reference": "9999344e47e7af6b00e1a898eacc4e4368fb7196" + "reference": "bfca2be3992f40e92206e5a7ebe5eaee37280b58" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/PHPCompatibility/PHPCompatibility/zipball/9999344e47e7af6b00e1a898eacc4e4368fb7196", - "reference": "9999344e47e7af6b00e1a898eacc4e4368fb7196", + "url": "https://api.github.com/repos/PHPCompatibility/PHPCompatibility/zipball/bfca2be3992f40e92206e5a7ebe5eaee37280b58", + "reference": "bfca2be3992f40e92206e5a7ebe5eaee37280b58", "shasum": "" }, "require": { @@ -651,7 +652,7 @@ "phpcs", "standards" ], - "time": "2019-09-05T18:36:49+00:00" + "time": "2019-10-16T21:24:24+00:00" }, { "name": "phpdocumentor/reflection-common", @@ -1237,16 +1238,16 @@ }, { "name": "phpunit/phpunit", - "version": "8.4.1", + "version": "8.4.2", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "366a4a0f2b971fd43b7c351d621e8dd7d7131869" + "reference": "a142a7e66c0ea7b5b6c04ee27f08d10d1137cd9b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/366a4a0f2b971fd43b7c351d621e8dd7d7131869", - "reference": "366a4a0f2b971fd43b7c351d621e8dd7d7131869", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/a142a7e66c0ea7b5b6c04ee27f08d10d1137cd9b", + "reference": "a142a7e66c0ea7b5b6c04ee27f08d10d1137cd9b", "shasum": "" }, "require": { @@ -1316,7 +1317,7 @@ "testing", "xunit" ], - "time": "2019-10-07T12:57:41+00:00" + "time": "2019-10-28T10:39:51+00:00" }, { "name": "psr/container", @@ -2074,16 +2075,16 @@ }, { "name": "squizlabs/php_codesniffer", - "version": "3.5.0", + "version": "3.5.2", "source": { "type": "git", "url": "https://github.com/squizlabs/PHP_CodeSniffer.git", - "reference": "0afebf16a2e7f1e434920fa976253576151effe9" + "reference": "65b12cdeaaa6cd276d4c3033a95b9b88b12701e7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/0afebf16a2e7f1e434920fa976253576151effe9", - "reference": "0afebf16a2e7f1e434920fa976253576151effe9", + "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/65b12cdeaaa6cd276d4c3033a95b9b88b12701e7", + "reference": "65b12cdeaaa6cd276d4c3033a95b9b88b12701e7", "shasum": "" }, "require": { @@ -2121,20 +2122,20 @@ "phpcs", "standards" ], - "time": "2019-09-26T23:12:26+00:00" + "time": "2019-10-28T04:36:32+00:00" }, { "name": "symfony/config", - "version": "v4.3.5", + "version": "v4.3.6", "source": { "type": "git", "url": "https://github.com/symfony/config.git", - "reference": "0acb26407a9e1a64a275142f0ae5e36436342720" + "reference": "f4ee0ebb91b16ca1ac105aa39f9284f3cac19a15" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/config/zipball/0acb26407a9e1a64a275142f0ae5e36436342720", - "reference": "0acb26407a9e1a64a275142f0ae5e36436342720", + "url": "https://api.github.com/repos/symfony/config/zipball/f4ee0ebb91b16ca1ac105aa39f9284f3cac19a15", + "reference": "f4ee0ebb91b16ca1ac105aa39f9284f3cac19a15", "shasum": "" }, "require": { @@ -2185,20 +2186,20 @@ ], "description": "Symfony Config Component", "homepage": "https://symfony.com", - "time": "2019-09-19T15:51:53+00:00" + "time": "2019-10-30T13:18:51+00:00" }, { "name": "symfony/console", - "version": "v4.3.5", + "version": "v4.3.6", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "929ddf360d401b958f611d44e726094ab46a7369" + "reference": "136c4bd62ea871d00843d1bc0316de4c4a84bb78" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/929ddf360d401b958f611d44e726094ab46a7369", - "reference": "929ddf360d401b958f611d44e726094ab46a7369", + "url": "https://api.github.com/repos/symfony/console/zipball/136c4bd62ea871d00843d1bc0316de4c4a84bb78", + "reference": "136c4bd62ea871d00843d1bc0316de4c4a84bb78", "shasum": "" }, "require": { @@ -2260,20 +2261,20 @@ ], "description": "Symfony Console Component", "homepage": "https://symfony.com", - "time": "2019-10-07T12:36:49+00:00" + "time": "2019-10-30T12:58:49+00:00" }, { "name": "symfony/dependency-injection", - "version": "v4.3.5", + "version": "v4.3.6", "source": { "type": "git", "url": "https://github.com/symfony/dependency-injection.git", - "reference": "e1e0762a814b957a1092bff75a550db49724d05b" + "reference": "fc036941dfafa037a7485714b62593c7eaf68edd" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/e1e0762a814b957a1092bff75a550db49724d05b", - "reference": "e1e0762a814b957a1092bff75a550db49724d05b", + "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/fc036941dfafa037a7485714b62593c7eaf68edd", + "reference": "fc036941dfafa037a7485714b62593c7eaf68edd", "shasum": "" }, "require": { @@ -2333,11 +2334,11 @@ ], "description": "Symfony DependencyInjection Component", "homepage": "https://symfony.com", - "time": "2019-10-02T12:58:58+00:00" + "time": "2019-10-28T17:07:32+00:00" }, { "name": "symfony/filesystem", - "version": "v4.3.5", + "version": "v4.3.6", "source": { "type": "git", "url": "https://github.com/symfony/filesystem.git", @@ -2387,16 +2388,16 @@ }, { "name": "symfony/finder", - "version": "v4.3.5", + "version": "v4.3.6", "source": { "type": "git", "url": "https://github.com/symfony/finder.git", - "reference": "5e575faa95548d0586f6bedaeabec259714e44d1" + "reference": "72a068f77e317ae77c0a0495236ad292cfb5ce6f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/5e575faa95548d0586f6bedaeabec259714e44d1", - "reference": "5e575faa95548d0586f6bedaeabec259714e44d1", + "url": "https://api.github.com/repos/symfony/finder/zipball/72a068f77e317ae77c0a0495236ad292cfb5ce6f", + "reference": "72a068f77e317ae77c0a0495236ad292cfb5ce6f", "shasum": "" }, "require": { @@ -2432,7 +2433,7 @@ ], "description": "Symfony Finder Component", "homepage": "https://symfony.com", - "time": "2019-09-16T11:29:48+00:00" + "time": "2019-10-30T12:53:54+00:00" }, { "name": "symfony/polyfill-ctype", diff --git a/lib/Froxlor/Api/ApiCommand.php b/lib/Froxlor/Api/ApiCommand.php index 6aa6f412..b0d6a0be 100644 --- a/lib/Froxlor/Api/ApiCommand.php +++ b/lib/Froxlor/Api/ApiCommand.php @@ -232,6 +232,151 @@ abstract class ApiCommand extends ApiParameter return $this->user_data; } + /** + * return SQL when parameter $sql_search is given via API + * + * @param array $sql_search + * optional array with index = fieldname, and value = array with 'op' => operator (one of <, > or =), LIKE is used if left empty and 'value' => searchvalue + * @param array $query_fields + * optional array of placeholders mapped to the actual value which is used in the API commands when executing the statement [internal] + * @param boolean $append + * optional append to WHERE clause rather then create new one, default false [internal] + * + * @return string + */ + protected function getSearchWhere(&$query_fields = array(), $append = false) + { + $search = $this->getParam('sql_search', true, array()); + $condition = ''; + if (! empty($search)) { + if ($append == true) { + $condition = ' AND '; + } else { + $condition = ' WHERE '; + } + $ops = array( + '<', + '>', + '=' + ); + $first = true; + foreach ($search as $field => $valoper) { + $cleanfield = str_replace(".", "", $field); + $sortfield = explode('.', $field); + foreach ($sortfield as $id => $sfield) { + if (substr($sfield, - 1, 1) != '`') { + $sfield .= '`'; + } + if ($sfield[0] != '`') { + $sfield = '`' . $sfield; + } + $sortfield[$id] = $sfield; + } + $field = implode('.', $sortfield); + if (! $first) { + $condition .= ' AND '; + } + if (! is_array($valoper) || ! isset($valoper['op']) || empty($valoper['op'])) { + $condition .= $field . ' LIKE :' . $cleanfield; + if (! is_array($valoper)) { + $query_fields[':' . $cleanfield] = '%' . $valoper . '%'; + } else { + $query_fields[':' . $cleanfield] = '%' . $valoper['value'] . '%'; + } + } elseif (in_array($valoper['op'], $ops)) { + $condition .= $field . ' ' . $valoper['op'] . ':' . $cleanfield; + $query_fields[':' . $cleanfield] = $valoper['value'] ?? ''; + } else { + continue; + } + if ($first) { + $first = false; + } + } + } + return $condition; + } + + /** + * return LIMIT clause when at least $sql_limit parameter is given via API + * + * @param int $sql_limit + * optional, limit resultset, default 0 + * @param int $sql_offset + * optional, offset for limitation, default 0 + * + * @return string + */ + protected function getLimit() + { + $limit = $this->getParam('sql_limit', true, 0); + $offset = $this->getParam('sql_offset', true, 0); + + if (! is_numeric($limit)) { + $limit = 0; + } + if (! is_numeric($offset)) { + $offset = 0; + } + + if ($limit > 0) { + return ' LIMIT ' . $offset . ',' . $limit; + } + + return ''; + } + + /** + * return ORDER BY clause if parameter $sql_orderby parameter is given via API + * + * @param array $sql_orderby + * optional array with index = fieldname and value = ASC|DESC + * + * @return string + */ + protected function getOrderBy() + { + $orderby = $this->getParam('sql_orderby', true, array()); + $order = ""; + if (! empty($orderby)) { + $order .= " ORDER BY "; + foreach ($orderby as $field => $by) { + $sortfield = explode('.', $field); + foreach ($sortfield as $id => $sfield) { + if (substr($sfield, - 1, 1) != '`') { + $sfield .= '`'; + } + if ($sfield[0] != '`') { + $sfield = '`' . $sfield; + } + $sortfield[$id] = $sfield; + } + $field = implode('.', $sortfield); + $by = strtoupper($by); + if (! in_array($by, [ + 'ASC', + 'DESC' + ])) { + $by = 'ASC'; + } + if (\Froxlor\Settings::Get('panel.natsorting') == 1) { + // Acts similar to php's natsort(), found in one comment at http://my.opera.com/cpr/blog/show.dml/160556 + $order .= "CONCAT( IF( ASCII( LEFT( " . $field . ", 5 ) ) > 57, + LEFT( " . $field . ", 1 ), 0 ), + IF( ASCII( RIGHT( " . $field . ", 1 ) ) > 57, + LPAD( " . $field . ", 255, '0' ), + LPAD( CONCAT( " . $field . ", '-' ), 255, '0' ) + )) " . $by . ", "; + } else { + $order .= $field . " " . $by . ", "; + } + } + $order = substr($order, 0, - 2); + } + + return $order; + } + /** * return logger instance * diff --git a/lib/Froxlor/Api/Commands/Admins.php b/lib/Froxlor/Api/Commands/Admins.php index 72b7bb48..ab48ed42 100644 --- a/lib/Froxlor/Api/Commands/Admins.php +++ b/lib/Froxlor/Api/Commands/Admins.php @@ -25,6 +25,15 @@ class Admins extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt /** * lists all admin entries * + * @param array $sql_search + * optional array with index = fieldname, and value = array with 'op' => operator (one of <, > or =), LIKE is used if left empty and 'value' => searchvalue + * @param int $sql_limit + * optional specify number of results to be returned + * @param int $sql_offset + * optional specify offset for resultset + * @param array $sql_orderby + * optional array with index = fieldname and value = ASC|DESC to order the resultset by one or more fields + * * @access admin * @throws \Exception * @return string json-encoded array count|list @@ -33,12 +42,11 @@ class Admins extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt { if ($this->isAdmin() && $this->getUserDetail('change_serversettings') == 1) { $this->logger()->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_NOTICE, "[API] list admins"); + $query_fields = array(); $result_stmt = Database::prepare(" SELECT * - FROM `" . TABLE_PANEL_ADMINS . "` - ORDER BY `loginname` ASC - "); - Database::pexecute($result_stmt, null, true, true); + FROM `" . TABLE_PANEL_ADMINS . "`" . $this->getSearchWhere($query_fields) . $this->getOrderBy() . $this->getLimit()); + Database::pexecute($result_stmt, $query_fields, true, true); $result = array(); while ($row = $result_stmt->fetch(\PDO::FETCH_ASSOC)) { $result[] = $row; @@ -51,6 +59,28 @@ class Admins extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt throw new \Exception("Not allowed to execute given command.", 403); } + /** + * returns the total number of admins for the given admin + * + * @access admin + * @throws \Exception + * @return string json-encoded array + */ + public function listingCount() + { + if ($this->isAdmin() && $this->getUserDetail('change_serversettings') == 1) { + $result_stmt = Database::prepare(" + SELECT COUNT(*) as num_admins + FROM `" . TABLE_PANEL_ADMINS . "` + "); + $result = Database::pexecute_first($result_stmt, null, true, true); + if ($result) { + return $this->response(200, "successfull", $result['num_admins']); + } + } + throw new \Exception("Not allowed to execute given command.", 403); + } + /** * return an admin entry by either id or loginname * diff --git a/lib/Froxlor/Api/Commands/Certificates.php b/lib/Froxlor/Api/Commands/Certificates.php index a9c46c9e..6d6ee3be 100644 --- a/lib/Froxlor/Api/Commands/Certificates.php +++ b/lib/Froxlor/Api/Commands/Certificates.php @@ -174,6 +174,15 @@ class Certificates extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resou /** * lists all certificate entries * + * @param array $sql_search + * optional array with index = fieldname, and value = array with 'op' => operator (one of <, > or =), LIKE is used if left empty and 'value' => searchvalue + * @param int $sql_limit + * optional specify number of results to be returned + * @param int $sql_offset + * optional specify offset for resultset + * @param array $sql_orderby + * optional array with index = fieldname and value = ASC|DESC to order the resultset by one or more fields + * * @access admin, customer * @throws \Exception * @return string json-encoded array count|list @@ -188,7 +197,7 @@ class Certificates extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resou WHERE "; $qry_params = array(); - + $query_fields = array(); if ($this->isAdmin() && $this->getUserDetail('customers_see_all') == '0') { // admin with only customer-specific permissions $certs_stmt_query .= "d.adminid = :adminid "; @@ -200,7 +209,8 @@ class Certificates extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resou } else { $certs_stmt_query .= "1 "; } - $certs_stmt = Database::prepare($certs_stmt_query); + $certs_stmt = Database::prepare($certs_stmt_query . $this->getSearchWhere($query_fields) . $this->getOrderBy() . $this->getLimit()); + $qry_params = array_merge($qry_params, $query_fields); Database::pexecute($certs_stmt, $qry_params, true, true); $result = array(); while ($cert = $certs_stmt->fetch(\PDO::FETCH_ASSOC)) { @@ -218,6 +228,40 @@ class Certificates extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resou )); } + /** + * returns the total number of certificates for the given user + * + * @access admin, customer + * @throws \Exception + * @return string json-encoded array + */ + public function listingCount() + { + // select all my (accessable) certificates + $certs_stmt_query = "SELECT COUNT(s.*) as num_certs + FROM `" . TABLE_PANEL_DOMAIN_SSL_SETTINGS . "` s + LEFT JOIN `" . TABLE_PANEL_DOMAINS . "` d ON `d`.`id` = `s`.`domainid` + LEFT JOIN `" . TABLE_PANEL_CUSTOMERS . "` c ON `c`.`customerid` = `d`.`customerid` + WHERE "; + $qry_params = array(); + if ($this->isAdmin() && $this->getUserDetail('customers_see_all') == '0') { + // admin with only customer-specific permissions + $certs_stmt_query .= "d.adminid = :adminid "; + $qry_params['adminid'] = $this->getUserDetail('adminid'); + } elseif ($this->isAdmin() == false) { + // customer-area + $certs_stmt_query .= "d.customerid = :cid "; + $qry_params['cid'] = $this->getUserDetail('customerid'); + } else { + $certs_stmt_query .= "1 "; + } + $certs_stmt = Database::prepare($certs_stmt_query); + $result = Database::pexecute_first($certs_stmt, $qry_params, true, true); + if ($result) { + return $this->response(200, "successfull", $result['num_certs']); + } + } + /** * delete certificates entry by id * diff --git a/lib/Froxlor/Api/Commands/Cronjobs.php b/lib/Froxlor/Api/Commands/Cronjobs.php index b8341f4a..66fda2cc 100644 --- a/lib/Froxlor/Api/Commands/Cronjobs.php +++ b/lib/Froxlor/Api/Commands/Cronjobs.php @@ -127,6 +127,15 @@ class Cronjobs extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceE /** * lists all cronjob entries * + * @param array $sql_search + * optional array with index = fieldname, and value = array with 'op' => operator (one of <, > or =), LIKE is used if left empty and 'value' => searchvalue + * @param int $sql_limit + * optional specify number of results to be returned + * @param int $sql_offset + * optional specify offset for resultset + * @param array $sql_orderby + * optional array with index = fieldname and value = ASC|DESC to order the resultset by one or more fields + * * @access admin * @throws \Exception * @return string json-encoded array count|list @@ -135,10 +144,10 @@ class Cronjobs extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceE { if ($this->isAdmin()) { $this->logger()->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_NOTICE, "[API] list cronjobs"); + $query_fields = array(); $result_stmt = Database::prepare(" - SELECT `c`.* FROM `" . TABLE_PANEL_CRONRUNS . "` `c` ORDER BY `module` ASC, `cronfile` ASC - "); - Database::pexecute($result_stmt); + SELECT `c`.* FROM `" . TABLE_PANEL_CRONRUNS . "` `c` " . $this->getSearchWhere($query_fields) . $this->getOrderBy() . $this->getLimit()); + Database::pexecute($result_stmt, $query_fields, true, true); $result = array(); while ($row = $result_stmt->fetch(\PDO::FETCH_ASSOC)) { $result[] = $row; @@ -151,6 +160,27 @@ class Cronjobs extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceE throw new \Exception("Not allowed to execute given command.", 403); } + /** + * returns the total number of cronjobs + * + * @access admin + * @throws \Exception + * @return string json-encoded array + */ + public function listingCount() + { + if ($this->isAdmin()) { + $result_stmt = Database::prepare(" + SELECT COUNT(`c`.*) as num_crons FROM `" . TABLE_PANEL_CRONRUNS . "` `c` + "); + $result = Database::pexecute_first($result_stmt, null, true, true); + if ($result) { + return $this->response(200, "successfull", $result['num_crons']); + } + } + throw new \Exception("Not allowed to execute given command.", 403); + } + /** * You cannot delete system cronjobs. */ diff --git a/lib/Froxlor/Api/Commands/CustomerBackups.php b/lib/Froxlor/Api/Commands/CustomerBackups.php index 00fe19f4..19f7b4ac 100644 --- a/lib/Froxlor/Api/Commands/CustomerBackups.php +++ b/lib/Froxlor/Api/Commands/CustomerBackups.php @@ -137,7 +137,15 @@ class CustomerBackups extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Re * optional, admin-only, select backup-jobs of a specific customer by id * @param string $loginname * optional, admin-only, select backup-jobs of a specific customer by loginname - * + * @param array $sql_search + * optional array with index = fieldname, and value = array with 'op' => operator (one of <, > or =), LIKE is used if left empty and 'value' => searchvalue + * @param int $sql_limit + * optional specify number of results to be returned + * @param int $sql_offset + * optional specify offset for resultset + * @param array $sql_orderby + * optional array with index = fieldname and value = ASC|DESC to order the resultset by one or more fields + * * @access admin, customer * @throws \Exception * @return string json-encoded array count|list @@ -149,8 +157,9 @@ class CustomerBackups extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Re $customer_ids = $this->getAllowedCustomerIds('extras.backup'); // check whether there is a backup-job for this customer - $sel_stmt = Database::prepare("SELECT * FROM `" . TABLE_PANEL_TASKS . "` WHERE `type` = '20'"); - Database::pexecute($sel_stmt); + $query_fields = array(); + $sel_stmt = Database::prepare("SELECT * FROM `" . TABLE_PANEL_TASKS . "` WHERE `type` = '20'" . $this->getSearchWhere($query_fields, true) . $this->getOrderBy() . $this->getLimit()); + Database::pexecute($sel_stmt, $query_fields, true, true); $result = array(); while ($entry = $sel_stmt->fetch(\PDO::FETCH_ASSOC)) { $entry['data'] = json_decode($entry['data'], true); @@ -165,6 +174,37 @@ class CustomerBackups extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Re )); } + /** + * returns the total number of planned backups + * + * @param int $customerid + * optional, admin-only, select backup-jobs of a specific customer by id + * @param string $loginname + * optional, admin-only, select backup-jobs of a specific customer by loginname + * + * @access admin, customer + * @throws \Exception + * @return string json-encoded array + */ + public function listingCount() + { + $this->validateAccess(); + + $customer_ids = $this->getAllowedCustomerIds('extras.backup'); + + // check whether there is a backup-job for this customer + $result_count = 0; + $sel_stmt = Database::prepare("SELECT * FROM `" . TABLE_PANEL_TASKS . "` WHERE `type` = '20'"); + Database::pexecute($sel_stmt, null, true, true); + while ($entry = $sel_stmt->fetch(\PDO::FETCH_ASSOC)) { + $entry['data'] = json_decode($entry['data'], true); + if (in_array($entry['data']['customerid'], $customer_ids)) { + $result_count ++; + } + } + return $this->response(200, "successfull", $result_count); + } + /** * delete a planned backup-jobs by id, if called from an admin you need to specify the customerid/loginname * @@ -195,7 +235,7 @@ class CustomerBackups extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Re if ($backupjob['id'] == $entry && in_array($backupjob['data']['customerid'], $customer_ids)) { Database::pexecute($del_stmt, array( 'tid' => $entry - )); + ), true, true); $this->logger()->logAction($this->isAdmin() ? \Froxlor\FroxlorLogger::ADM_ACTION : \Froxlor\FroxlorLogger::USR_ACTION, LOG_NOTICE, "[API] deleted planned customer-backup #" . $entry); return $this->response(200, "successfull", true); } diff --git a/lib/Froxlor/Api/Commands/Customers.php b/lib/Froxlor/Api/Commands/Customers.php index 8d500f9b..c7c0e2e8 100644 --- a/lib/Froxlor/Api/Commands/Customers.php +++ b/lib/Froxlor/Api/Commands/Customers.php @@ -25,6 +25,15 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource /** * lists all customer entries * + * @param array $sql_search + * optional array with index = fieldname, and value = array with 'op' => operator (one of <, > or =), LIKE is used if left empty and 'value' => searchvalue + * @param int $sql_limit + * optional specify number of results to be returned + * @param int $sql_offset + * optional specify offset for resultset + * @param array $sql_orderby + * optional array with index = fieldname and value = ASC|DESC to order the resultset by one or more fields + * * @access admin * @throws \Exception * @return string json-encoded array count|list @@ -33,19 +42,19 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource { if ($this->isAdmin()) { $this->logger()->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_NOTICE, "[API] list customers"); + $query_fields = array(); $result_stmt = Database::prepare(" SELECT `c`.*, `a`.`loginname` AS `adminname` FROM `" . TABLE_PANEL_CUSTOMERS . "` `c`, `" . TABLE_PANEL_ADMINS . "` `a` WHERE " . ($this->getUserDetail('customers_see_all') ? '' : " `c`.`adminid` = :adminid AND ") . " - `c`.`adminid` = `a`.`adminid` - ORDER BY `c`.`loginname` ASC - "); + `c`.`adminid` = `a`.`adminid`" . $this->getSearchWhere($query_fields, true) . $this->getOrderBy() . $this->getLimit()); $params = array(); if ($this->getUserDetail('customers_see_all') == '0') { $params = array( 'adminid' => $this->getUserDetail('adminid') ); } + $params = array_merge($params, $query_fields); Database::pexecute($result_stmt, $params, true, true); $result = array(); while ($row = $result_stmt->fetch(\PDO::FETCH_ASSOC)) { @@ -59,6 +68,34 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource throw new \Exception("Not allowed to execute given command.", 403); } + /** + * returns the total number of customers for the given admin + * + * @access admin + * @throws \Exception + * @return string json-encoded array + */ + public function listingCount() + { + if ($this->isAdmin()) { + $result_stmt = Database::prepare(" + SELECT COUNT(*) as num_customers + FROM `" . TABLE_PANEL_CUSTOMERS . "` + WHERE " . ($this->getUserDetail('customers_see_all') ? "1" : " `adminid` = :adminid ")); + $params = array(); + if ($this->getUserDetail('customers_see_all') == '0') { + $params = array( + 'adminid' => $this->getUserDetail('adminid') + ); + } + $result = Database::pexecute_first($result_stmt, $params, true, true); + if ($result) { + return $this->response(200, "successfull", $result['num_customers']); + } + } + throw new \Exception("Not allowed to execute given command.", 403); + } + /** * return a customer entry by either id or loginname * diff --git a/lib/Froxlor/Api/Commands/DirOptions.php b/lib/Froxlor/Api/Commands/DirOptions.php index ad5116b9..2ce1a425 100644 --- a/lib/Froxlor/Api/Commands/DirOptions.php +++ b/lib/Froxlor/Api/Commands/DirOptions.php @@ -285,7 +285,15 @@ class DirOptions extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc * optional, admin-only, select directory-protections of a specific customer by id * @param string $loginname * optional, admin-only, select directory-protections of a specific customer by loginname - * + * @param array $sql_search + * optional array with index = fieldname, and value = array with 'op' => operator (one of <, > or =), LIKE is used if left empty and 'value' => searchvalue + * @param int $sql_limit + * optional specify number of results to be returned + * @param int $sql_offset + * optional specify offset for resultset + * @param array $sql_orderby + * optional array with index = fieldname and value = ASC|DESC to order the resultset by one or more fields + * * @access admin, customer * @throws \Exception * @return string json-encoded array count|list @@ -298,11 +306,12 @@ class DirOptions extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc $customer_ids = $this->getAllowedCustomerIds('extras.pathoptions'); $result = array(); + $query_fields = array(); $result_stmt = Database::prepare(" SELECT * FROM `" . TABLE_PANEL_HTACCESS . "` - WHERE `customerid` IN (" . implode(', ', $customer_ids) . ") - "); - Database::pexecute($result_stmt, null, true, true); + WHERE `customerid` IN (" . implode(', ', $customer_ids) . ")" . $this->getSearchWhere($query_fields, true) . $this->getOrderBy() . $this->getLimit() + ); + Database::pexecute($result_stmt, $query_fields, true, true); while ($row = $result_stmt->fetch(\PDO::FETCH_ASSOC)) { $result[] = $row; } @@ -313,6 +322,36 @@ class DirOptions extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc )); } + /** + * returns the total number of accessable directory options + * + * @param int $customerid + * optional, admin-only, select directory-protections of a specific customer by id + * @param string $loginname + * optional, admin-only, select directory-protections of a specific customer by loginname + * + * @access admin, customer + * @throws \Exception + * @return string json-encoded array count|list + */ + public function listingCount() + { + if ($this->isAdmin() == false && Settings::IsInList('panel.customer_hide_options', 'extras')) { + throw new \Exception("You cannot access this resource", 405); + } + $customer_ids = $this->getAllowedCustomerIds('extras.pathoptions'); + + $result = array(); + $result_stmt = Database::prepare(" + SELECT COUNT(*) as num_htaccess FROM `" . TABLE_PANEL_HTACCESS . "` + WHERE `customerid` IN (" . implode(', ', $customer_ids) . ") + "); + $result = Database::pexecute_first($result_stmt, null, true, true); + if ($result) { + return $this->response(200, "successfull", $result['num_htaccess']); + } + } + /** * delete a directory-options by id * @@ -373,7 +412,7 @@ class DirOptions extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc Database::pexecute($stmt, array( "customerid" => $customer_data['customerid'], "id" => $id - )); + ), true, true); $this->logger()->logAction($this->isAdmin() ? \Froxlor\FroxlorLogger::ADM_ACTION : \Froxlor\FroxlorLogger::USR_ACTION, LOG_INFO, "[API] deleted directory-option for '" . str_replace($customer_data['documentroot'], '/', $result['path']) . "'"); \Froxlor\System\Cronjob::inserttask('1'); return $this->response(200, "successfull", $result); diff --git a/lib/Froxlor/Api/Commands/DirProtections.php b/lib/Froxlor/Api/Commands/DirProtections.php index 7d1bdf7e..c609c377 100644 --- a/lib/Froxlor/Api/Commands/DirProtections.php +++ b/lib/Froxlor/Api/Commands/DirProtections.php @@ -268,7 +268,15 @@ class DirProtections extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Res * optional, admin-only, select directory-protections of a specific customer by id * @param string $loginname * optional, admin-only, select directory-protections of a specific customer by loginname - * + * @param array $sql_search + * optional array with index = fieldname, and value = array with 'op' => operator (one of <, > or =), LIKE is used if left empty and 'value' => searchvalue + * @param int $sql_limit + * optional specify number of results to be returned + * @param int $sql_offset + * optional specify offset for resultset + * @param array $sql_orderby + * optional array with index = fieldname and value = ASC|DESC to order the resultset by one or more fields + * * @access admin, customer * @throws \Exception * @return string json-encoded array count|list @@ -281,11 +289,11 @@ class DirProtections extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Res $customer_ids = $this->getAllowedCustomerIds('extras.directoryprotection'); $result = array(); + $query_fields = array(); $result_stmt = Database::prepare(" SELECT * FROM `" . TABLE_PANEL_HTPASSWDS . "` - WHERE `customerid` IN (" . implode(', ', $customer_ids) . ") - "); - Database::pexecute($result_stmt, null, true, true); + WHERE `customerid` IN (" . implode(', ', $customer_ids) . ")" . $this->getSearchWhere($query_fields, true) . $this->getOrderBy() . $this->getLimit()); + Database::pexecute($result_stmt, $query_fields, true, true); while ($row = $result_stmt->fetch(\PDO::FETCH_ASSOC)) { $result[] = $row; } @@ -296,6 +304,36 @@ class DirProtections extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Res )); } + /** + * returns the total number of accessable directory protections + * + * @param int $customerid + * optional, admin-only, select directory-protections of a specific customer by id + * @param string $loginname + * optional, admin-only, select directory-protections of a specific customer by loginname + * + * @access admin, customer + * @throws \Exception + * @return string json-encoded array count|list + */ + public function listingCount() + { + if ($this->isAdmin() == false && Settings::IsInList('panel.customer_hide_options', 'extras')) { + throw new \Exception("You cannot access this resource", 405); + } + $customer_ids = $this->getAllowedCustomerIds('extras.directoryprotection'); + + $result = array(); + $result_stmt = Database::prepare(" + SELECT COUNT(*) as num_htpasswd FROM `" . TABLE_PANEL_HTPASSWDS . "` + WHERE `customerid` IN (" . implode(', ', $customer_ids) . ") + "); + $result = Database::pexecute_first($result_stmt, null, true, true); + if ($result) { + return $this->response(200, "successfull", $result['num_htpasswd']); + } + } + /** * delete a directory-protection by either id or username * diff --git a/lib/Froxlor/Api/Commands/DomainZones.php b/lib/Froxlor/Api/Commands/DomainZones.php index 2c94823c..303be716 100644 --- a/lib/Froxlor/Api/Commands/DomainZones.php +++ b/lib/Froxlor/Api/Commands/DomainZones.php @@ -379,6 +379,14 @@ class DomainZones extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour * optional, the domain id * @param string $domainname * optional, the domain name + * @param array $sql_search + * optional array with index = fieldname, and value = array with 'op' => operator (one of <, > or =), LIKE is used if left empty and 'value' => searchvalue + * @param int $sql_limit + * optional specify number of results to be returned + * @param int $sql_offset + * optional specify offset for resultset + * @param array $sql_orderby + * optional array with index = fieldname and value = ASC|DESC to order the resultset by one or more fields * * @access admin, customer * @throws \Exception @@ -404,11 +412,10 @@ class DomainZones extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour 'domainname' => $domainname )); $id = $result['id']; - - $sel_stmt = Database::prepare("SELECT * FROM `" . TABLE_DOMAIN_DNS . "` WHERE `domain_id` = :did"); - Database::pexecute($sel_stmt, array( - 'did' => $id - ), true, true); + $query_fields = array(); + $sel_stmt = Database::prepare("SELECT * FROM `" . TABLE_DOMAIN_DNS . "` WHERE `domain_id` = :did" . $this->getSearchWhere($query_fields, true) . $this->getOrderBy() . $this->getLimit()); + $query_fields['did'] = $id; + Database::pexecute($sel_stmt, $query_fields, true, true); $result = []; while ($row = $sel_stmt->fetch(\PDO::FETCH_ASSOC)) { $result[] = $row; @@ -419,6 +426,48 @@ class DomainZones extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour )); } + /** + * returns the total number of domainzone-entries for given domain + * + * @param int $id + * optional, the domain id + * @param string $domainname + * optional, the domain name + * + * @access admin, customer + * @throws \Exception + * @return bool + */ + public function listingCount() + { + if (Settings::Get('system.dnsenabled') != '1') { + throw new \Exception("DNS service not enabled on this system", 405); + } + + if ($this->isAdmin() == false && $this->getUserDetail('dnsenabled') != '1') { + throw new \Exception("You cannot access this resource", 405); + } + + $id = $this->getParam('id', true, 0); + $dn_optional = ($id <= 0 ? false : true); + $domainname = $this->getParam('domainname', $dn_optional, ''); + + // get requested domain + $result = $this->apiCall('SubDomains.get', array( + 'id' => $id, + 'domainname' => $domainname + )); + $id = $result['id']; + + $sel_stmt = Database::prepare("SELECT COUNT(*) as num_dns FROM `" . TABLE_DOMAIN_DNS . "` WHERE `domain_id` = :did"); + $result = Database::pexecute_first($sel_stmt, array( + 'did' => $id + ), true, true); + if ($result) { + return $this->response(200, "successfull", $result['num_dns']); + } + } + /** * deletes a domain-dns entry by id * diff --git a/lib/Froxlor/Api/Commands/Domains.php b/lib/Froxlor/Api/Commands/Domains.php index 8fb5c190..7c0b95b6 100644 --- a/lib/Froxlor/Api/Commands/Domains.php +++ b/lib/Froxlor/Api/Commands/Domains.php @@ -25,6 +25,15 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn /** * lists all domain entries * + * @param array $sql_search + * optional array with index = fieldname, and value = array with 'op' => operator (one of <, > or =), LIKE is used if left empty and 'value' => searchvalue + * @param int $sql_limit + * optional specify number of results to be returned + * @param int $sql_offset + * optional specify offset for resultset + * @param array $sql_orderby + * optional array with index = fieldname and value = ASC|DESC to order the resultset by one or more fields + * * @access admin * @throws \Exception * @return string json-encoded array count|list @@ -33,6 +42,7 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn { if ($this->isAdmin()) { $this->logger()->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_NOTICE, "[API] list domains"); + $query_fields = array(); $result_stmt = Database::prepare(" SELECT `d`.*, `c`.`loginname`, `c`.`deactivated`, `c`.`name`, `c`.`firstname`, `c`.`company`, `c`.`standardsubdomain`, @@ -40,12 +50,13 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn FROM `" . TABLE_PANEL_DOMAINS . "` `d` LEFT JOIN `" . TABLE_PANEL_CUSTOMERS . "` `c` USING(`customerid`) LEFT JOIN `" . TABLE_PANEL_DOMAINS . "` `ad` ON `d`.`aliasdomain`=`ad`.`id` - WHERE `d`.`parentdomainid`='0' " . ($this->getUserDetail('customers_see_all') ? '' : " AND `d`.`adminid` = :adminid ")); + WHERE `d`.`parentdomainid`='0' " . ($this->getUserDetail('customers_see_all') ? '' : " AND `d`.`adminid` = :adminid ") . $this->getSearchWhere($query_fields, true) . $this->getOrderBy() . $this->getLimit()); $params = array(); if ($this->getUserDetail('customers_see_all') == '0') { $params['adminid'] = $this->getUserDetail('adminid'); } - Database::pexecute($result_stmt, $params); + $params = array_merge($params, $query_fields); + Database::pexecute($result_stmt, $params, true, true); $result = array(); while ($row = $result_stmt->fetch(\PDO::FETCH_ASSOC)) { $result[] = $row; @@ -58,6 +69,36 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn throw new \Exception("Not allowed to execute given command.", 403); } + /** + * returns the total number of accessable domains + * + * @access admin + * @throws \Exception + * @return string json-encoded array count|list + */ + public function listingCount() + { + if ($this->isAdmin()) { + $this->logger()->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_NOTICE, "[API] list domains"); + $result_stmt = Database::prepare(" + SELECT + COUNT(`d`.*) as num_domains + FROM `" . TABLE_PANEL_DOMAINS . "` `d` + LEFT JOIN `" . TABLE_PANEL_CUSTOMERS . "` `c` USING(`customerid`) + LEFT JOIN `" . TABLE_PANEL_DOMAINS . "` `ad` ON `d`.`aliasdomain`=`ad`.`id` + WHERE `d`.`parentdomainid`='0' " . ($this->getUserDetail('customers_see_all') ? '' : " AND `d`.`adminid` = :adminid ")); + $params = array(); + if ($this->getUserDetail('customers_see_all') == '0') { + $params['adminid'] = $this->getUserDetail('adminid'); + } + $result = Database::pexecute_first($result_stmt, $params, true, true); + if ($result) { + return $this->response(200, "successfull", $result['num_domains']); + } + } + throw new \Exception("Not allowed to execute given command.", 403); + } + /** * return a domain entry by either id or domainname * diff --git a/lib/Froxlor/Api/Commands/EmailAccounts.php b/lib/Froxlor/Api/Commands/EmailAccounts.php index 98f52b3c..853bc8d2 100644 --- a/lib/Froxlor/Api/Commands/EmailAccounts.php +++ b/lib/Froxlor/Api/Commands/EmailAccounts.php @@ -388,12 +388,21 @@ class EmailAccounts extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Reso } /** - * You cannot directly list email forwarders. + * You cannot directly list email accounts. * You need to call Emails.listing() */ public function listing() { - throw new \Exception('You cannot directly list email forwarders. You need to call Emails.listing()', 303); + throw new \Exception('You cannot directly list email accounts. You need to call Emails.listing()', 303); + } + + /** + * You cannot directly count email accounts. + * You need to call Emails.listingCount() + */ + public function listingCount() + { + throw new \Exception('You cannot directly count email accounts. You need to call Emails.listingCount()', 303); } /** diff --git a/lib/Froxlor/Api/Commands/EmailForwarders.php b/lib/Froxlor/Api/Commands/EmailForwarders.php index 9ca87e6f..fcfff35a 100644 --- a/lib/Froxlor/Api/Commands/EmailForwarders.php +++ b/lib/Froxlor/Api/Commands/EmailForwarders.php @@ -134,6 +134,15 @@ class EmailForwarders extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Re throw new \Exception('You cannot directly list email forwarders. You need to call Emails.listing()', 303); } + /** + * You cannot directly count email forwarders. + * You need to call Emails.listingCount() + */ + public function listingCount() + { + throw new \Exception('You cannot directly count email forwarders. You need to call Emails.listingCount()', 303); + } + /** * delete email-forwarder entry for given email-address by either id or email-address and forwarder-id * diff --git a/lib/Froxlor/Api/Commands/Emails.php b/lib/Froxlor/Api/Commands/Emails.php index f4cb959a..f5efc5fb 100644 --- a/lib/Froxlor/Api/Commands/Emails.php +++ b/lib/Froxlor/Api/Commands/Emails.php @@ -265,7 +265,15 @@ class Emails extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt * optional, admin-only, select email addresses of a specific customer by id * @param string $loginname * optional, admin-only, select email addresses of a specific customer by loginname - * + * @param array $sql_search + * optional array with index = fieldname, and value = array with 'op' => operator (one of <, > or =), LIKE is used if left empty and 'value' => searchvalue + * @param int $sql_limit + * optional specify number of results to be returned + * @param int $sql_offset + * optional specify offset for resultset + * @param array $sql_orderby + * optional array with index = fieldname and value = ASC|DESC to order the resultset by one or more fields + * * @access admin, customer * @throws \Exception * @return string json-encoded array count|list @@ -274,14 +282,14 @@ class Emails extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt { $customer_ids = $this->getAllowedCustomerIds('email'); $result = array(); + $query_fields = array(); $result_stmt = Database::prepare(" SELECT m.`id`, m.`domainid`, m.`email`, m.`email_full`, m.`iscatchall`, u.`quota`, m.`destination`, m.`popaccountid`, d.`domain`, u.`mboxsize` FROM `" . TABLE_MAIL_VIRTUAL . "` m LEFT JOIN `" . TABLE_PANEL_DOMAINS . "` d ON (m.`domainid` = d.`id`) LEFT JOIN `" . TABLE_MAIL_USERS . "` u ON (m.`popaccountid` = u.`id`) - WHERE m.`customerid` IN (" . implode(", ", $customer_ids) . ") - "); - Database::pexecute($result_stmt, null, true, true); + WHERE m.`customerid` IN (" . implode(", ", $customer_ids) . ")" . $this->getSearchWhere($query_fields, true) . $this->getOrderBy() . $this->getLimit()); + Database::pexecute($result_stmt, $query_fields, true, true); while ($row = $result_stmt->fetch(\PDO::FETCH_ASSOC)) { $result[] = $row; } @@ -292,6 +300,34 @@ class Emails extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt )); } + /** + * returns the total number of accessable email addresses + * + * @param int $customerid + * optional, admin-only, select email addresses of a specific customer by id + * @param string $loginname + * optional, admin-only, select email addresses of a specific customer by loginname + * + * @access admin, customer + * @throws \Exception + * @return string json-encoded array + */ + public function listingCount() + { + $customer_ids = $this->getAllowedCustomerIds('email'); + $result_stmt = Database::prepare(" + SELECT COUNT(m.*) as num_emails + FROM `" . TABLE_MAIL_VIRTUAL . "` m + LEFT JOIN `" . TABLE_PANEL_DOMAINS . "` d ON (m.`domainid` = d.`id`) + LEFT JOIN `" . TABLE_MAIL_USERS . "` u ON (m.`popaccountid` = u.`id`) + WHERE m.`customerid` IN (" . implode(", ", $customer_ids) . ") + "); + $result = Database::pexecute_first($result_stmt, null, true, true); + if ($result) { + return $this->response(200, "successfull", $result['num_emails']); + } + } + /** * delete an email address by either id or username * diff --git a/lib/Froxlor/Api/Commands/FpmDaemons.php b/lib/Froxlor/Api/Commands/FpmDaemons.php index eaac40d1..f36c1a19 100644 --- a/lib/Froxlor/Api/Commands/FpmDaemons.php +++ b/lib/Froxlor/Api/Commands/FpmDaemons.php @@ -24,6 +24,15 @@ class FpmDaemons extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc /** * lists all fpm-daemon entries * + * @param array $sql_search + * optional array with index = fieldname, and value = array with 'op' => operator (one of <, > or =), LIKE is used if left empty and 'value' => searchvalue + * @param int $sql_limit + * optional specify number of results to be returned + * @param int $sql_offset + * optional specify offset for resultset + * @param array $sql_orderby + * optional array with index = fieldname and value = ASC|DESC to order the resultset by one or more fields + * * @access admin * @throws \Exception * @return string json-encoded array count|list @@ -32,21 +41,18 @@ class FpmDaemons extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc { if ($this->isAdmin()) { $this->logger()->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_NOTICE, "[API] list fpm-daemons"); - - $result = Database::query(" - SELECT * FROM `" . TABLE_PANEL_FPMDAEMONS . "` ORDER BY `description` ASC - "); - + $query_fields = array(); + $result_stmt = Database::prepare(" + SELECT * FROM `" . TABLE_PANEL_FPMDAEMONS . "`" . $this->getSearchWhere($query_fields) . $this->getOrderBy() . $this->getLimit()); + Database::pexecute($result_stmt, $query_fields, true, true); $fpmdaemons = array(); - while ($row = $result->fetch(\PDO::FETCH_ASSOC)) { + while ($row = $result_stmt->fetch(\PDO::FETCH_ASSOC)) { $query_params = array( 'id' => $row['id'] ); - $query = "SELECT * FROM `" . TABLE_PANEL_PHPCONFIGS . "` WHERE `fpmsettingid` = :id"; - - $configresult_stmt = Database::prepare($query); + $configresult_stmt = Database::prepare("SELECT * FROM `" . TABLE_PANEL_PHPCONFIGS . "` WHERE `fpmsettingid` = :id"); Database::pexecute($configresult_stmt, $query_params, true, true); $configs = array(); @@ -72,6 +78,27 @@ class FpmDaemons extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc throw new \Exception("Not allowed to execute given command.", 403); } + /** + * returns the total number of accessable fpm daemons + * + * @access admin + * @throws \Exception + * @return string json-encoded array + */ + public function listingCount() + { + if ($this->isAdmin()) { + $result_stmt = Database::prepare(" + SELECT COUNT(*) as num_fpms FROM `" . TABLE_PANEL_FPMDAEMONS . "` + "); + $result = Database::pexecute_first($result_stmt, null, true, true); + if ($result) { + return $this->response(200, "successfull", $result['num_fpms']); + } + } + throw new \Exception("Not allowed to execute given command.", 403); + } + /** * return a fpm-daemon entry by id * diff --git a/lib/Froxlor/Api/Commands/Ftps.php b/lib/Froxlor/Api/Commands/Ftps.php index 876c0f93..59b7906e 100644 --- a/lib/Froxlor/Api/Commands/Ftps.php +++ b/lib/Froxlor/Api/Commands/Ftps.php @@ -460,7 +460,15 @@ class Ftps extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEntit * optional, admin-only, select ftp-users of a specific customer by id * @param string $loginname * optional, admin-only, select ftp-users of a specific customer by loginname - * + * @param array $sql_search + * optional array with index = fieldname, and value = array with 'op' => operator (one of <, > or =), LIKE is used if left empty and 'value' => searchvalue + * @param int $sql_limit + * optional specify number of results to be returned + * @param int $sql_offset + * optional specify offset for resultset + * @param array $sql_orderby + * optional array with index = fieldname and value = ASC|DESC to order the resultset by one or more fields + * * @access admin, customer * @throws \Exception * @return string json-encoded array count|list @@ -469,11 +477,11 @@ class Ftps extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEntit { $customer_ids = $this->getAllowedCustomerIds('ftp'); $result = array(); + $query_fields = array(); $result_stmt = Database::prepare(" SELECT * FROM `" . TABLE_FTP_USERS . "` - WHERE `customerid` IN (" . implode(", ", $customer_ids) . ") - "); - Database::pexecute($result_stmt, null, true, true); + WHERE `customerid` IN (" . implode(", ", $customer_ids) . ")" . $this->getSearchWhere($query_fields, true) . $this->getOrderBy() . $this->getLimit()); + Database::pexecute($result_stmt, $query_fields, true, true); while ($row = $result_stmt->fetch(\PDO::FETCH_ASSOC)) { $result[] = $row; } @@ -484,6 +492,32 @@ class Ftps extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEntit )); } + /** + * returns the total number of accessable ftp accounts + * + * @param int $customerid + * optional, admin-only, select ftp-users of a specific customer by id + * @param string $loginname + * optional, admin-only, select ftp-users of a specific customer by loginname + * + * @access admin, customer + * @throws \Exception + * @return string json-encoded array + */ + public function listingCount() + { + $customer_ids = $this->getAllowedCustomerIds('ftp'); + $result = array(); + $result_stmt = Database::prepare(" + SELECT COUNT(*) as num_ftps FROM `" . TABLE_FTP_USERS . "` + WHERE `customerid` IN (" . implode(", ", $customer_ids) . ") + "); + $result = Database::pexecute_first($result_stmt, null, true, true); + if ($result) { + return $this->response(200, "successfull", $result['num_ftps']); + } + } + /** * delete a ftp-user by either id or username * diff --git a/lib/Froxlor/Api/Commands/HostingPlans.php b/lib/Froxlor/Api/Commands/HostingPlans.php index b20db944..0e39b9c6 100644 --- a/lib/Froxlor/Api/Commands/HostingPlans.php +++ b/lib/Froxlor/Api/Commands/HostingPlans.php @@ -25,6 +25,15 @@ class HostingPlans extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resou /** * list all available hosting plans * + * @param array $sql_search + * optional array with index = fieldname, and value = array with 'op' => operator (one of <, > or =), LIKE is used if left empty and 'value' => searchvalue + * @param int $sql_limit + * optional specify number of results to be returned + * @param int $sql_offset + * optional specify offset for resultset + * @param array $sql_orderby + * optional array with index = fieldname and value = ASC|DESC to order the resultset by one or more fields + * * @access admin * @throws \Exception * @return string json-encoded array count|list @@ -33,15 +42,17 @@ class HostingPlans extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resou { if ($this->isAdmin()) { $this->logger()->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_NOTICE, "[API] list hosting-plans"); + $query_fields = array(); $result_stmt = Database::prepare(" SELECT p.*, a.loginname as adminname FROM `" . TABLE_PANEL_PLANS . "` p, `" . TABLE_PANEL_ADMINS . "` a - WHERE `p`.`adminid` = `a`.`adminid`" . ($this->getUserDetail('customers_see_all') ? '' : " AND `p`.`adminid` = :adminid ")); + WHERE `p`.`adminid` = `a`.`adminid`" . ($this->getUserDetail('customers_see_all') ? '' : " AND `p`.`adminid` = :adminid ") . $this->getSearchWhere($query_fields, true) . $this->getOrderBy() . $this->getLimit()); $params = array(); if ($this->getUserDetail('customers_see_all') == '0') { $params['adminid'] = $this->getUserDetail('adminid'); } - Database::pexecute($result_stmt, $params); + $params = array_merge($params, $query_fields); + Database::pexecute($result_stmt, $params, true, true); $result = array(); while ($row = $result_stmt->fetch(\PDO::FETCH_ASSOC)) { $result[] = $row; @@ -54,6 +65,32 @@ class HostingPlans extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resou throw new \Exception("Not allowed to execute given command.", 403); } + /** + * returns the total number of accessable hosting plans + * + * @access admin + * @throws \Exception + * @return string json-encoded array + */ + public function listingCount() + { + if ($this->isAdmin()) { + $result_stmt = Database::prepare(" + SELECT COUNT(p.*) as num_plans + FROM `" . TABLE_PANEL_PLANS . "` p, `" . TABLE_PANEL_ADMINS . "` a + WHERE `p`.`adminid` = `a`.`adminid`" . ($this->getUserDetail('customers_see_all') ? '' : " AND `p`.`adminid` = :adminid ")); + $params = array(); + if ($this->getUserDetail('customers_see_all') == '0') { + $params['adminid'] = $this->getUserDetail('adminid'); + } + $result = Database::pexecute_first($result_stmt, $params, true, true); + if ($result) { + return $this->response(200, "successfull", $result['num_plans']); + } + } + throw new \Exception("Not allowed to execute given command.", 403); + } + /** * return a hosting-plan entry by either id or plan-name * diff --git a/lib/Froxlor/Api/Commands/IpsAndPorts.php b/lib/Froxlor/Api/Commands/IpsAndPorts.php index 801d6f7c..54d7a4a2 100644 --- a/lib/Froxlor/Api/Commands/IpsAndPorts.php +++ b/lib/Froxlor/Api/Commands/IpsAndPorts.php @@ -25,6 +25,15 @@ class IpsAndPorts extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour /** * lists all ip/port entries * + * @param array $sql_search + * optional array with index = fieldname, and value = array with 'op' => operator (one of <, > or =), LIKE is used if left empty and 'value' => searchvalue + * @param int $sql_limit + * optional specify number of results to be returned + * @param int $sql_offset + * optional specify offset for resultset + * @param array $sql_orderby + * optional array with index = fieldname and value = ASC|DESC to order the resultset by one or more fields + * * @access admin * @throws \Exception * @return string json-encoded array count|list @@ -34,12 +43,14 @@ class IpsAndPorts extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour if ($this->isAdmin() && ($this->getUserDetail('change_serversettings') || ! empty($this->getUserDetail('ip')))) { $this->logger()->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_NOTICE, "[API] list ips and ports"); $ip_where = ""; + $append_where = false; if (! empty($this->getUserDetail('ip')) && $this->getUserDetail('ip') != - 1) { $ip_where = "WHERE `id` IN (" . implode(", ", json_decode($this->getUserDetail('ip'), true)) . ")"; + $append_where = true; } + $query_fields = array(); $result_stmt = Database::prepare(" - SELECT * FROM `" . TABLE_PANEL_IPSANDPORTS . "` " . $ip_where . " ORDER BY `ip` ASC, `port` ASC - "); + SELECT * FROM `" . TABLE_PANEL_IPSANDPORTS . "` " . $ip_where . $this->getSearchWhere($query_fields, $append_where) . $this->getOrderBy() . $this->getLimit()); Database::pexecute($result_stmt, null, true, true); $result = array(); while ($row = $result_stmt->fetch(\PDO::FETCH_ASSOC)) { @@ -53,6 +64,30 @@ class IpsAndPorts extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour throw new \Exception("Not allowed to execute given command.", 403); } + /** + * returns the total number of accessable ip/port entries + * + * @access admin + * @throws \Exception + * @return string json-encoded array + */ + public function listingCount() + { + if ($this->isAdmin() && ($this->getUserDetail('change_serversettings') || ! empty($this->getUserDetail('ip')))) { + $ip_where = ""; + if (! empty($this->getUserDetail('ip')) && $this->getUserDetail('ip') != - 1) { + $ip_where = "WHERE `id` IN (" . implode(", ", json_decode($this->getUserDetail('ip'), true)) . ")"; + } + $result_stmt = Database::prepare(" + SELECT COUNT(*) as num_ips FROM `" . TABLE_PANEL_IPSANDPORTS . "` " . $ip_where); + $result = Database::pexecute_first($result_stmt, null, true, true); + if ($result) { + return $this->response(200, "successfull", $result['num_plans']); + } + } + throw new \Exception("Not allowed to execute given command.", 403); + } + /** * return an ip/port entry by id * diff --git a/lib/Froxlor/Api/Commands/Mysqls.php b/lib/Froxlor/Api/Commands/Mysqls.php index 35f6062c..6ccc619b 100644 --- a/lib/Froxlor/Api/Commands/Mysqls.php +++ b/lib/Froxlor/Api/Commands/Mysqls.php @@ -359,7 +359,15 @@ class Mysqls extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt * optional, admin-only, select dbs of a specific customer by id * @param string $loginname * optional, admin-only, select dbs of a specific customer by loginname - * + * @param array $sql_search + * optional array with index = fieldname, and value = array with 'op' => operator (one of <, > or =), LIKE is used if left empty and 'value' => searchvalue + * @param int $sql_limit + * optional specify number of results to be returned + * @param int $sql_offset + * optional specify offset for resultset + * @param array $sql_orderby + * optional array with index = fieldname and value = ASC|DESC to order the resultset by one or more fields + * * @access admin, customer * @throws \Exception * @return string json-encoded array count|list @@ -369,10 +377,11 @@ class Mysqls extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt $result = array(); $dbserver = $this->getParam('mysql_server', true, - 1); $customer_ids = $this->getAllowedCustomerIds('mysql'); + $query_fields = array(); $result_stmt = Database::prepare(" SELECT * FROM `" . TABLE_PANEL_DATABASES . "` - WHERE `customerid`= :customerid AND `dbserver` = :dbserver - "); + WHERE `customerid`= :customerid AND `dbserver` = :dbserver". $this->getSearchWhere($query_fields, true) . $this->getOrderBy() . $this->getLimit() + ); if ($dbserver < 0) { // use all dbservers $dbservers_stmt = Database::query("SELECT DISTINCT `dbserver` FROM `" . TABLE_PANEL_DATABASES . "`"); @@ -388,10 +397,10 @@ class Mysqls extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt foreach ($customer_ids as $customer_id) { foreach ($dbservers as $_dbserver) { - Database::pexecute($result_stmt, array( + Database::pexecute($result_stmt, array_merge(array( 'customerid' => $customer_id, 'dbserver' => $_dbserver['dbserver'] - ), true, true); + ), $query_fields), true, true); // Begin root-session Database::needRoot(true, $_dbserver['dbserver']); while ($row = $result_stmt->fetch(\PDO::FETCH_ASSOC)) { @@ -416,6 +425,31 @@ class Mysqls extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt )); } + /** + * returns the total number of accessable databases + * + * @param int $customerid + * optional, admin-only, select dbs of a specific customer by id + * @param string $loginname + * optional, admin-only, select dbs of a specific customer by loginname + * + * @access admin, customer + * @throws \Exception + * @return string json-encoded array + */ + public function listingCount() + { + $customer_ids = $this->getAllowedCustomerIds('mysql'); + $result_stmt = Database::prepare(" + SELECT COUNT(*) as num_dbs FROM `" . TABLE_PANEL_DATABASES . "` + WHERE `customerid` IN (" . implode(", ", $customer_ids) . ") + "); + $result = Database::pexecute_first($result_stmt, null, true, true); + if ($result) { + return $this->response(200, "successfull", $result['num_dbs']); + } + } + /** * delete a mysql database by either id or dbname * diff --git a/lib/Froxlor/Api/Commands/PhpSettings.php b/lib/Froxlor/Api/Commands/PhpSettings.php index f0370252..bc3f5d3d 100644 --- a/lib/Froxlor/Api/Commands/PhpSettings.php +++ b/lib/Froxlor/Api/Commands/PhpSettings.php @@ -27,7 +27,15 @@ class PhpSettings extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour * * @param bool $with_subdomains * optional, also include subdomains to the list domains that use the config, default 0 (false) - * + * @param array $sql_search + * optional array with index = fieldname, and value = array with 'op' => operator (one of <, > or =), LIKE is used if left empty and 'value' => searchvalue + * @param int $sql_limit + * optional specify number of results to be returned + * @param int $sql_offset + * optional specify offset for resultset + * @param array $sql_orderby + * optional array with index = fieldname and value = ASC|DESC to order the resultset by one or more fields + * * @access admin * @throws \Exception * @return string json-encoded array count|list @@ -38,16 +46,15 @@ class PhpSettings extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour $this->logger()->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_NOTICE, "[API] list php-configs"); $with_subdomains = $this->getBoolParam('with_subdomains', true, false); - - $result = Database::query(" + $query_fields = array(); + $result_stmt = Database::prepare(" SELECT c.*, fd.description as fpmdesc FROM `" . TABLE_PANEL_PHPCONFIGS . "` c - LEFT JOIN `" . TABLE_PANEL_FPMDAEMONS . "` fd ON fd.id = c.fpmsettingid - ORDER BY c.description ASC - "); - + LEFT JOIN `" . TABLE_PANEL_FPMDAEMONS . "` fd ON fd.id = c.fpmsettingid" . $this->getSearchWhere($query_fields) . $this->getOrderBy() . $this->getLimit() + ); + Database::pexecute($result_stmt, $query_fields, true, true); $phpconfigs = array(); - while ($row = $result->fetch(\PDO::FETCH_ASSOC)) { + while ($row = $result_stmt->fetch(\PDO::FETCH_ASSOC)) { $query_params = array( 'id' => $row['id'] ); @@ -115,6 +122,28 @@ class PhpSettings extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour throw new \Exception("Not allowed to execute given command.", 403); } + /** + * returns the total number of accessable php-setting entries + * + * @access admin + * @throws \Exception + * @return string json-encoded array + */ + public function listingCount() + { + if ($this->isAdmin()) { + $result_stmt = Database::prepare(" + SELECT COUNT(c.*) as num_phps + FROM `" . TABLE_PANEL_PHPCONFIGS . "` c + "); + $result = Database::pexecute_first($result_stmt, null, true, true); + if ($result) { + return $this->response(200, "successfull", $result['num_phps']); + } + } + throw new \Exception("Not allowed to execute given command.", 403); + } + /** * return a php-setting entry by id * diff --git a/lib/Froxlor/Api/Commands/SubDomains.php b/lib/Froxlor/Api/Commands/SubDomains.php index 00847da9..85180bc4 100644 --- a/lib/Froxlor/Api/Commands/SubDomains.php +++ b/lib/Froxlor/Api/Commands/SubDomains.php @@ -684,6 +684,19 @@ class SubDomains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc /** * lists all subdomain entries * + * @param int $customerid + * optional, admin-only, select (sub)domains of a specific customer by id + * @param string $loginname + * optional, admin-only, select (sub)domains of a specific customer by loginname + * @param array $sql_search + * optional array with index = fieldname, and value = array with 'op' => operator (one of <, > or =), LIKE is used if left empty and 'value' => searchvalue + * @param int $sql_limit + * optional specify number of results to be returned + * @param int $sql_offset + * optional specify offset for resultset + * @param array $sql_orderby + * optional array with index = fieldname and value = ASC|DESC to order the resultset by one or more fields + * * @access admin, customer * @throws \Exception * @return string json-encoded array count|list @@ -725,27 +738,21 @@ class SubDomains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc $this->getUserDetail('customerid') => $this->getUserDetail('standardsubdomain') ); } - + $query_fields = array(); // prepare select statement $domains_stmt = Database::prepare(" SELECT `d`.`id`, `d`.`customerid`, `d`.`domain`, `d`.`documentroot`, `d`.`isbinddomain`, `d`.`isemaildomain`, `d`.`caneditdomain`, `d`.`iswildcarddomain`, `d`.`parentdomainid`, `d`.`letsencrypt`, `d`.`termination_date`, `ad`.`id` AS `aliasdomainid`, `ad`.`domain` AS `aliasdomain`, `da`.`id` AS `domainaliasid`, `da`.`domain` AS `domainalias` FROM `" . TABLE_PANEL_DOMAINS . "` `d` LEFT JOIN `" . TABLE_PANEL_DOMAINS . "` `ad` ON `d`.`aliasdomain`=`ad`.`id` LEFT JOIN `" . TABLE_PANEL_DOMAINS . "` `da` ON `da`.`aliasdomain`=`d`.`id` - WHERE `d`.`customerid`= :customerid - AND `d`.`email_only`='0' - AND `d`.`id` <> :standardsubdomain - "); + WHERE `d`.`customerid` IN (" . implode(', ', $customer_ids) . ") + AND `d`.`email_only` = '0' + AND `d`.`id` NOT IN (" . implode(', ', $customer_stdsubs) . ")" . $this->getSearchWhere($query_fields, true) . $this->getOrderBy() . $this->getLimit()); $result = array(); - foreach ($customer_ids as $customer_id) { - Database::pexecute($domains_stmt, array( - "customerid" => $customer_id, - "standardsubdomain" => $customer_stdsubs[$customer_id] - ), true, true); - while ($row = $domains_stmt->fetch(\PDO::FETCH_ASSOC)) { - $result[] = $row; - } + Database::pexecute($domains_stmt, $query_fields, true, true); + while ($row = $domains_stmt->fetch(\PDO::FETCH_ASSOC)) { + $result[] = $row; } return $this->response(200, "successfull", array( 'count' => count($result), @@ -753,6 +760,71 @@ class SubDomains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc )); } + /** + * returns the total number of accessable subdomain entries + * + * @param int $customerid + * optional, admin-only, select (sub)domains of a specific customer by id + * @param string $loginname + * optional, admin-only, select (sub)domains of a specific customer by loginname + * + * @access admin, customer + * @throws \Exception + * @return string json-encoded array + */ + public function listingCount() + { + if ($this->isAdmin()) { + // if we're an admin, list all databases of all the admins customers + // or optionally for one specific customer identified by id or loginname + $customerid = $this->getParam('customerid', true, 0); + $loginname = $this->getParam('loginname', true, ''); + + if (! empty($customerid) || ! empty($loginname)) { + $result = $this->apiCall('Customers.get', array( + 'id' => $customerid, + 'loginname' => $loginname + )); + $custom_list_result = array( + $result + ); + } else { + $_custom_list_result = $this->apiCall('Customers.listing'); + $custom_list_result = $_custom_list_result['list']; + } + $customer_ids = array(); + $customer_stdsubs = array(); + foreach ($custom_list_result as $customer) { + $customer_ids[] = $customer['customerid']; + $customer_stdsubs[$customer['customerid']] = $customer['standardsubdomain']; + } + } else { + if (Settings::IsInList('panel.customer_hide_options', 'domains')) { + throw new \Exception("You cannot access this resource", 405); + } + $customer_ids = array( + $this->getUserDetail('customerid') + ); + $customer_stdsubs = array( + $this->getUserDetail('customerid') => $this->getUserDetail('standardsubdomain') + ); + } + // prepare select statement + $domains_stmt = Database::prepare(" + SELECT COUNT(`d`.*) as num_subdom + FROM `" . TABLE_PANEL_DOMAINS . "` `d` + LEFT JOIN `" . TABLE_PANEL_DOMAINS . "` `ad` ON `d`.`aliasdomain`=`ad`.`id` + LEFT JOIN `" . TABLE_PANEL_DOMAINS . "` `da` ON `da`.`aliasdomain`=`d`.`id` + WHERE `d`.`customerid` IN (" . implode(', ', $customer_ids) . ") + AND `d`.`email_only` = '0' + AND `d`.`id` NOT IN (" . implode(', ', $customer_stdsubs) . ") + "); + $result = Database::pexecute_first($domains_stmt, null, true, true); + if ($result) { + return $this->response(200, "successfull", $result['num_subdom']); + } + } + /** * delete a subdomain by either id or domainname * diff --git a/lib/Froxlor/Api/Commands/Traffic.php b/lib/Froxlor/Api/Commands/Traffic.php index 83c758f9..368c81e2 100644 --- a/lib/Froxlor/Api/Commands/Traffic.php +++ b/lib/Froxlor/Api/Commands/Traffic.php @@ -116,6 +116,16 @@ class Traffic extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn )); } + /** + * You cannot count the traffic data list + * + * @throws \Exception + */ + public function listingCount() + { + throw new \Exception('You cannot count the traffic data list', 303); + } + /** * You cannot delete traffic data * diff --git a/lib/Froxlor/Api/ResourceEntity.php b/lib/Froxlor/Api/ResourceEntity.php index 1f3ff79f..fe3068da 100644 --- a/lib/Froxlor/Api/ResourceEntity.php +++ b/lib/Froxlor/Api/ResourceEntity.php @@ -21,6 +21,8 @@ interface ResourceEntity public function listing(); + public function listingCount(); + public function get(); public function add(); diff --git a/tests/Admins/AdminsTest.php b/tests/Admins/AdminsTest.php index e1fcb9f8..635f3574 100644 --- a/tests/Admins/AdminsTest.php +++ b/tests/Admins/AdminsTest.php @@ -156,6 +156,51 @@ class AdminsTest extends TestCase $json_result = Admins::getLocal($admin_userdata)->listing(); $result = json_decode($json_result, true)['data']; $this->assertEquals(2, $result['count']); + + $json_result = Admins::getLocal($admin_userdata)->listingCount(); + $result = json_decode($json_result, true)['data']; + $this->assertEquals(2, $result); + } + + public function testAdminAdminsListLimitOffsetOrderSearch() + { + global $admin_userdata; + + $json_result = Admins::getLocal($admin_userdata, [ + 'sql_orderby' => [ + 'loginname' => 'DESC' + ] + ])->listing(); + $result = json_decode($json_result, true)['data']; + $this->assertEquals(2, $result['count']); + $this->assertEquals('reseller', $result['list'][0]['loginname']); + + $json_result = Admins::getLocal($admin_userdata, [ + 'sql_limit' => 1 + ])->listing(); + $result = json_decode($json_result, true)['data']; + $this->assertEquals(1, $result['count']); + $this->assertEquals('admin', $result['list'][0]['loginname']); + + $json_result = Admins::getLocal($admin_userdata, [ + 'sql_limit' => 1, + 'sql_offset' => 1 + ])->listing(); + $result = json_decode($json_result, true)['data']; + $this->assertEquals(1, $result['count']); + $this->assertEquals('reseller', $result['list'][0]['loginname']); + + $json_result = Admins::getLocal($admin_userdata, [ + 'sql_search' => [ + 'loginname' => [ + 'value' => 'adm', + 'op' => null /* LIKE */ + ] + ] + ])->listing(); + $result = json_decode($json_result, true)['data']; + $this->assertEquals(1, $result['count']); + $this->assertEquals('admin', $result['list'][0]['loginname']); } public function testResellerAdminsGet() diff --git a/tests/Backup/CustomerBackupsTest.php b/tests/Backup/CustomerBackupsTest.php index 306c9f7e..a2a4aca1 100644 --- a/tests/Backup/CustomerBackupsTest.php +++ b/tests/Backup/CustomerBackupsTest.php @@ -154,6 +154,10 @@ class CustomerBackupsTest extends TestCase $this->assertEquals('1', $result['list'][0]['data']['backup_dbs']); $this->assertEquals('1', $result['list'][0]['data']['backup_mail']); $this->assertEquals('1', $result['list'][0]['data']['backup_web']); + + $json_result = CustomerBackups::getLocal($admin_userdata)->listingCount(); + $result = json_decode($json_result, true)['data']; + $this->assertEquals(1, $result); } /** diff --git a/tests/Certificates/CertificatesTest.php b/tests/Certificates/CertificatesTest.php index 3a35f7c3..cf33fbce 100644 --- a/tests/Certificates/CertificatesTest.php +++ b/tests/Certificates/CertificatesTest.php @@ -74,6 +74,10 @@ class CertificatesTest extends TestCase $json_result = Certificates::getLocal($admin_userdata)->listing(); $result = json_decode($json_result, true)['data']; $this->assertEquals(2, $result['count']); + + $json_result = Certificates::getLocal($admin_userdata)->listingCount(); + $result = json_decode($json_result, true)['data']; + $this->assertEquals(2, $result); } public function testResellerCertificatesList() @@ -89,6 +93,10 @@ class CertificatesTest extends TestCase $json_result = Certificates::getLocal($reseller_userdata)->listing(); $result = json_decode($json_result, true)['data']; $this->assertEquals(2, $result['count']); + + $json_result = Certificates::getLocal($reseller_userdata)->listingCount(); + $result = json_decode($json_result, true)['data']; + $this->assertEquals(2, $result); } public function testCustomerCertificatesList() @@ -103,6 +111,10 @@ class CertificatesTest extends TestCase $json_result = Certificates::getLocal($customer_userdata)->listing(); $result = json_decode($json_result, true)['data']; $this->assertEquals(2, $result['count']); + + $json_result = Certificates::getLocal($customer_userdata)->listingCount(); + $result = json_decode($json_result, true)['data']; + $this->assertEquals(2, $result); } public function testAdminCertificatesUpdate() diff --git a/tests/Cronjobs/CronjobsTest.php b/tests/Cronjobs/CronjobsTest.php index ac7012f8..633e537c 100644 --- a/tests/Cronjobs/CronjobsTest.php +++ b/tests/Cronjobs/CronjobsTest.php @@ -21,6 +21,10 @@ class CronjobsTest extends TestCase $result = json_decode($json_result, true)['data']; $this->assertTrue(isset($result['list'][0]['module'])); $this->assertTrue(isset($result['list'][0]['cronfile'])); + + $json_result = Cronjobs::getLocal($admin_userdata)->listingCount(); + $result = json_decode($json_result, true)['data']; + $this->assertEquals(6, $result); } public function testCustomerCronjobsListNotAllowed() diff --git a/tests/Customers/CustomersTest.php b/tests/Customers/CustomersTest.php index a321b009..26100f3e 100644 --- a/tests/Customers/CustomersTest.php +++ b/tests/Customers/CustomersTest.php @@ -110,6 +110,10 @@ class CustomersTest extends TestCase $json_result = Customers::getLocal($admin_userdata)->listing(); $result = json_decode($json_result, true)['data']; $this->assertEquals(1, $result['count']); + + $json_result = Customers::getLocal($admin_userdata)->listingCount(); + $result = json_decode($json_result, true)['data']; + $this->assertEquals(1, $result); } /** @@ -128,6 +132,10 @@ class CustomersTest extends TestCase $json_result = Customers::getLocal($reseller_userdata)->listing(); $result = json_decode($json_result, true)['data']; $this->assertEquals(0, $result['count']); + + $json_result = Customers::getLocal($reseller_userdata)->listingCount(); + $result = json_decode($json_result, true)['data']; + $this->assertEquals(0, $result); } /** @@ -145,8 +153,11 @@ class CustomersTest extends TestCase $this->expectExceptionCode(403); $this->expectExceptionMessage("Not allowed to execute given command."); - $json_result = Customers::getLocal($customer_userdata)->listing(); + + $this->expectExceptionCode(403); + $this->expectExceptionMessage("Not allowed to execute given command."); + $json_result = Customers::getLocal($customer_userdata)->listingCount(); } /** diff --git a/tests/Customers/HostingPlansTest.php b/tests/Customers/HostingPlansTest.php index 463fa64b..61955fab 100644 --- a/tests/Customers/HostingPlansTest.php +++ b/tests/Customers/HostingPlansTest.php @@ -83,6 +83,10 @@ class HostingPlansTest extends TestCase $json_result = HostingPlans::getLocal($admin_userdata)->listing(); $result = json_decode($json_result, true)['data']; $this->assertEquals(1, $result['count']); + + $json_result = HostingPlans::getLocal($admin_userdata)->listingCount(); + $result = json_decode($json_result, true)['data']; + $this->assertEquals(1, $result); } /** @@ -101,6 +105,10 @@ class HostingPlansTest extends TestCase $json_result = HostingPlans::getLocal($reseller_userdata)->listing(); $result = json_decode($json_result, true)['data']; $this->assertEquals(0, $result['count']); + + $json_result = HostingPlans::getLocal($reseller_userdata)->listingCount(); + $result = json_decode($json_result, true)['data']; + $this->assertEquals(0, $result); } /** @@ -118,8 +126,11 @@ class HostingPlansTest extends TestCase $this->expectExceptionCode(403); $this->expectExceptionMessage("Not allowed to execute given command."); - $json_result = HostingPlans::getLocal($customer_userdata)->listing(); + + $this->expectExceptionCode(403); + $this->expectExceptionMessage("Not allowed to execute given command."); + $json_result = HostingPlans::getLocal($customer_userdata)->listingCount(); } public function testCustomerPlanAdd() diff --git a/tests/DomainZones/DomainZonesTest.php b/tests/DomainZones/DomainZonesTest.php index 2b50a6c8..155b217c 100644 --- a/tests/DomainZones/DomainZonesTest.php +++ b/tests/DomainZones/DomainZonesTest.php @@ -116,6 +116,10 @@ class DomainZonesTest extends TestCase $result = json_decode($json_result, true)['data']; $this->assertEquals(1, $result['count']); $this->assertEquals('www2', $result['list'][0]['record']); + + $json_result = DomainZones::getLocal($admin_userdata, $data)->listingCount(); + $result = json_decode($json_result, true)['data']; + $this->assertEquals(1, $result); } /** diff --git a/tests/Domains/DomainsTest.php b/tests/Domains/DomainsTest.php index 4efe7798..f60257b5 100644 --- a/tests/Domains/DomainsTest.php +++ b/tests/Domains/DomainsTest.php @@ -50,6 +50,10 @@ class DomainsTest extends TestCase $result = json_decode($json_result, true)['data']; $this->assertEquals(1, $result['count']); $this->assertEquals('test.local', $result['list'][0]['domain']); + + $json_result = Domains::getLocal($admin_userdata)->listingCount(); + $result = json_decode($json_result, true)['data']; + $this->assertEquals(1, $result); } /** @@ -68,6 +72,10 @@ class DomainsTest extends TestCase $json_result = Domains::getLocal($reseller_userdata)->listing(); $result = json_decode($json_result, true)['data']; $this->assertEquals(0, $result['count']); + + $json_result = Domains::getLocal($reseller_userdata)->listingCount(); + $result = json_decode($json_result, true)['data']; + $this->assertEquals(0, $result); } public function testResellerDomainsAddWithCanEditPhpSettingsDefaultIp() @@ -234,4 +242,22 @@ class DomainsTest extends TestCase 'loginname' => 'test3' ))->delete(); } + + public function testCustomerDomainsList() + { + global $admin_userdata; + // get customer + $json_result = Customers::getLocal($admin_userdata, array( + 'id' => 1 + ))->get(); + $customer_userdata = json_decode($json_result, true)['data']; + + $this->expectExceptionCode(403); + $this->expectExceptionMessage("Not allowed to execute given command."); + $json_result = Domains::getLocal($customer_userdata)->listing(); + + $this->expectExceptionCode(403); + $this->expectExceptionMessage("Not allowed to execute given command."); + $json_result = Domains::getLocal($customer_userdata)->listingCount(); + } } diff --git a/tests/Emails/EmailsTest.php b/tests/Emails/EmailsTest.php index a7b64306..3e254bbb 100644 --- a/tests/Emails/EmailsTest.php +++ b/tests/Emails/EmailsTest.php @@ -362,6 +362,10 @@ class MailsTest extends TestCase $this->assertEquals(2, $result['count']); $this->assertEquals("info@test2.local", $result['list'][0]['email']); $this->assertEquals("@test2.local", $result['list'][1]['email']); + + $json_result = Emails::getLocal($customer_userdata)->listingCount(); + $result = json_decode($json_result, true)['data']; + $this->assertEquals(2, $result); } public function testCustomerEmailAccountsAdd() diff --git a/tests/Extras/DirOptionsTest.php b/tests/Extras/DirOptionsTest.php index ebb59cab..ec2a3f0b 100644 --- a/tests/Extras/DirOptionsTest.php +++ b/tests/Extras/DirOptionsTest.php @@ -158,6 +158,10 @@ class DirOptionsTest extends TestCase $result = json_decode($json_result, true)['data']; $this->assertEquals(1, $result['count']); $this->assertEquals($customer_userdata['documentroot'] . 'test/', $result['list'][0]['path']); + + $json_result = DirOptions::getLocal($admin_userdata)->listingCount(); + $result = json_decode($json_result, true)['data']; + $this->assertEquals(1, $result); } /** diff --git a/tests/Extras/DirProtectionsTest.php b/tests/Extras/DirProtectionsTest.php index 053d3f38..4bcd5e4c 100644 --- a/tests/Extras/DirProtectionsTest.php +++ b/tests/Extras/DirProtectionsTest.php @@ -175,6 +175,10 @@ class DirProtectionsTest extends TestCase $this->assertEquals(2, $result['count']); $this->assertEquals('test1', $result['list'][0]['username']); $this->assertEquals('testing', $result['list'][1]['username']); + + $json_result = DirProtections::getLocal($customer_userdata)->listingCount(); + $result = json_decode($json_result, true)['data']; + $this->assertEquals(2, $result); } /** diff --git a/tests/Ftps/FtpsTest.php b/tests/Ftps/FtpsTest.php index 75d739d5..1ed6788d 100644 --- a/tests/Ftps/FtpsTest.php +++ b/tests/Ftps/FtpsTest.php @@ -88,6 +88,10 @@ class FtpsTest extends TestCase $json_result = Ftps::getLocal($admin_userdata)->listing(); $result = json_decode($json_result, true)['data']; $this->assertEquals(2, $result['count']); + + $json_result = Ftps::getLocal($admin_userdata)->listingCount(); + $result = json_decode($json_result, true)['data']; + $this->assertEquals(2, $result); } public function testAdminFtpsListSpecificCustomer() @@ -115,6 +119,10 @@ class FtpsTest extends TestCase $result = json_decode($json_result, true)['data']; $this->assertEquals(1, $result['count']); $this->assertEquals('test1', $result['list'][0]['username']); + + $json_result = Ftps::getLocal($reseller_userdata)->listingCount(); + $result = json_decode($json_result, true)['data']; + $this->assertEquals(1, $result); } public function testCustomerFtpsList() @@ -129,6 +137,10 @@ class FtpsTest extends TestCase $result = json_decode($json_result, true)['data']; $this->assertEquals(1, $result['count']); $this->assertEquals('test1', $result['list'][0]['username']); + + $json_result = Ftps::getLocal($customer_userdata)->listingCount(); + $result = json_decode($json_result, true)['data']; + $this->assertEquals(1, $result); } public function testCustomerFtpsAdd() diff --git a/tests/IpsAndPorts/IpsAndPortsTest.php b/tests/IpsAndPorts/IpsAndPortsTest.php index e121a525..36b1a76f 100644 --- a/tests/IpsAndPorts/IpsAndPortsTest.php +++ b/tests/IpsAndPorts/IpsAndPortsTest.php @@ -21,6 +21,10 @@ class IpsAndPortsTest extends TestCase $result = json_decode($json_result, true)['data']; $this->assertEquals(2, $result['count']); $this->assertEquals('82.149.225.46', $result['list'][0]['ip']); + + $json_result = IpsAndPorts::getLocal($admin_userdata)->listingCount(); + $result = json_decode($json_result, true)['data']; + $this->assertEquals(2, $result); } public function testResellerIpsAndPortsListHasNone() @@ -107,6 +111,10 @@ class IpsAndPortsTest extends TestCase $result = json_decode($json_result, true)['data']; $this->assertEquals(1, $result['count']); $this->assertEquals('82.149.225.47', $result['list'][0]['ip']); + + $json_result = IpsAndPorts::getLocal($reseller_userdata)->listingCount(); + $result = json_decode($json_result, true)['data']; + $this->assertEquals(1, $result); } /** diff --git a/tests/Mysqls/MysqlsTest.php b/tests/Mysqls/MysqlsTest.php index 45947c68..817d4b23 100644 --- a/tests/Mysqls/MysqlsTest.php +++ b/tests/Mysqls/MysqlsTest.php @@ -139,6 +139,10 @@ class MysqlsTest extends TestCase $result = json_decode($json_result, true)['data']; $this->assertEquals(1, $result['count']); $this->assertEquals('test1sql1', $result['list'][0]['databasename']); + + $json_result = Mysqls::getLocal($customer_userdata)->listingCount(); + $result = json_decode($json_result, true)['data']; + $this->assertEquals(1, $result); } /** diff --git a/tests/PhpAndFpm/FpmDaemonsTest.php b/tests/PhpAndFpm/FpmDaemonsTest.php index 1b024b34..82d187ab 100644 --- a/tests/PhpAndFpm/FpmDaemonsTest.php +++ b/tests/PhpAndFpm/FpmDaemonsTest.php @@ -141,6 +141,10 @@ class FpmDaemonsTest extends TestCase $this->assertEquals(2, $result['count']); $this->assertEquals('System default', $result['list'][0]['description']); $this->assertEquals('test2 fpm edit', $result['list'][1]['description']); + + $json_result = FpmDaemons::getLocal($admin_userdata)->listingCount(); + $result = json_decode($json_result, true)['data']; + $this->assertEquals(2, $result); } public function testAdminFpmDaemonsGetNotFound() @@ -190,6 +194,10 @@ class FpmDaemonsTest extends TestCase $this->expectExceptionCode(403); $this->expectExceptionMessage("Not allowed to execute given command."); FpmDaemons::getLocal($customer_userdata)->listing(); + + $this->expectExceptionCode(403); + $this->expectExceptionMessage("Not allowed to execute given command."); + FpmDaemons::getLocal($customer_userdata)->listingCount(); } public function testCustomerFpmDaemonsUpdate() diff --git a/tests/PhpAndFpm/PhpSettingsTest.php b/tests/PhpAndFpm/PhpSettingsTest.php index 3e2f0278..29b61fe0 100644 --- a/tests/PhpAndFpm/PhpSettingsTest.php +++ b/tests/PhpAndFpm/PhpSettingsTest.php @@ -23,6 +23,10 @@ class PhpSettingsText extends TestCase $result = json_decode($json_result, true)['data']; $this->assertEquals("Default Config", $result['list'][0]['description']); $this->assertEquals("/usr/bin/php-cgi", $result['list'][0]['binary']); + + $json_result = PhpSettings::getLocal($admin_userdata)->listingCount(); + $result = json_decode($json_result, true)['data']; + $this->assertEquals(2, $result); } public function testCustomerPhpSettingsListNotAllowed() @@ -36,6 +40,10 @@ class PhpSettingsText extends TestCase $this->expectExceptionCode(403); $this->expectExceptionMessage("Not allowed to execute given command."); PhpSettings::getLocal($customer_userdata)->listing(); + + $this->expectExceptionCode(403); + $this->expectExceptionMessage("Not allowed to execute given command."); + PhpSettings::getLocal($customer_userdata)->listingCount(); } public function testAdminPhpSettingsAdd() diff --git a/tests/SubDomains/SubDomainsTest.php b/tests/SubDomains/SubDomainsTest.php index 4c45765c..7a20254a 100644 --- a/tests/SubDomains/SubDomainsTest.php +++ b/tests/SubDomains/SubDomainsTest.php @@ -201,6 +201,10 @@ class SubDomainsTest extends TestCase $json_result = SubDomains::getLocal($customer_userdata)->listing(); $result = json_decode($json_result, true)['data']; $this->assertEquals(3, $result['count']); + + $json_result = SubDomains::getLocal($customer_userdata)->listingCount(); + $result = json_decode($json_result, true)['data']; + $this->assertEquals(3, $result); } public function testResellerSubDomainsList() @@ -215,6 +219,10 @@ class SubDomainsTest extends TestCase $json_result = SubDomains::getLocal($reseller_userdata)->listing(); $result = json_decode($json_result, true)['data']; $this->assertEquals(3, $result['count']); + + $json_result = SubDomains::getLocal($reseller_userdata)->listingCount(); + $result = json_decode($json_result, true)['data']; + $this->assertEquals(3, $result); } public function testAdminSubDomainsListWithCustomer() @@ -225,6 +233,12 @@ class SubDomainsTest extends TestCase ])->listing(); $result = json_decode($json_result, true)['data']; $this->assertEquals(3, $result['count']); + + $json_result = SubDomains::getLocal($admin_userdata, [ + 'loginname' => 'test1' + ])->listingCount(); + $result = json_decode($json_result, true)['data']; + $this->assertEquals(3, $result); } /** diff --git a/tests/Traffic/TrafficTest.php b/tests/Traffic/TrafficTest.php index 3383dd61..9dfafedf 100644 --- a/tests/Traffic/TrafficTest.php +++ b/tests/Traffic/TrafficTest.php @@ -79,6 +79,10 @@ class TrafficTest extends TestCase $this->assertEquals(1, $result['count']); $http = 2 * (5 * 1024 * 1024 * 1024); // 2x 5 GB $this->assertEquals($http, $result['list'][0]['http']); + + $this->expectExceptionCode(303); + $this->expectExceptionMessage("You cannot count the traffic data list"); + Traffic::getLocal($admin_userdata)->listingCount(); } public function testAdminTrafficListSpecificDate() @@ -120,6 +124,10 @@ class TrafficTest extends TestCase $this->assertEquals(1, $result['count']); $mail = 250 * 1024 * 1024; // 250 MB $this->assertEquals($mail, $result['list'][0]['mail']); + + $this->expectExceptionCode(303); + $this->expectExceptionMessage("You cannot count the traffic data list"); + Traffic::getLocal($admin_userdata)->listingCount(); } public function testAdminTrafficAdd()