Compare commits

..

No commits in common. "0a67c168628698c4121fcec11872c3ec8534ecf6" and "9b2c7f34953f4f2a13c23bcb8cadbc5cfb113808" have entirely different histories.

12 changed files with 106 additions and 578 deletions

1
.gitignore vendored
View File

@ -5,4 +5,3 @@
/swagger-ui/
/config.json.local
/bindAPI.log

View File

@ -92,7 +92,7 @@ Here I will install it under /usr/local/bin, in the example with the standalone
`wget https://getcomposer.org/installer`
`php installer --install-dir=/usr/local/bin --filename=composer`
`php composer-setup.php --install-dir=/usr/local/bin --filename=composer`
Now we can change into our new user, remind to give him shell access in the panel.
@ -296,10 +296,10 @@ GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, INDEX, DROP, ALTER, CREATE TEMPORA
There is no need to run FLUSH PRIVILEGES when using GRANT!
```
So, now it offers us the SQL statements to create a new user and database and set permissions. If were on plain debian,
we just can copy and paste (the password is random) this as root into mysql.
So, now it offers us the SQL statements to create a new user and database and set permissions.
If were on plain debian, we just can copy and paste (the password is random) this as root into mysql.
If we're using the panel, lets create a database and write down the credentials and update config.json.
If we're using hte panel, lets create a database and write down the credentials and update config.json.
And another call to the console:
@ -420,7 +420,7 @@ We create a new key:
```
$ ./bin/console apikeys:create
API key 1 has been generated. Store it in a save place, it cannot be recovered.
6213acb116613.[truncated]
6213acb116613.[truncated]]
```
And add it to our list of nameservers:

View File

@ -1,7 +1,6 @@
#!/usr/local/bin/php
#!/usr/bin/keyhelp-php81
<?php declare(strict_types=1);
namespace App\Controller;
// #!/usr/bin/keyhelp-php81
// & ~E_DEPRECATED is needed because of a bug in PhpStorm
use DI\DependencyException;

View File

@ -70,7 +70,7 @@
}
},
"/dyndns/{hostname}": {
"post": {
"get": {
"tags": [
"DNS"
],

View File

@ -384,7 +384,6 @@ class BindAPI
return true;
}
/**
* @param String $domainName
* @param \App\Entity\Panel $panel
@ -471,7 +470,6 @@ class BindAPI
exit(1);
}
if ($create['header'] != 201) {
print_r(value: $create);
die("make error handling");
} else {
echo COLOR_GREEN . 'OK' . COLOR_DEFAULT;
@ -1013,7 +1011,7 @@ class BindAPI
}
if (!empty($domains)) {
$table = new ConsoleTable();
$table->setHeaders(content: ['ID', 'Name', 'Panel', 'Type']);
$table->setHeaders(content: ['ID', 'Name', 'Panel']);
/** @var Domain $domain */
foreach ($domains as $domain) {
$row = [];
@ -1021,7 +1019,6 @@ class BindAPI
$row[] = $domain->getId();
$row[] = $domain->getName();
$row[] = $domain->getPanel();
$row[] = $this->domainController->isMasterZone(domain: $domain) ? 'MASTER' : 'SLAVE';
} catch (DependencyException|NotFoundException $e) {
echo $e->getMessage();
}
@ -1108,14 +1105,14 @@ class BindAPI
if (empty($name) && empty($panel)) {
echo 'No name or panel given, just recreate the config file' . PHP_EOL;
$this->domainController->updateSlaveZones();
$this->domainController->createSlaveZoneFile(domain: $domain);
exit(1);
}
$newDomain = new Domain(name: $name, panel: $panelName, id: $domain->getId());
if ($this->domainRepository->update(domain: $newDomain) !== false) {
echo 'Domain server has been updated' . PHP_EOL;
$this->domainController->updateSlaveZones();
$this->domainController->createSlaveZoneFile(domain: $domain);
} else {
echo 'Error while updating domain server.' . PHP_EOL;
}

View File

@ -19,7 +19,6 @@ class DatabaseConnection
const TABLE_NAMESERVERS = self::TABLE_PREFIX . "nameservers";
const TABLE_PANELS = self::TABLE_PREFIX . "panels";
const TABLE_APIKEYS = self::TABLE_PREFIX . "apikeys";
const TABLE_DYNDNS = self::TABLE_PREFIX . "dyndns";
public function __construct(private array $config)
{
@ -84,19 +83,6 @@ class DatabaseConnection
$statement = $this->dbConnection->prepare(query: $sql);
$statement->execute();
$sql = "
CREATE TABLE `dyndns` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` VARCHAR(255) NOT NULL,
`a` VARBINARY(255) NOT NULL,
`aaaa` VARBINARY(255) NOT NULL,
`last_update` TIMESTAMP NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci";
$statement = $this->dbConnection->prepare(query: $sql);
$statement->execute();
echo 'Tables have been created.' . PHP_EOL;
}
exit(1);

