mirror of
https://github.com/loewexy/pdnsmanager.git
synced 2025-01-15 18:52:20 +01:00
Added GET /domains functionality
This commit is contained in:
parent
54bf2a1099
commit
5f93a13412
7 changed files with 302 additions and 6 deletions
|
@ -10,7 +10,8 @@
|
|||
"Operations\\": "operations/",
|
||||
"Plugins\\": "plugins/",
|
||||
"Middlewares\\": "middlewares/",
|
||||
"Exceptions\\": "exceptions/"
|
||||
"Exceptions\\": "exceptions/",
|
||||
"Utils\\": "utils/"
|
||||
}
|
||||
}
|
||||
}
|
42
backend/controllers/Domains.php
Normal file
42
backend/controllers/Domains.php
Normal file
|
@ -0,0 +1,42 @@
|
|||
<?php
|
||||
|
||||
namespace Controllers;
|
||||
|
||||
require '../vendor/autoload.php';
|
||||
|
||||
use \Slim\Http\Request as Request;
|
||||
use \Slim\Http\Response as Response;
|
||||
|
||||
class Domains
|
||||
{
|
||||
/** @var \Monolog\Logger */
|
||||
private $logger;
|
||||
|
||||
/** @var \Slim\Container */
|
||||
private $container;
|
||||
|
||||
public function __construct(\Slim\Container $c)
|
||||
{
|
||||
$this->logger = $c->logger;
|
||||
$this->container = $c;
|
||||
}
|
||||
|
||||
public function getList(Request $req, Response $res, array $args)
|
||||
{
|
||||
$domains = new \Operations\Domains($this->container);
|
||||
|
||||
$paging = new \Utils\PagingInfo($req->getQueryParam('page'), $req->getQueryParam('pagesize'));
|
||||
$query = $req->getQueryParam('query');
|
||||
$sort = $req->getQueryParam('sort');
|
||||
$type = $req->getQueryParam('type');
|
||||
|
||||
$userId = $req->getAttribute('userId');
|
||||
|
||||
$results = $domains->getDomains($paging, $userId, $query, $sort, $type);
|
||||
|
||||
return $res->withJson([
|
||||
'paging' => $paging->toArray(),
|
||||
'results' => $results
|
||||
], 200);
|
||||
}
|
||||
}
|
46
backend/operations/AccessControl.php
Normal file
46
backend/operations/AccessControl.php
Normal file
|
@ -0,0 +1,46 @@
|
|||
<?php
|
||||
|
||||
namespace Operations;
|
||||
|
||||
require '../vendor/autoload.php';
|
||||
|
||||
/**
|
||||
* This class provides access control for the application.
|
||||
*/
|
||||
class AccessControl
|
||||
{
|
||||
/** @var \Monolog\Logger */
|
||||
private $logger;
|
||||
|
||||
/** @var \PDO */
|
||||
private $db;
|
||||
|
||||
public function __construct(\Slim\Container $c)
|
||||
{
|
||||
$this->logger = $c->logger;
|
||||
$this->db = $c->db;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if the given user has admin privileges.
|
||||
*
|
||||
* @param $userId User id of the user
|
||||
*
|
||||
* @return bool true if admin, false otherwise
|
||||
*/
|
||||
public function isAdmin(int $userId) : bool
|
||||
{
|
||||
$query = $this->db->prepare('SELECT type FROM users WHERE id=:id');
|
||||
$query->bindValue(':id', $userId, \PDO::PARAM_STR);
|
||||
$query->execute();
|
||||
|
||||
$record = $query->fetch();
|
||||
|
||||
if ($record === false) {
|
||||
$this->logger->error('Queried record for non existing user id, this should not happen.', ['userId' => $userId]);
|
||||
return false;
|
||||
}
|
||||
|
||||
return $record['type'] == 'admin';
|
||||
}
|
||||
}
|
107
backend/operations/Domains.php
Normal file
107
backend/operations/Domains.php
Normal file
|
@ -0,0 +1,107 @@
|
|||
<?php
|
||||
|
||||
namespace Operations;
|
||||
|
||||
require '../vendor/autoload.php';
|
||||
|
||||
/**
|
||||
* This class provides functions for retrieving and modifying domains.
|
||||
*/
|
||||
class Domains
|
||||
{
|
||||
/** @var \Monolog\Logger */
|
||||
private $logger;
|
||||
|
||||
/** @var \PDO */
|
||||
private $db;
|
||||
|
||||
/** @var \Slim\Container */
|
||||
private $c;
|
||||
|
||||
public function __construct(\Slim\Container $c)
|
||||
{
|
||||
$this->logger = $c->logger;
|
||||
$this->db = $c->db;
|
||||
$this->c = $c;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a list of domains according to filter criteria
|
||||
*
|
||||
* @param $pi PageInfo object, which is also updated with total page number
|
||||
* @param $userId Id of the user for which the table should be retrieved
|
||||
* @param $query Search query to search in the domain name, null for no filter
|
||||
* @param $sorting Sort string in format 'field-asc,field2-desc', null for default
|
||||
* @param $type Type to filter for, null for no filter
|
||||
*/
|
||||
public function getDomains(\Utils\PagingInfo &$pi, int $userId, ? string $query, ? string $sorting, ? string $type) : array
|
||||
{
|
||||
$ac = new \Operations\AccessControl($this->c);
|
||||
$userIsAdmin = $ac->isAdmin($userId);
|
||||
|
||||
$queryStr = $query === null ? '%' : '%' . $query . '%';
|
||||
|
||||
//Count elements
|
||||
if ($pi->pageSize === null) {
|
||||
$pi->totalPages = 1;
|
||||
} else {
|
||||
$query = $this->db->prepare('
|
||||
SELECT COUNT(*) AS total
|
||||
FROM domains D
|
||||
LEFT OUTER JOIN permissions P ON D.id = P.domain_id
|
||||
WHERE (P.user_id=:userId OR :userIsAdmin) AND
|
||||
(D.name LIKE :nameQuery) AND
|
||||
(D.type = :domainType OR :noTypeFilter)
|
||||
');
|
||||
|
||||
$query->bindValue(':userId', $userId, \PDO::PARAM_INT);
|
||||
$query->bindValue(':userIsAdmin', intval($userIsAdmin), \PDO::PARAM_INT);
|
||||
$query->bindValue(':nameQuery', $queryStr, \PDO::PARAM_STR);
|
||||
$query->bindValue(':domainType', (string)$type, \PDO::PARAM_STR);
|
||||
$query->bindValue(':noTypeFilter', intval($type === null), \PDO::PARAM_INT);
|
||||
|
||||
$query->execute();
|
||||
$record = $query->fetch();
|
||||
|
||||
$pi->totalPages = ceil($record['total'] / $pi->pageSize);
|
||||
}
|
||||
|
||||
//Query and return result
|
||||
$ordStr = \Services\Database::makeSortingString($sorting, [
|
||||
'id' => 'D.id',
|
||||
'name' => 'D.name',
|
||||
'type' => 'D.type',
|
||||
'records' => 'records'
|
||||
]);
|
||||
$pageStr = \Services\Database::makePagingString($pi);
|
||||
|
||||
$query = $this->db->prepare('
|
||||
SELECT D.id,D.name,D.type,D.master,count(R.domain_id) AS records
|
||||
FROM domains D
|
||||
LEFT OUTER JOIN records R ON D.id = R.domain_id
|
||||
LEFT OUTER JOIN permissions P ON D.id = P.domain_id
|
||||
WHERE (P.user_id=:userId OR :userIsAdmin)
|
||||
GROUP BY D.id
|
||||
HAVING
|
||||
(D.name LIKE :nameQuery) AND
|
||||
(D.type=:domainType OR :noTypeFilter)'
|
||||
. $ordStr . $pageStr);
|
||||
|
||||
$query->bindValue(':userId', $userId, \PDO::PARAM_INT);
|
||||
$query->bindValue(':userIsAdmin', intval($userIsAdmin), \PDO::PARAM_INT);
|
||||
$query->bindValue(':nameQuery', $queryStr, \PDO::PARAM_STR);
|
||||
$query->bindValue(':domainType', (string)$type, \PDO::PARAM_STR);
|
||||
$query->bindValue(':noTypeFilter', intval($type === null), \PDO::PARAM_INT);
|
||||
|
||||
$query->execute();
|
||||
|
||||
$data = $query->fetchAll();
|
||||
|
||||
return array_map(function ($item) {
|
||||
if ($item['type'] != 'SLAVE') {
|
||||
unset($item['master']);
|
||||
}
|
||||
return $item;
|
||||
}, $data);
|
||||
}
|
||||
}
|
|
@ -26,6 +26,8 @@ $app->group('/v1', function () {
|
|||
|
||||
$this->group('', function () {
|
||||
$this->delete('/sessions/{sessionId}', '\Controllers\Sessions:delete');
|
||||
|
||||
$this->get('/domains', '\Controllers\Domains:getList');
|
||||
})->add('\Middlewares\Authentication');
|
||||
|
||||
});
|
||||
|
|
|
@ -12,10 +12,10 @@ class Database
|
|||
|
||||
try {
|
||||
$pdo = new \PDO(
|
||||
'mysql:host=' . $config['host'] . ';port=' . $config['port'] . ';dbname=' . $config['dbname'],
|
||||
$config['user'],
|
||||
$config['password']
|
||||
);
|
||||
'mysql:host=' . $config['host'] . ';port=' . $config['port'] . ';dbname=' . $config['dbname'],
|
||||
$config['user'],
|
||||
$config['password']
|
||||
);
|
||||
} catch (\PDOException $e) {
|
||||
$c->logger->critical("SQL Connect Error: " . $e->getMessage());
|
||||
$c->logger->critical("DB Config was", $config);
|
||||
|
@ -31,7 +31,68 @@ class Database
|
|||
}
|
||||
|
||||
$c->logger->debug("Database setup successfull");
|
||||
|
||||
|
||||
return $pdo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes a SQL LIMIT string from paging information
|
||||
*
|
||||
* @param $pi PagingInfo object to use
|
||||
*
|
||||
* @return string SQL string to use
|
||||
*/
|
||||
public static function makePagingString(\Utils\PagingInfo $pi) : string
|
||||
{
|
||||
if ($pi->pageSize === null) {
|
||||
return '';
|
||||
}
|
||||
|
||||
if ($pi->page === null) {
|
||||
$pi->page = 1;
|
||||
}
|
||||
|
||||
$offset = ($pi->page - 1) * $pi->pageSize;
|
||||
|
||||
return ' LIMIT ' . intval($pi->pageSize) . ' OFFSET ' . intval($offset);
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes a SQL ORDER BY string from order information.
|
||||
*
|
||||
* This is done from a string with format 'field-asc,field2-desc'
|
||||
* where fields are mapped to columns in param $colMap. This also
|
||||
* should prevent SQL injections.
|
||||
*
|
||||
* @param $sort Sort string
|
||||
* @param $colMap Map which assigns to each field name a column to use
|
||||
*
|
||||
* @return string SQL string to use
|
||||
*/
|
||||
public static function makeSortingString(? string $sort, array $colMap)
|
||||
{
|
||||
if ($sort === null) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$orderStrings = [];
|
||||
|
||||
foreach (explode(',', $sort) as $value) {
|
||||
$parts = explode('-', $value);
|
||||
|
||||
if (array_key_exists($parts[0], $colMap) && count($parts) == 2) { // is valid known field
|
||||
if ($parts[1] == 'asc') {
|
||||
$orderStrings[] = $colMap[$parts[0]] . ' ASC';
|
||||
} else if ($parts[1] == 'desc') {
|
||||
$orderStrings[] = $colMap[$parts[0]] . ' DESC';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (count($orderStrings) == 0) { // none was valid
|
||||
return '';
|
||||
}
|
||||
|
||||
return ' ORDER BY ' . implode(', ', $orderStrings);
|
||||
}
|
||||
}
|
||||
|
|
37
backend/utils/PagingInfo.php
Normal file
37
backend/utils/PagingInfo.php
Normal file
|
@ -0,0 +1,37 @@
|
|||
<?php
|
||||
|
||||
namespace Utils;
|
||||
|
||||
require '../vendor/autoload.php';
|
||||
|
||||
class PagingInfo
|
||||
{
|
||||
/** @var int */
|
||||
public $page;
|
||||
|
||||
/** @var int */
|
||||
public $pageSize;
|
||||
|
||||
/** @var int */
|
||||
public $totalPages;
|
||||
|
||||
public function __construct(? int $page, ? int $pageSize, int $totalPages = null)
|
||||
{
|
||||
$this->page = $page === null ? 1 : $page;
|
||||
$this->pageSize = $pageSize;
|
||||
$this->totalPages = $totalPages;
|
||||
}
|
||||
|
||||
public function toArray()
|
||||
{
|
||||
$val = [
|
||||
'page' => $this->page,
|
||||
'total' => $this->totalPages,
|
||||
'pagesize' => $this->pageSize
|
||||
];
|
||||
|
||||
return array_filter($val, function ($var) {
|
||||
return !is_null($var);
|
||||
});;
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue