Compare commits

..

No commits in common. "cbb428d417ba85d8539087f09a3387f1f08fbf4d" and "ff5160d9bd8ff8bc61d888efce20223185bb9410" have entirely different histories.

9 changed files with 328 additions and 343 deletions

View File

@ -335,7 +335,7 @@ ns1.24unix.net 176.9.165.128 pong 2a01:4f8:161:12cd::128 pong
ns2.24unix.net 37.120.185.117 pong 2a03:4000:f:5e2:a80c:2dff:fed1:e109 pong ns2.24unix.net 37.120.185.117 pong 2a03:4000:f:5e2:a80c:2dff:fed1:e109 pong
``` ```
Now we can add all our panels: Now we can add all out panels:
``` ```
$ ./bin/console panels:create executor.24unix.net a=176.9.165.128 aaaa=2a01:4f8:161:12cd::128 apikey=Lo7jsXYQ.[truncated] $ ./bin/console panels:create executor.24unix.net a=176.9.165.128 aaaa=2a01:4f8:161:12cd::128 apikey=Lo7jsXYQ.[truncated]
@ -446,7 +446,6 @@ tfunix has to be a group member of the „bind“ group.
As root perform: As root perform:
`usermod -G bind tfunix` `usermod -G bind tfunix`
(Mind that it is a capital G, else you'll change the primary group and the checks will fail. (Mind that it is a capital G, else you'll change the primary group and the checks will fail.
Don't ask how I noticed …) Don't ask how I noticed …)
@ -479,46 +478,15 @@ Checking permission:
UID: 5001 UID: 5001
Name: tfunix Name: tfunix
✅ is in group 'bind
Checking file: /etc/bind/local.zones Checking file: /etc/bind/local.zones
✅ Group has write access . ✅ Group has write access .
Checking /etc/bind/named.conf.local Checking /etc/bind/named.conf.local
✅ /etc/bind/local.zones is included in /etc/bind/named.conf.local ✅ /etc/bind/local.zones is included in /etc/bind/named.conf.local
Checking directory: /etc/bind/zones/ Checking directory: /etc/bind/zones/
✅ Group has write access . ✅ Group has write access .
```
Now, there is one manual step left, for now.
We have to go to each panel and add an include file.
BUT: This is a temporary workaround, a later version of Keyhelp will enable us to automate this step.
So, execute ./bin/console check:showincludes:
``` ```
./bin/console check:showincludes
You need to add these lines to /etc/bind/local.bindapi.options and make sure
that include "/etc/bind/local.bindapi.options"; exists in /etc/bind/named.conf.options.
allow-transfer {
176.9.165.128;
2a01:4f8:161:12cd::128;
37.120.185.117;
2a03:4000:f:5e2:a80c:2dff:fed1:e109;
212.227.160.159;
2001:8d8:1801:701::1;
};
also-notify {
176.9.165.128;
2a01:4f8:161:12cd::128;
37.120.185.117;
2a03:4000:f:5e2:a80c:2dff:fed1:e109;
212.227.160.159;
2001:8d8:1801:701::1;
};
After the modification feel free to run named-checkconf to ensure there were no errors.
```
TODO TODO

View File

@ -3,6 +3,5 @@
"dbPort": 3306, "dbPort": 3306,
"dbDatabase": "sampledb", "dbDatabase": "sampledb",
"dbUser": "sampleuser", "dbUser": "sampleuser",
"dbPassword": "secret", "dbPassword": "secret"
"debug": false
} }

View File

@ -41,7 +41,7 @@ class ApiController
} }
curl_setopt(handle: $curl, option: CURLOPT_RETURNTRANSFER, value: 1); curl_setopt(handle: $curl, option: CURLOPT_RETURNTRANSFER, value: 1);
curl_setopt(handle: $curl, option: CURLOPT_TIMEOUT_MS, value: 19999); curl_setopt(handle: $curl, option: CURLOPT_TIMEOUT_MS, value: 3000);
curl_setopt(handle: $curl, option: CURLOPT_HTTP_VERSION, value: CURL_HTTP_VERSION_2TLS); curl_setopt(handle: $curl, option: CURLOPT_HTTP_VERSION, value: CURL_HTTP_VERSION_2TLS);
if ($versionIP == 4) { if ($versionIP == 4) {
@ -91,16 +91,11 @@ class ApiController
$error = true; $error = true;
$result = curl_error(handle: $curl); $result = curl_error(handle: $curl);
} }
$info = curl_getinfo(handle: $curl);
$responseTime = $info['total_time'];
curl_close(handle: $curl); curl_close(handle: $curl);
return [ return [
'responseTime' => $responseTime, 'error' => $error,
'error' => $error, 'data' => $result,
'data' => $result, 'header' => $httpResponse ?? ''
'header' => $httpResponse ?? ''
]; ];
} }

View File