View File

@ -67,30 +67,6 @@ class DomainController
}
function updateSlaveZones()
{
if ($this->config['verbose']) {
echo 'Delete all slave zones';
}
$zones = glob(pattern: $this->localZonesDir . '*');
foreach ($zones as $zone) {
unlink(filename: $zone);
}
$domains = $this->domainRepository->findAll();
foreach ($domains as $domain) {
if ($this->config['verbose']) {
echo 'Create zone: ' . $domain->getName() . PHP_EOL;
}
$this->createSlaveZoneFile(domain: $domain);
}
$this->createIncludeFile();
}
function deleteOnNameservers(Domain $domain)
{
if ($this->config['debug']) {
@ -226,28 +202,25 @@ class DomainController
*/
public function createSlaveZoneFile(Domain $domain): void
{
$domainName = $domain->getName();
if ($this->config['debug']) {
$domainName = $domain->getName();
$this->log->debug(message: "createZoneFile($domainName)");
}
// check if we're a master zone
if ($this->isMasterZone(domain: $domain)) {
echo 'We are zone master for ' . $domainName . PHP_EOL;
echo 'We are zone master for ' . $domain->getName() . PHP_EOL;
exit(1);
}
if ($zonefile = fopen(filename: $this->localZonesDir . $domainName, mode: 'w')) {
if ($zonefile = fopen(filename: $this->localZonesDir . $domain->getName(), mode: 'w')) {
$panelName = $domain->getPanel();
if (!$panel = $this->panelRepository->findByName(name: $panelName)) {
echo "Error: Panel $panelName doesn't exist." . PHP_EOL;
die();
}
$panel = $this->panelRepository->findByName(name: $panelName);
$a = $panel->getA();
$aaaa = $panel->getAaaa();
fputs(stream: $zonefile, data: 'zone "' . $domainName . '"' . ' IN {' . PHP_EOL);
fputs(stream: $zonefile, data: 'zone "' . $domain->getName() . '"' . ' IN {' . PHP_EOL);
fputs(stream: $zonefile, data: "\ttype slave;" . PHP_EOL);
fputs(stream: $zonefile, data: "\tfile \"" . $this->zoneCachePath . $domainName . '.db";' . PHP_EOL);
fputs(stream: $zonefile, data: "\tfile \"" . $this->zoneCachePath . $domain->getName() . '.db";' . PHP_EOL);
fputs(stream: $zonefile, data: "\tmasters {" . PHP_EOL);
if (!empty($a)) {
fputs(stream: $zonefile, data: "\t\t" . $a . ';' . PHP_EOL);
@ -258,10 +231,10 @@ class DomainController
fputs(stream: $zonefile, data: "\t};" . PHP_EOL);
fputs(stream: $zonefile, data: "};" . PHP_EOL);
}
$this->createIncludeFile();
}
public function isMasterZone(Domain $domain): bool
private function isMasterZone(Domain $domain): bool
{
if (file_exists(filename: '/etc/bind/keyhelp_domains/' . $domain->getName())) {
return true;

View File

@ -5,10 +5,8 @@ namespace App\Controller;
error_reporting(error_level: E_ALL);
use App\Entity\Domain;
use App\Entity\DynDNS;
use App\Repository\ApikeyRepository;
use App\Repository\DomainRepository;
use App\Repository\DynDNSRepository;
use App\Repository\PanelRepository;
use DI\Container;
use DI\ContainerBuilder;
@ -57,7 +55,6 @@ class RequestController
private DomainController $domainController;
private DomainRepository $domainRepository;
private PanelRepository $panelRepository;
private DynDNSRepository $DynDNSRepository;
private Container $container;
private string $header;
private array $result;
@ -76,6 +73,7 @@ class RequestController
{
$this->requestMethod = strtoupper(string: $requestMethod);
$dateFormat = "Y:m:d H:i:s";
$output = "%datetime% %channel%.%level_name% %message%\n"; // %context% %extra%
$formatter = new LineFormatter(format: $output, dateFormat: $dateFormat);
@ -86,10 +84,6 @@ class RequestController
$this->log = new Logger(name: 'bindAPI');
$this->log->pushHandler(handler: $stream);
if ($this->config['debug']) {
$this->log->debug(message: 'RequestController::__construct');
}
$containerBuilder = new ContainerBuilder();
$containerBuilder->addDefinitions([
@ -100,9 +94,6 @@ class RequestController
DomainRepository::class => autowire()
->constructorParameter(parameter: 'config', value: $this->config)
->constructorParameter(parameter: 'log', value: $this->log),
DynDNSRepository::class => autowire()
->constructorParameter(parameter: 'config', value: $this->config)
->constructorParameter(parameter: 'log', value: $this->log),
]);
$this->container = $containerBuilder->build();
@ -112,7 +103,6 @@ class RequestController
$this->domainController = $this->container->get(name: DomainController::class);
$this->domainRepository = $this->container->get(name: DomainRepository::class);
$this->panelRepository = $this->container->get(name: PanelRepository::class);
$this->dynDNSRepository = $this->container->get(name: DynDNSRepository::class);
}
/**
@ -298,6 +288,7 @@ class RequestController
echo $this->status;
} else {
echo json_encode(value: [
'status' => $this->status ?? "Error: No status",
'message' => $this->message ?? "Error: No message."
]);
}
@ -525,10 +516,6 @@ class RequestController
private function handleDynDNS()
{
if ($this->config['debug']) {
$this->log->debug(message: 'handleDynDNS()');
}
if ($this->checkPassword()) {
$host = $this->uri[3] ?? '';
@ -549,58 +536,9 @@ class RequestController
}
}
if ($this->config['debug']) {
$this->log->debug(message: 'a: ' . $a);
$this->log->debug(message: 'aaaa: ' . $aaaa);
}
$domainName = $this->getDomain(host: $host);
$hostName = str_replace(search: '.' . $domainName, replace: '', subject: $host);
if (!$domain = $this->domainRepository->findByName(name: $domainName)) {
$this->header = '404 Not Found';
$this->message = 'Domain ' . $domainName . ' not found';
} else {
// check if address has changed
if ($dynDNS = $this->dynDNSRepository->findByName(name: $host)) {
echo 'found host';
print_r($dynDNS);
print("a: $a");
print("aaaa: $aaaa");
$ipChanged = false;
if (!empty($a)) {
if ($a != $dynDNS->getA()) {
echo $a . '!=' . $dynDNS->getA();
$dynDNS->setA(a: $a);
$ipChanged = true;
}
}
if (!empty($aaaa)) {
if ($aaaa != $dynDNS->getAaaa()) {
$dynDNS->setAaaa(aaaa: $aaaa);
$ipChanged = true;
}
}
if (!$ipChanged) {
$this->header = '304 Not Modified';
$this->message = 'Not modified';
} else {
$this->dynDNSRepository->update(dynDNS: $dynDNS);
}
} else {
$dynDNS = new DynDNS(name: $host, a: $a, aaaa: $aaaa);
$this->dynDNSRepository->insert(dynDNS: $dynDNS);
}
$domain = $this->domainRepository->findByName(name: $domainName);
$panel = $this->panelRepository->findByName(name: $domain->getPanel());
if (!empty($panel->getAaaa())) {
@ -696,12 +634,11 @@ class RequestController
}
if ($result['header'] == 200) {
$this->header = '200 OK';
$this->message = 'DynDNS host successfully updated';
$this->status = json_encode(value: ['message' => 'DynDNS host successfully updated']);
}
} else {
$this->header = '404 Not Found';
$this->message = 'Host ' . $hostName . ' not found';
}
$this->status = 'Host ' . COLOR_YELLOW . $hostName . ' not found';
}
}
}

View File

@ -1,82 +0,0 @@
<?php declare(strict_types=1);
namespace App\Entity;
/**
*
*/
class DynDNS
{
/**
*/
public function __construct(private string $name, private string $a, private string $aaaa, private int $id = 0)
{
}
/**
* @return String
*/
public function getA(): string
{
return $this->a;
}
/**
* @return String
*/
public function getAaaa(): string
{
return $this->aaaa;
}
/**
* @return int
*/
public function getId(): int
{
return $this->id;
}
/**
* @return String
*/
public function getName(): string
{
return $this->name;
}
/**
* @param String $a
*/
public function setA(string $a): void
{
$this->a = $a;
}
/**
* @param String $aaaa
*/
public function setAaaa(string $aaaa): void
{
$this->aaaa = $aaaa;
}
/**
* @param int $id
*/
public function setId(int $id): void
{
$this->id = $id;
}
/**
* @param String $name
*/
public function setName(string $name): void
{
$this->name = $name;
}
}

View File

@ -1,14 +0,0 @@
<?php
namespace App\Enums;
/**
*
*/
enum PanelType
{
case Panel;
case Custom;
case Undefined;
}

View File

@ -1,245 +0,0 @@
<?php declare(strict_types=1);
namespace App\Repository;
use App\Controller\DatabaseConnection;
use App\Entity\DynDNS;
use Monolog\Logger;
use PDO;
use PDOException;
/**
*
*/
class DynDNSRepository
{
public function __construct(private DatabaseConnection $databaseConnection, private array $config, private Logger $log)
{
if ($this->config['debug']) {
$this->log->debug(message: "DynDNSRepository::__construct()");
}
}
/**
* @param \App\Entity\DynDNS $dynDNS
*
* @return int
*/
public function delete(DynDNS $dynDNS): int
{
$dynDNSName = $dynDNS->getName();
if ($this->config['debug']) {
$this->log->debug(message: "delete($dynDNSName)");
}
$sql = "
DELETE FROM " . DatabaseConnection::TABLE_DYNDNS . "
WHERE id = :id";
try {
$statement = $this->databaseConnection->getConnection()->prepare(query: $sql);
$id = $dynDNS->getId();
$statement->bindParam(param: 'id', var: $id);
$statement->execute();
return $statement->rowCount();
} catch (PDOException $e) {
exit($e->getMessage());
}
}
/**
* @return array
*/
public function findAll(): array
{
if ($this->config['debug']) {
$this->log->debug(message: "findAll()");
}
$dyndns = [];
$sql = "
SELECT id, name, a, aaaa
FROM " . DatabaseConnection::TABLE_DYNDNS . "
ORDER BY name";
try {
$statement = $this->databaseConnection->getConnection()->prepare(query: $sql);
$statement->execute();
while ($result = $statement->fetch(mode: PDO::FETCH_ASSOC)) {
$dyndns = new DynDNS(name: $result['name'], a: $result['a'], aaaa: $result['aaaa'], id: $result['id']);
$dyndns[] = $dyndns;
}
return $dyndns;
} catch (PDOException $e) {
exit($e->getMessage());
}
}
/**
* @param String $name
*
* @return \App\Entity\Domain|bool
*/
public function findByName(string $name): DynDNS|bool
{
if ($this->config['debug']) {
$this->log->debug(message: "findByName($name)");
}
$sql = "
SELECT id, name, a, aaaa
FROM " . DatabaseConnection::TABLE_DYNDNS . "
WHERE name = :name";
try {
$statement = $this->databaseConnection->getConnection()->prepare(query: $sql);
$statement->bindParam(param: ':name', var: $name);
$statement->execute();
if ($result = $statement->fetch(mode: PDO::FETCH_ASSOC)) {
return new DynDNS(name: $result['name'], a: $result['a'], aaaa: $result['aaaa'], id: $result['id']);
} else {
return false;
}
} catch (PDOException $e) {
exit($e->getMessage());
}
}
/**
* @param String $field
*
* @return int
*/
public function getLongestEntry(string $field): int
{
$sql = "
SELECT MAX(LENGTH(" . $field . ")) as length FROM " . DatabaseConnection::TABLE_DYNDNS;
try {
$statement = $this->databaseConnection->getConnection()->prepare(query: $sql);
$statement->execute();
$result = $statement->fetch();
return $result['length'];
} catch (PDOException $e) {
exit($e->getMessage());
}
}
/**
* @param \App\Entity\DynDNS $dynDNS
*
* @return string|false
*/
public function insert(DynDNS $dynDNS): bool|string
{
$dynDNSName = $dynDNS->getName();
if ($this->config['debug']) {
$this->log->debug(message: "insert($dynDNSName)");
}
$sql = "
INSERT INTO " . DatabaseConnection::TABLE_DYNDNS . " (name, a, aaaa)
VALUES (:name, :a, :aaaa)";
try {
$a = $dynDNS->getA();
$aaaa = $dynDNS->getAaaa();
$statement = $this->databaseConnection->getConnection()->prepare(query: $sql);
$statement->bindParam(param: ':name', var: $dynDNSName);
$statement->bindParam(param: ':a', var: $a);
$statement->bindParam(param: ':aaaa', var: $aaaa);
$statement->execute();
return $this->databaseConnection->getConnection()->lastInsertId();
} catch (PDOException $e) {
exit($e->getMessage());
}
}
/**
* @param \App\Entity\DynDNS $dynDNS
*
* @return false|int
*/
public function update(DynDNS $dynDNS): bool|int
{
$dynDNSnName = $dynDNS->getName();
if ($this->config['debug']) {
$this->log->debug(message: "update($dynDNSnName)");
}
$id = $dynDNS->getId();
$current = $this->findByID(id: $id);
if (empty($dynDNSnName)) {
$name = $current->getName();
} else {
$name = $dynDNSnName;
}
if (empty($dynDNS->getA())) {
$a = $current->getA();
} else {
$a = $dynDNS->getA();
}
if (empty($dynDNS->getAaaa())) {
$aaaa = $current->getAaaa();
} else {
$aaaa = $dynDNS->getAaaa();
}
$sql = "
UPDATE " . DatabaseConnection::TABLE_DYNDNS . " SET
name = :name,
a = :a,
aaaa = :aaaa
WHERE id = :id";
try {
$statement = $this->databaseConnection->getConnection()->prepare(query: $sql);
$statement->bindParam(param: 'id', var: $id);
$statement->bindParam(param: 'name', var: $name);
$statement->bindParam(param: 'a', var: $a);
$statement->bindParam(param: 'aaaa', var: $aaaa);
$statement->execute();
return $statement->rowCount();
} catch (PDOException $e) {
echo $e->getMessage();
return false;
}
}
/**
* @param int $id
*
* @return bool|\App\Entity\Domain
*/
public function findByID(int $id): bool|DynDNS
{
if ($this->config['debug']) {
$this->log->debug(message: "findById($id)");
}
$sql = "
SELECT id, name, a, aaaa
FROM . " . DatabaseConnection::TABLE_DYNDNS . "
WHERE id = :id";
try {
$statement = $this->databaseConnection->getConnection()->prepare(query: $sql);
$statement->bindParam(param: ':id', var: $id);
$statement->execute();
if ($result = $statement->fetch(mode: PDO::FETCH_ASSOC)) {
return new DynDNS(name: $result['name'], a: $result['a'], aaaa: $result['aaaa'], id: $result['id']);
} else {
return false;
}
} catch (PDOException $e) {
exit($e->getMessage());
}
}
}

View File

@ -42,28 +42,6 @@ class NameserverRepository
}
/**
* @return \App\Entity\Nameserver
*/
public function findFirst(): Nameserver
{
$nameservers = [];
$sql = "
SELECT id, name, a, aaaa, apikey
FROM " . DatabaseConnection::TABLE_NAMESERVERS . "
ORDER BY name";
try {
$statement = $this->databaseConnection->getConnection()->prepare(query: $sql);
$statement->execute();
$result = $statement->fetch(mode: PDO::FETCH_ASSOC);
return new Nameserver(name: $result['name'], id: $result['id'], a: $result['a'], aaaa: $result['aaaa'], apikey: $result['apikey']);
} catch (PDOException $e) {
exit($e->getMessage());
}
}
/**
* @param int $id
*