@ -145,8 +145,6 @@ class BindAPI
echo COLOR_GREEN . "\t check:permissions" . PHP_EOL; echo COLOR_GREEN . "\t check:permissions" . PHP_EOL;
echo COLOR_GREEN . "\t check:panels {ID} {fix=yes}" . PHP_EOL; echo COLOR_GREEN . "\t check:panels {ID} {fix=yes}" . PHP_EOL;
echo COLOR_GREEN . "\t check:domains {ID} {fix=yes}" . PHP_EOL; echo COLOR_GREEN . "\t check:domains {ID} {fix=yes}" . PHP_EOL;
echo COLOR_GREEN . "\t check:showinclude" . COLOR_DEFAULT . " Temporary needed until KeyHelp 22.1" . PHP_EOL;
echo COLOR_YELLOW . "panels" . COLOR_DEFAULT . "\t all Keyhelp systems configured" . PHP_EOL; echo COLOR_YELLOW . "panels" . COLOR_DEFAULT . "\t all Keyhelp systems configured" . PHP_EOL;
echo COLOR_GREEN . "\t panels:list" . PHP_EOL; echo COLOR_GREEN . "\t panels:list" . PHP_EOL;
@ -187,7 +185,6 @@ class BindAPI
match ($subcommand) { match ($subcommand) {
'permissions' => $this->handleCheckPermissions(), 'permissions' => $this->handleCheckPermissions(),
'panels' => $this->handleCheckPanels(), 'panels' => $this->handleCheckPanels(),
'showincludes' => $this->showIncludes(),
}; };
} catch (UnhandledMatchError) { } catch (UnhandledMatchError) {
echo 'Unknown action: ' . $subcommand . PHP_EOL; echo 'Unknown action: ' . $subcommand . PHP_EOL;
@ -248,59 +245,16 @@ class BindAPI
$this->log->debug(message: "checkSinglePanel()"); $this->log->debug(message: "checkSinglePanel()");
} }
echo COLOR_DEFAULT . 'Keyhelp-Panel: ' . COLOR_YELLOW . $panel->getName(); echo COLOR_DEFAULT . 'Keyhelp-Panel: ' . COLOR_YELLOW . $panel->getName() . PHP_EOL;
if (!empty($panel->getAaaa())) {
if ($this->config['verbose']) {
if (empty($panel->getA())) {
try {
$panelRequest = $this->apiController->sendCommand(
requestType: 'GET',
serverName : $panel->getName(),
versionIP : 6,
apiKey : $panel->getApikey(),
command : '/server',
serverType : 'panel');
} catch (DependencyException|NotFoundException $e) {
echo $e->getMessage();
exit(1);
}
} else {
try {
$panelRequest = $this->apiController->sendCommand(
requestType: 'GET',
serverName : $panel->getName(),
versionIP : 4,
apiKey : $panel->getApikey(),
command : '/server',
serverType : 'panel');
} catch (DependencyException|NotFoundException $e) {
echo $e->getMessage();
exit();
}
}
$panelData = json_decode(json: $panelRequest['data']);
if (!empty($panelData)) {
$panelVersion = $panelData->meta->panel_version;
$responseTime = sprintf("%0.3f", $panelRequest['responseTime']);
} else {
$panelVersion = 'n/a';
$responseTime = 'n/a';
}
echo COLOR_DEFAULT . ' KeyHelp version: ' . $panelVersion . " ($responseTime seconds)" . PHP_EOL;
} else {
echo PHP_EOL;
}
if (empty($panel->getA())) {
try { try {
$result = $this->apiController->sendCommand( $result = $this->apiController->sendCommand(
requestType: 'GET', requestType: 'GET',
serverName : $panel->getName(), serverName: $panel->getName(),
versionIP : 6, versionIP: 6,
apiKey : $panel->getApikey(), apiKey: $panel->getApikey(),
command : 'domains', command: 'domains',
serverType : 'panel' serverType: 'panel'
); );
} catch (DependencyException|NotFoundException $e) { } catch (DependencyException|NotFoundException $e) {
echo $e->getMessage(); echo $e->getMessage();
@ -309,17 +263,16 @@ class BindAPI
try { try {
$result = $this->apiController->sendCommand( $result = $this->apiController->sendCommand(
requestType: 'GET', requestType: 'GET',
serverName : $panel->getName(), serverName: $panel->getName(),
versionIP : 4, versionIP: 4,
apiKey : $panel->getApikey(), apiKey: $panel->getApikey(),
command : 'domains', command: 'domains',
serverType : 'panel'); serverType: 'panel');
} catch (DependencyException|NotFoundException $e) { } catch (DependencyException|NotFoundException $e) {
echo $e->getMessage(); echo $e->getMessage();
} }
} }
if (!empty($result['error'])) { if (!empty($result['error'])) {
echo $result['data'] . PHP_EOL; echo $result['data'] . PHP_EOL;
exit(1); exit(1);
@ -342,7 +295,7 @@ class BindAPI
$domainCount = 0; $domainCount = 0;
foreach ($domains as $domain) { foreach ($domains as $domain) {
if ($this->isValidSecondLevelDomain(domainName: $domain->domain, panel: $panel->getName(), parent: $domain->id_parent_domain)) { if ($this->isValidSecondLevelDomain(domainName: $domain->domain, panel: $panel->getName(), parent: $domain->id_parent_domain)) {
echo COLOR_DEFAULT . " Domain: " . COLOR_YELLOW . str_pad(string: $domain->domain, length: $maxDomainName); echo COLOR_DEFAULT . "Domain: " . COLOR_YELLOW . str_pad(string: $domain->domain, length: $maxDomainName);
try { try {
$this->checkNS(domainName: $domain->domain, panel: $panel); $this->checkNS(domainName: $domain->domain, panel: $panel);
} catch (DependencyException|NotFoundException $e) { } catch (DependencyException|NotFoundException $e) {
@ -353,9 +306,9 @@ class BindAPI
} }
} }
if ($domainCount == 0) { if ($domainCount == 0) {
echo 'No second level domains found.' . COLOR_DEFAULT . PHP_EOL; echo 'No second level domains found.' . PHP_EOL;
} }
echo PHP_EOL;
} }
function isValidSecondLevelDomain(string $domainName, string $panel, int $parent): bool function isValidSecondLevelDomain(string $domainName, string $panel, int $parent): bool
@ -418,19 +371,19 @@ class BindAPI
if (!empty($nameServer->getName())) { if (!empty($nameServer->getName())) {
$result = $this->apiController->sendCommand( $result = $this->apiController->sendCommand(
requestType: 'GET', requestType: 'GET',
serverName : $nameServer->getName(), serverName: $nameServer->getName(),
versionIP : 6, versionIP: 6,
apiKey : $nameServer->getApikey(), apiKey: $nameServer->getApikey(),
command : 'domains/name/' . $domainName, command: 'domains/name/' . $domainName,
serverType : 'nameserver'); serverType: 'nameserver');
} else { } else {
$result = $this->apiController->sendCommand( $result = $this->apiController->sendCommand(
requestType: 'GET', requestType: 'GET',
serverName : $nameServer->getName(), serverName: $nameServer->getName(),
versionIP : 4, versionIP: 4,
apiKey : $nameServer->getApikey(), apiKey: $nameServer->getApikey(),
command : 'domains/name/', command: 'domains/name/',
serverType : 'nameserver' . $domainName); serverType: 'nameserver' . $domainName);
} }
} catch (DependencyException|NotFoundException $e) { } catch (DependencyException|NotFoundException $e) {
echo $e->getMessage(); echo $e->getMessage();
@ -450,26 +403,26 @@ class BindAPI
'name' => $domainName, 'name' => $domainName,
'panel' => $panel->getName(), 'panel' => $panel->getName(),
'content' => $this->domainController->createPanelContent(panel: $panel->getName()) 'content' => $this->domainController->createPanelContent(panel: $panel->getName())
]; ];
try { try {
if (!empty($nameServer->getAaaa())) { if (!empty($nameServer->getAaaa())) {
$create = $this->apiController->sendCommand( $create = $this->apiController->sendCommand(
requestType: 'POST', requestType: 'POST',
serverName : $nameServer->getName(), serverName: $nameServer->getName(),
versionIP : 6, versionIP: 6,
apiKey : $nameServer->getApikey(), apiKey: $nameServer->getApikey(),
command : 'domains', command: 'domains',
serverType : 'nameserver', serverType: 'nameserver',
body : $body); body: $body);
} else { } else {
$create = $this->apiController->sendCommand( $create = $this->apiController->sendCommand(
requestType: 'POST', requestType: 'POST',
serverName : $nameServer->getName(), serverName: $nameServer->getName(),
versionIP : 4, versionIP: 4,
apiKey : $nameServer->getAPikey(), apiKey: $nameServer->getAPikey(),
command : 'domains', command: 'domains',
serverType : 'nameserver', serverType: 'nameserver',
body : $body); body: $body);
} }
} catch (DependencyException|NotFoundException $e) { } catch (DependencyException|NotFoundException $e) {
echo $e->getMessage(); echo $e->getMessage();
@ -795,11 +748,11 @@ class BindAPI
try { try {
if ($result = $this->apiController->sendCommand( if ($result = $this->apiController->sendCommand(
requestType: 'GET', requestType: 'GET',
serverName : $server->getName(), serverName: $server->getName(),
versionIP : 4, versionIP: 4,
apiKey : $server->getApikey(), apiKey: $server->getApikey(),
command : 'ping', command: 'ping',
serverType : $type)) { serverType: $type)) {
if ($this->config['verbose']) { if ($this->config['verbose']) {
if ($result['data'] == 'pong') { if ($result['data'] == 'pong') {
echo COLOR_GREEN . $result['data']; echo COLOR_GREEN . $result['data'];
@ -822,11 +775,11 @@ class BindAPI
try { try {
if ($result = $this->apiController->sendCommand( if ($result = $this->apiController->sendCommand(
requestType: 'GET', requestType: 'GET',
serverName : $server->getName(), serverName: $server->getName(),
versionIP : 6, versionIP: 6,
apiKey : $server->getApikey(), apiKey: $server->getApikey(),
command : 'ping', command: 'ping',
serverType : $type)) { serverType: $type)) {
if ($this->config['verbose']) { if ($this->config['verbose']) {
if ($result['data'] == 'pong') { if ($result['data'] == 'pong') {
echo COLOR_GREEN . $result['data']; echo COLOR_GREEN . $result['data'];
@ -1016,14 +969,28 @@ class BindAPI
} }
if (!empty($domains)) { if (!empty($domains)) {
$table = new ConsoleTable(); $table = new ConsoleTable();
$table->setHeaders(content: ['ID', 'Name', 'Panel']); $table->setHeaders(content: ['ID', 'Name', 'Content']);
/** @var Domain $domain */ /** @var Domain $domain */
foreach ($domains as $domain) { foreach ($domains as $domain) {
$row = []; $row = [];
try { try {
$row[] = $domain->getId(); $row[] = $domain->getId();
$row[] = $domain->getName(); $row[] = $domain->getName();
$row[] = $domain->getPanel(); $content = json_decode(json: $domain->getContent());
$column = '';
if (!empty($content->panel)) {
$column = 'Panel: ' . $content->panel;
}
if (!empty($content->custom)) {
$column .= 'Custom: ';
if (!empty($content->custom->a)) {
$column .= 'A: ' . $content->custom->a;
}
if (!empty($content->custom->aaaa)) {
$column .= ' AAAA: ' . $content->custom->a;
}
}
$row[] = $column;
} catch (DependencyException|NotFoundException $e) { } catch (DependencyException|NotFoundException $e) {
echo $e->getMessage(); echo $e->getMessage();
} }
@ -1056,11 +1023,16 @@ class BindAPI
} }
$arguments = $this->parseArguments(); $arguments = $this->parseArguments();
$a = $arguments['a'] ?? '';
$aaaa = $arguments['aaaa'] ?? '';
$panel = $arguments['panel'] ?? ''; $panel = $arguments['panel'] ?? '';
if (empty($panel)) { print("panel: $panel");
echo 'You need to supply the panel name.' . PHP_EOL; if (empty($a) && empty($aaaa) && empty($panel)) {
exit(1); echo 'At least one IP address or panel is required.' . PHP_EOL;
exit(0);
} }
try { try {
@ -1068,13 +1040,24 @@ class BindAPI
echo "Domain: $name already exists." . PHP_EOL; echo "Domain: $name already exists." . PHP_EOL;
exit(1); exit(1);
} else { } else {
if ($this->panelRepository->findByName(name: $panel)) { if (!empty($panel)) {
$content = $this->domainController->createPanelContent(panel: $panel); if ($this->panelRepository->findByName(name: $panel)) {
$content = $this->domainController->createPanelContent(panel: $panel);
} else {
echo 'Unknown panel: ' . $panel;
exit(1);
}
} else { } else {
echo 'Unknown panel: ' . $panel; $content = [];
exit(1); if (!empty($a)) {
$content['a'] = $a;
}
if (!empty($aaaa)) {
$content['aaaa'] = $aaaa;
}
$content = $this->domainController->createIPContent(ip: $content);
} }
$domain = new Domain(name: $name, panel: $panel); $domain = new Domain(name: $name, content: $content);
$result = $this->domainRepository->insert(domain: $domain); $result = $this->domainRepository->insert(domain: $domain);
echo "Domain $name has been created with id $result" . PHP_EOL; echo "Domain $name has been created with id $result" . PHP_EOL;
$this->domainController->createSlaveZoneFile(domain: $domain); $this->domainController->createSlaveZoneFile(domain: $domain);
@ -1095,7 +1078,9 @@ class BindAPI
$id = intval(value: $this->arguments[1] ?? 0); $id = intval(value: $this->arguments[1] ?? 0);
$name = $arguments['name'] ?? ''; $name = $arguments['name'] ?? '';
$panelName = $arguments['panel'] ?? ''; $panel = $arguments['panel'] ?? '';
$a = $arguments['a'] ?? '';
$aaaa = $arguments['aaaa'] ?? '';
if ($id == 0) { if ($id == 0) {
echo 'An ID is required' . PHP_EOL; echo 'An ID is required' . PHP_EOL;
@ -1108,17 +1093,35 @@ class BindAPI
$content = []; $content = [];
if (!empty($panelName)) { if (!empty($panel)) {
$panel = $this->panelRepository->findByName(name: $panelName); $panel = $this->panelRepository->findByName(name: $panel);
$content = $this->domainController->createPanelContent(panel: $panel->getName());
} else {
$addresses = [];
if (!empty($a)) {
$addresses[] = [
'a' => $a
];
}
if (!empty($aaaa)) {
$addresses[] = [
'aaaa' => $aaaa
];
}
if (!empty($addresses)) {
$content = $this->domainController->createIPContent(ip: $content);
}
} }
if (empty($name) && empty($content)) {
if (empty($name) && empty($panel)) {
echo 'No name or panel given, just recreate the config file' . PHP_EOL; echo 'No name or panel given, just recreate the config file' . PHP_EOL;
$this->domainController->createSlaveZoneFile(domain: $domain); $this->domainController->createSlaveZoneFile(domain: $domain);
exit(1); exit(1);
} }
$newDomain = new Domain(name: $name, panel: $panelName, id: $domain->getId()); if (empty($content)) {
$newDomain = new Domain(name: $name, id: $domain->getId(), content: '');
} else {
$newDomain = new Domain(name: $name, id: $domain->getId(), content: $content);
}
if ($this->domainRepository->update(domain: $newDomain) !== false) { if ($this->domainRepository->update(domain: $newDomain) !== false) {
echo 'Domain server has been updated' . PHP_EOL; echo 'Domain server has been updated' . PHP_EOL;
$this->domainController->createSlaveZoneFile(domain: $domain); $this->domainController->createSlaveZoneFile(domain: $domain);
@ -1316,36 +1319,4 @@ class BindAPI
$this->nameserverRepository->delete(id: $id); $this->nameserverRepository->delete(id: $id);
echo "The nameserver with ID $id has been deleted." . PHP_EOL; echo "The nameserver with ID $id has been deleted." . PHP_EOL;
} }
/**
* @throws \DI\DependencyException
* @throws \DI\NotFoundException
*/
private function showIncludes()
{
$nameservers = $this->nameserverRepository->findAll();
echo COLOR_DEFAULT . 'You need to add these lines to ' . COLOR_YELLOW . '/etc/bind/local.bindapi.options' . COLOR_DEFAULT . ' and make sure' . PHP_EOL;
echo 'that ' . COLOR_YELLOW . 'include "/etc/bind/local.bindapi.options";' . COLOR_DEFAULT . ' exists in ' . COLOR_YELLOW . '/etc/bind/named.conf.options' . COLOR_DEFAULT . '.' . PHP_EOL;
$ip = [];
foreach ($nameservers as $nameserver) {
if (!empty($nameserver->getA())) {
$ip[] = $nameserver->getA();
}
if (!empty($nameserver->getAaaa())) {
$ip[] = $nameserver->getAaaa();
}
}
echo PHP_EOL . 'allow-transfer {' . PHP_EOL;
foreach ($ip as $currentIp)
echo "\t$currentIp;" . PHP_EOL;
echo '};';
echo PHP_EOL . 'also-notify {' . PHP_EOL;
foreach ($ip as $currentIp)
echo "\t$currentIp;" . PHP_EOL;
echo '};' . PHP_EOL;
echo PHP_EOL . 'After the modification feel free to run ' . COLOR_YELLOW . 'named-checkconf' . COLOR_DEFAULT . ' to ensure there were no errors.' . PHP_EOL;
}
} }

View File

@ -53,7 +53,9 @@ class DatabaseConnection
CREATE TABLE `domains` ( CREATE TABLE `domains` (
`id` int(11) NOT NULL AUTO_INCREMENT, `id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL, `name` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
`panel` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL, `panel_id` int(11) DEFAULT 0,
`a` varbinary(255) DEFAULT NULL,
`aaaa` varbinary(255) DEFAULT NULL,
PRIMARY KEY (`id`) PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci"; ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci";
$statement = $this->dbConnection->prepare(query: $sql); $statement = $this->dbConnection->prepare(query: $sql);
@ -79,7 +81,7 @@ class DatabaseConnection
`aaaa` varbinary(255) DEFAULT NULL, `aaaa` varbinary(255) DEFAULT NULL,
`apikey` varbinary(255) DEFAULT NULL, `apikey` varbinary(255) DEFAULT NULL,
PRIMARY KEY (`id`) PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci"; ) ENGINE=InnoDB AUTO_INCREMENT=28 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci";
$statement = $this->dbConnection->prepare(query: $sql); $statement = $this->dbConnection->prepare(query: $sql);
$statement->execute(); $statement->execute();

View File

@ -117,7 +117,7 @@ class DomainController
$bindGroup = posix_getgrnam(name: 'bind'); $bindGroup = posix_getgrnam(name: 'bind');
$members = $bindGroup['members']; $members = $bindGroup['members'];
if (in_array(needle: $name, haystack: $members)) { if (in_array(needle: $name, haystack: $members)) {
echo "\t$name is in group 'bind" . PHP_EOL; echo "\tis in group 'bind" . PHP_EOL;
} else { } else {
echo "\t$name needs to be in group $bindGroup!" . PHP_EOL; echo "\t$name needs to be in group $bindGroup!" . PHP_EOL;
@ -211,13 +211,15 @@ class DomainController
// check if we're a master zone // check if we're a master zone
$keyhelpConf = file_get_contents(filename: $this->keyhelpNamedCond); $keyhelpConf = file_get_contents(filename: $this->keyhelpNamedCond);
if (str_contains(haystack: $keyhelpConf, needle: $domain->getName())) { if (str_contains($keyhelpConf, $domain->getName())) {
echo 'We a zone master for ' . $domain->getName() . PHP_EOL; echo 'We a zone master for ' . $domain->getName() . PHP_EOL;
exit(1); exit(1);
} }
if ($zonefile = fopen(filename: $this->localZonesDir . $domain->getName(), mode: 'w')) { if ($zonefile = fopen(filename: $this->localZonesDir . $domain->getName(), mode: 'w')) {
$panelName = $domain->getPanel(); // TODO fixme soon
$content = json_decode(json: $domain->getContent());
$panelName = $content->panel;
$panel = $this->panelRepository->findByName(name: $panelName); $panel = $this->panelRepository->findByName(name: $panelName);
$a = $panel->getA(); $a = $panel->getA();
$aaaa = $panel->getAaaa(); $aaaa = $panel->getAaaa();
@ -235,7 +237,42 @@ class DomainController
fputs(stream: $zonefile, data: "};" . PHP_EOL); fputs(stream: $zonefile, data: "};" . PHP_EOL);
} }
$this->createIncludeFile(); $this->createIncludeFile();
// TODO add on nameservers
}
/**
* @param String $panel
*
* @return String
*/
function createPanelContent(String $panel): String
{
return json_encode(value: [
'panel' => $panel
]
);
} }
/**
* @param array $ip
*
* @return String
*/
function createIPContent(array $ip): String
{
$result = [];
if (!empty($ip['a'])) {
$result['a'] = $ip['a'];
}
if (!empty($ip['aaaa'])) {
$result['aaaa'] = $ip['aaaa'];
}
return json_encode(value: [
'custom' => $result
]
);
}
} }

View File

@ -22,17 +22,17 @@ use OpenApi\Attributes as OAT;
*/ */
#[OAT\Info(version: '0.0.1', title: 'bindAPI')] #[OAT\Info(version: '0.0.1', title: 'bindAPI')]
#[OAT\Server( #[OAT\Server(
url : "{schema}://{hostname}/api", url: "{schema}://{hostname}/api",
description: "The bindAPI URL.", description: "The bindAPI URL.",
variables : [ variables: [
new OAT\ServerVariable( new OAT\ServerVariable(
serverVariable: "schema", serverVariable: "schema",
default : "https", default: "https",
enum : ["https", "http"] enum: ["https", "http"]
), ),
new OAT\ServerVariable( new OAT\ServerVariable(
serverVariable: "hostname", serverVariable: "hostname",
default : "ns2.24unix.net", default: "ns2.24unix.net",
) )
] ]
)] )]
@ -41,10 +41,10 @@ use OpenApi\Attributes as OAT;
)] )]
#[OAT\SecurityScheme( #[OAT\SecurityScheme(
securityScheme: "Authorization", securityScheme: "Authorization",
type : "apiKey", type: "apiKey",
description : "description", description: "description",
name : "X-API-Key", name: "X-API-Key",
in : "header" in: "header"
)] )]
class RequestController class RequestController
{ {
@ -101,29 +101,29 @@ class RequestController
* @return void * @return void
*/ */
#[OAT\Get( #[OAT\Get(
path : '/domains', path: '/domains',
operationId: 'getAllDomains', operationId: 'getAllDomains',
description: 'Returns a list of all domains on this server.', description: 'Returns a list of all domains on this server.',
summary : 'Listing all domains.', summary: 'Listing all domains.',
// security: [ // security: [
// 'Authorization' => [ // 'Authorization' => [
// //
// "read:api" // "read:api"
// ] // ]
// ], // ],
servers : [], servers: [],
tags : ['Domains'], tags: ['Domains'],
responses : [ responses: [
new OAT\Response( new OAT\Response(
response : 200, response: 200,
description: 'OK' description: 'OK'
), ),
new OAT\Response( new OAT\Response(
response : 401, response: 401,
description: 'API key is missing or invalid.' description: 'API key is missing or invalid.'
), ),
new OAT\Response( new OAT\Response(
response : 404, response: 404,
description: 'Domain not found.' description: 'Domain not found.'
)] )]
)] )]
@ -186,27 +186,27 @@ class RequestController
*/ */
#[OAT\Get( #[OAT\Get(
path : '/domains/{name}', path: '/domains/{name}',
operationId: 'getSingleDomain', operationId: 'getSingleDomain',
description: 'Returns information of a single domain specified by its domain name.', description: 'Returns information of a single domain specified by its domain name.',
summary : 'Returns a single domain.', summary: 'Returns a single domain.',
security : [ security: [
], ],
tags : ['Domains'], tags: ['Domains'],
parameters : [ parameters: [
new OAT\Parameter(name: 'name', in: 'path', required: true, schema: new OAT\Schema(type: 'string')), new OAT\Parameter(name: 'name', in: 'path', required: true, schema: new OAT\Schema(type: 'string')),
], ],
responses : [ responses: [
new OAT\Response( new OAT\Response(
response : 200, response: 200,
description: 'OK' description: 'OK'
), ),
new OAT\Response( new OAT\Response(
response : 401, response: 401,
description: 'API key is missing or invalid.' description: 'API key is missing or invalid.'
), ),
new OAT\Response( new OAT\Response(
response : 404, response: 404,
description: 'Domain not found.' description: 'Domain not found.'
)] )]
@ -314,9 +314,9 @@ class RequestController
if ($this->uri[3] == 'name') { if ($this->uri[3] == 'name') {
if ($result = $this->domainRepository->findByName(name: $this->uri[4])) { if ($result = $this->domainRepository->findByName(name: $this->uri[4])) {
$domain = [ $domain = [
'id' => $result->getId(), 'id' => $result->getId(),
'name' => $result->getName(), 'name' => $result->getName(),
'panel' => $result->getPanel() 'content' => json_decode(json: $result->getContent())
]; ];
$this->result = $domain; $this->result = $domain;
} else { } else {
@ -332,9 +332,9 @@ class RequestController
if ($id > 0) { if ($id > 0) {
if ($result = $this->domainRepository->findById(id: $id)) { if ($result = $this->domainRepository->findById(id: $id)) {
$domain = [ $domain = [
'id' => $result->getId(), 'id' => $result->getId(),
'name' => $result->getName(), 'name' => $result->getName(),
'panel' => $result->getPanel() 'content' => json_decode(json: $result->getContent())
]; ];
$this->result = $domain; $this->result = $domain;
} else { } else {
@ -342,6 +342,7 @@ class RequestController
$this->status = "404 Not Found "; $this->status = "404 Not Found ";
$this->message = "The specified domain was not found."; $this->message = "The specified domain was not found.";
} }
} else { } else {
$this->header = "400 Bad request"; $this->header = "400 Bad request";
$this->status = "400 Not Found"; $this->status = "400 Not Found";
@ -353,115 +354,126 @@ class RequestController
} }
/** /**
* @return void * @return void
*/ */
public public
function handleDomainPostRequest(): void function handleDomainPostRequest(): void
{ {
$name = $_POST['name'] ?? ''; $name = $_POST['name'] ?? '';
$panel = $_POST['panel'] ?? ''; $panel = $_POST['panel'] ?? '';
if (empty($name)) { $content = $_POST['content'] ?? '';
$this->header = "400 Bad Request"; if (empty($name)) {
$this->status = "400 Bad Request";
$this->message = "A name is required";
} else {
if (empty($panel)) {
$this->header = "400 Bad Request"; $this->header = "400 Bad Request";
$this->status = "400 Bad Request"; $this->status = "400 Bad Request";
$this->message = "A panel ID is required."; $this->message = "A name is required";
} else { } else {
if ($this->domainRepository->findByName(name: $name)) { if (empty($a) && empty($aaaa) && empty($panel)) {
$this->header = "400 Bad request"; $this->header = "400 Bad Request";
$this->status = "400 Bad request"; $this->status = "400 Bad Request";
$this->message = "Domain: $name already exists."; $this->message = "At least one IP address or panel ID is required.";
} else { } else {
$domain = new Domain(name: $name, panel: $panel); if ($this->domainRepository->findByName(name: $name)) {
if ($result = $this->domainRepository->insert(domain: $domain)) { $this->header = "400 Bad request";
$this->header = "201 Created"; $this->status = "400 Bad request";
$this->status = "201 Created"; $this->message = "Domain: $name already exists.";
} else { } else {
$this->header = "500 Server error"; $domain = new Domain(name: $name, content: $content);
$this->status = "500 Server error"; if ($result = $this->domainRepository->insert(domain: $domain)) {
$this->status = "201 Created";
$this->message = $result;
} else {
$this->header = "500 Server error";
$this->status = "500 Server error";
$this->message = $result;
}
} }
$this->message = $result;
} }
} }
} }
}
/** /**
* @return void * @return void
*/ */
public function handleDomainPutRequest(): void public
{ function handleDomainPutRequest(): void
$putData = fopen(filename: 'php://input', mode: 'r'); {
$data = fread(stream: $putData, length: 512); $putData = fopen(filename: 'php://input', mode: 'r');
$params = explode(separator: '&', string: $data); $data = fread(stream: $putData, length: 512);
$params = explode(separator: '&', string: $data);
foreach ($params as $param) { foreach ($params as $param) {
[$key, $value] = explode(separator: '=', string: $param); [$key, $value] = explode(separator: '=', string: $param);
$put[$key] = $value; $put[$key] = $value;
} }
$id = $put['id'] ?? 0; $id = $put['id'] ?? 0;
$name = $put['name'] ?? ''; $name = $put['name'] ?? '';
$panel = $put['panel'] ?? ""; $content = $put['content'] ?? "";
if ($id == 0) { if ($id == 0) {
$this->header = "400 Bad Request"; $this->status = "400 Bad Request";
$this->status = "400 Bad Request"; $this->message = "An ID is required";
$this->message = "An ID is required";
} else {
if (!$this->domainRepository->findByID(id: $id)) {
$this->status = "404 Not Found";
$this->message = "Domain with ID : $id doesn't exist.";
} else { } else {
// TODO not required, as we rely on the ID if (!$this->domainRepository->findByID(id: $id)) {
$domain = new Domain(name: $name, panel: $panel, id: $id); $this->status = "404 Not Found";
$this->domainRepository->update(domain: $domain); $this->message = "Domain with ID : $id doesn't exist.";
$this->header = "201 Updated"; } else {
$this->status = "201 Updated"; // TODO not required, as we rely on the ID
$this->message = "201 Updated"; if (empty($name)) {
$this->status = "400 Bad Request";
$this->message = "A name is required";
} else {
if (empty($a) && empty($aaaa)) {
$this->status = "400 Bad Request";
$this->message = "At least one IP address is required.";
} else {
$domain = new Domain(name: $name, id: $id, content: $content);
$this->domainRepository->update(domain: $domain);
$this->header = "201 Updated";
$this->status = "201 Updated";
$this->message = "201 Updated";
}
}
}
} }
} }
}
/** /**
* @return void * @return void
*/ */
public public
function handleDomainDeleteRequest(): void function handleDomainDeleteRequest(): void
{ {
$deleteData = fopen(filename: 'php://input', mode: 'r'); $deleteData = fopen(filename: 'php://input', mode: 'r');
$data = fread(stream: $deleteData, length: 512); $data = fread(stream: $deleteData, length: 512);
$params = explode(separator: '&', string: $data); $params = explode(separator: '&', string: $data);
foreach ($params as $param) { foreach ($params as $param) {
[$key, $value] = explode(separator: '=', string: $param); [$key, $value] = explode(separator: '=', string: $param);
$delete[$key] = $value; $delete[$key] = $value;
} }
$id = $delete['id'] ?? 0; $id = $delete['id'] ?? 0;
if ($id == 0) { if ($id == 0) {
$this->header = "400 Bad Request";
$this->status = "400 Bad Request";
$this->message = "You need to supply an ID.";
} else {
if (!$domain = $this->domainRepository->findByID(id: $id)) {
$this->header = "400 Bad Request"; $this->header = "400 Bad Request";
$this->status = "400 Bad Request"; $this->status = "400 Bad Request";
$this->message = "There is no domain with ID $id."; $this->message = "You need to supply an ID.";
} else { } else {
$this->domainRepository->delete(domain: $domain);
$this->header = "204 No content."; if (!$domain = $this->domainRepository->findByID(id: $id)) {
$this->status = "204 No content."; $this->header = "400 Bad Request";
$this->message = "The domain $id has been deleted."; $this->status = "400 Bad Request";
$this->message = "There is no domain with ID $id.";
} else {
$this->domainRepository->delete(domain: $domain);
$this->header = "204 No content.";
$this->status = "204 No content.";
$this->message = "The domain $id has been deleted.";
}
} }
} }
}
} }

View File

@ -14,25 +14,9 @@ class Domain
/** /**
*/ */
public function __construct(private string $name, private String $panel, private int $id = 0) public function __construct(private string $name, private int $id = 0, private string $content = '')
{} {}
/**
* @return String
*/
public function getPanel(): string
{
return $this->panel;
}
/**
* @param String $panel
*/
public function setPanel(string $panel): void
{
$this->panel = $panel;
}
/** /**
* @return String * @return String
@ -67,4 +51,21 @@ class Domain
$this->id = $id; $this->id = $id;
} }
/**
* @return string
*/
public function getContent(): string
{
return $this->content;
}
/**
* @param string $content
*/
public function setContent(string $content): void
{
$this->content = $content;
}
} }

View File

@ -33,7 +33,7 @@ class DomainRepository
$domains = []; $domains = [];
$sql = " $sql = "
SELECT id, name, panel SELECT id, name, content
FROM " . DatabaseConnection::TABLE_DOMAINS . " FROM " . DatabaseConnection::TABLE_DOMAINS . "
ORDER BY name"; ORDER BY name";
@ -43,7 +43,7 @@ class DomainRepository
while ($result = $statement->fetch(mode: PDO::FETCH_ASSOC)) { while ($result = $statement->fetch(mode: PDO::FETCH_ASSOC)) {
//print_r($result); //print_r($result);
//die(); //die();
$domain = new Domain(name: $result['name'], panel: $result['panel'], id: $result['id']); $domain = new Domain(name: $result['name'], id: $result['id'], content: $result['content']);
$domains[] = $domain; $domains[] = $domain;
} }
return $domains; return $domains;
@ -75,7 +75,7 @@ class DomainRepository
$statement->execute(); $statement->execute();
if ($result = $statement->fetch(mode: PDO::FETCH_ASSOC)) { if ($result = $statement->fetch(mode: PDO::FETCH_ASSOC)) {
return new Domain(name: $result['name'], panel: $result['content'], id: $result['id']); return new Domain(name: $result['name'], id: $result['id'], content: $result['content']);
} else { } else {
return false; return false;
} }
@ -105,7 +105,7 @@ class DomainRepository
$statement->bindParam(param: ':name', var: $name); $statement->bindParam(param: ':name', var: $name);
$statement->execute(); $statement->execute();
if ($result = $statement->fetch(mode: PDO::FETCH_ASSOC)) { if ($result = $statement->fetch(mode: PDO::FETCH_ASSOC)) {
return new Domain(name: $result['name'], panel: $result['content'], id: $result['id']); return new Domain(name: $result['name'], id: $result['id'], content: $result['content']);
} else { } else {
return false; return false;
} }
@ -133,10 +133,10 @@ class DomainRepository
try { try {
$name = $domain->getName(); $name = $domain->getName();
$panel = $domain->getPanel(); $content = $domain->getContent();
$statement = $this->databaseConnection->getConnection()->prepare(query: $sql); $statement = $this->databaseConnection->getConnection()->prepare(query: $sql);
$statement->bindParam(param: ':name', var: $name); $statement->bindParam(param: ':name', var: $name);
$statement->bindParam(param: ':panel', var: $panel); $statement->bindParam(param: ':content', var: $content);
$statement->execute(); $statement->execute();
return $this->databaseConnection->getConnection()->lastInsertId(); return $this->databaseConnection->getConnection()->lastInsertId();
@ -166,10 +166,10 @@ class DomainRepository
} else { } else {
$name = $domain->getName(); $name = $domain->getName();
} }
if (empty($domain->getPanel())) { if (empty($domain->getContent())) {
$content = $current->getPanel(); $content = $current->getContent();
} else { } else {
$content = $domain->getPanel(); $content = $domain->getContent();
} }
$sql = " $sql = "