diff --git a/src/Controller/BindAPI.php b/src/Controller/BindAPI.php index c070166..e5c7d08 100755 --- a/src/Controller/BindAPI.php +++ b/src/Controller/BindAPI.php @@ -5,12 +5,12 @@ namespace App\Controller; define('COLOR_RED', "\033[31m"); define('COLOR_GREEN', "\033[32m"); define('COLOR_YELLOW', "\033[33m"); +define('COLOR_BLUE', "\033[34m"); define('COLOR_DEFAULT', "\033[39m"); // TODO add to all Controllers error_reporting(error_level: E_ALL); -// 61e6ce5dd8a1b.bc1c314ce364f6878084c254fe4c6345801c43a49bb8eb71 use LucidFrame\Console\ConsoleTable; use UnhandledMatchError; @@ -37,18 +37,93 @@ class BindAPI $this->databaseConnection = new DatabaseConnection(config: $this->config); $this->panelController = new PanelController($this->databaseConnection); $this->apiUsers = new ApiKeys($this->databaseConnection); - $this->domainController = new DomainController($this->databaseConnection); + $this->domainController = new DomainController($this->databaseConnection, $this->panelController); $this->nameserverController = new NameserverController($this->databaseConnection); $this->checkController = new CheckController(); } + /** + * @return int|void + */ + public function getId() + { + if (!empty($this->arguments[1])) { + $id = intval(value: $this->arguments[1] ?? 0); + + if ($id != $this->arguments[1]) { + echo 'ID has to be a number.' . PHP_EOL; + exit(1); + } + } else { + $id = 0; + } + return $id; + } + + /** + * @param bool|array $panel + * + * @return bool + */ + public function checkNSPing(bool|array $nameserver): Bool + { + $maxName = $this->nameserverController->getLongestEntry(field: 'name'); + $maxA = $this->nameserverController->getLongestEntry(field: 'a'); + $maxAAAA = $this->nameserverController->getLongestEntry(field: 'aaaa'); + + $error = false; + + if ($this->config['verbose']) { + print(COLOR_YELLOW . str_pad(string: $nameserver['name'], length: $maxName)); + } + + $a = $nameserver['a'] ?? ''; + if (!empty($a)) { + if ($this->config['verbose']) { + echo COLOR_DEFAULT . ' ' . str_pad(string: $a, length: $maxA, pad_type: STR_PAD_LEFT) . ' '; + } + if ($result = $this->checkController->sendCommand(serverName: $nameserver['name'], versionIP: 4, apiKey: $nameserver['apikey'], command: 'ping', type: 'nameserver')) { + if ($this->config['verbose']) { + if ($result == 'pong') { + echo COLOR_GREEN . $result; + } else { + echo COLOR_BLUE . $result; // TODO 'skip'; + } + } + } else { + $error = true; + } + } + $aaaa = $nameserver['aaaa'] ?? ''; + if (!empty($aaaa)) { + if ($this->config['verbose']) { + echo COLOR_DEFAULT . ' ' . str_pad(string: $aaaa, length: $maxAAAA, pad_type: STR_PAD_LEFT) . ' '; + } + if ($result = $this->checkController->sendCommand(serverName: $nameserver['name'], versionIP: 6, apiKey: $nameserver['apikey'], command: 'ping', type: 'nameserver')) { + if ($this->config['verbose']) { + if ($result == 'pong') { + echo COLOR_GREEN . $result; + } else { + echo COLOR_BLUE . $result; // TODO 'skip'; + } + } + } else { + $error = true; + } + } + if ($this->config['verbose']) { + echo PHP_EOL; + } + return $error; + } + /** * @param bool|array $panel * * @return bool */ - public function checkPing(bool|array $panel): Bool + public function checkPanelPing(bool|array $panel): Bool { $maxName = $this->panelController->getLongestEntry(field: 'name'); $maxA = $this->panelController->getLongestEntry(field: 'a'); @@ -65,12 +140,12 @@ class BindAPI if ($this->config['verbose']) { echo COLOR_DEFAULT . ' ' . str_pad(string: $a, length: $maxA, pad_type: STR_PAD_LEFT) . ' '; } - if ($result = $this->checkController->sendCommand(serverName: $panel['name'], versionIP: 4, apiKey: $panel['apikey'], command: 'ping')) { + if ($result = $this->checkController->sendPanelCommand(serverName: $panel['name'], versionIP: 4, apiKey: $panel['apikey'], command: 'ping')) { if ($this->config['verbose']) { if ($result == 'pong') { echo COLOR_GREEN . $result; } else { - echo COLOR_RED . $result; + echo COLOR_BLUE . 'skip'; } } } else { @@ -80,14 +155,14 @@ class BindAPI $aaaa = $panel['aaaa'] ?? ''; if (!empty($aaaa)) { if ($this->config['verbose']) { - echo COLOR_DEFAULT . ' ' . str_pad(string: $aaaa, length: $maxAAAA, pad_type: STR_PAD_LEFT); + echo COLOR_DEFAULT . ' ' . str_pad(string: $aaaa, length: $maxAAAA, pad_type: STR_PAD_LEFT) . ' '; } - if ($result = $this->checkController->sendCommand(serverName: $panel['name'], versionIP: 6, apiKey: $panel['apikey'], command: 'ping')) { + if ($result = $this->checkController->sendPanelCommand(serverName: $panel['name'], versionIP: 6, apiKey: $panel['apikey'], command: 'ping')) { if ($this->config['verbose']) { if ($result == 'pong') { echo COLOR_GREEN . $result; } else { - echo COLOR_RED . $result; + echo COLOR_BLUE . 'skip'; } } } else { @@ -103,22 +178,101 @@ class BindAPI function handleChecks(String $subcommand) { - print("hable"); try { match ($subcommand) { 'permissions' => $this->handleCheckPermissions(), + 'panels' => $this->handleCheckPanels(), }; } catch (UnhandledMatchError) { echo 'Unknown action: ' . $subcommand . PHP_EOL; } } + + /** + * @param String $domain + * + * @return bool|void + */ + function checkNS(String $domain) + { + $nameServers = $this->nameserverController->findAll(); + $i = 1; + foreach($nameServers as $nameServer) { + print("nameserver $i"); + $i++; + if (!empty($nameServer['aaaa'])) { + $result = $this->checkController->sendCommand(serverName: $nameServer['name'], + versionIP: 6, + apiKey: $nameServer['apikey'], + command: 'domains/' . $domain, + type: 'nameserver'); + } else { + $result = $this->checkController->sendCommand(serverName: $nameServer['name'], + versionIP: 4, + apiKey: $nameServer['apikey'], + command: 'domains', + type: 'nameserver' . $domain); + } + if ($result['header'] == 200) { + print("OK"); + } else { + print("missing"); + } + } + echo PHP_EOL; + } + + + function handleCheckPanels() + { + $id = $this->getId(); + $maxDomain = $this->panelController->getLongestEntry(field:'name'); + + print("$maxDomain"); + die(); + + if ($id != 0) { + if ($panel = $this->panelController->findByID($id)) { + if (!empty($panel['aaaa'])) { + $result = $this->checkController->sendCommand(serverName: $panel['name'], + versionIP: 6, + apiKey: $panel['apikey'], + command: 'domains', + type: 'panel'); + } else { + $result = $this->checkController->sendCommand(serverName: $panel['name'], + versionIP: 4, + apiKey: $panel['apikey'], + command: 'domains', + type: 'panel'); + } + + $domains = json_decode($result['data']); + foreach ($domains as $domain) { + if ($domain->id_parent_domain == 0 && !str_contains(haystack: $domain->domain, needle: $panel['name'])) { + echo PHP_EOL . COLOR_DEFAULT . "check: " . COLOR_YELLOW . str_pad($domain->domain, $maxDomain); + if ($this->checkNS($domain->domain)) { + echo COLOR_GREEN . ' OK'; + } else { + echo COLOR_RED . 'Missing'; + } + } + } + } else { + echo "Unknown Panel ID: $id" . PHP_EOL; + exit(1); + } + } + } + + function handleCheckPermissions() { - $test = fgets(stream: STDIN); - echo "received: $test" . PHP_EOL; + $this->domainController->checkPermissions(); } + function runCommand() { if ($this->argumentsCount < 1) { @@ -152,11 +306,17 @@ class BindAPI */ function showUsage(): void { - echo 'Usage' . PHP_EOL; + echo COLOR_YELLOW . 'Usage:' . PHP_EOL; + echo COLOR_DEFAULT . "\t./bin/console {options} {arguments}" . PHP_EOL . PHP_EOL; + + echo COLOR_YELLOW . 'Options:' . PHP_EOL; + echo COLOR_GREEN . "\t-v, --version\t\t" . COLOR_DEFAULT . "Display the version of the API" . PHP_EOL; + echo COLOR_GREEN . "\t-V, --verbose\t\t" . COLOR_DEFAULT . "All :list command are auto-verbose" . PHP_EOL . PHP_EOL; + echo COLOR_YELLOW . "check" . COLOR_DEFAULT . "\t health checks the system can perform" . PHP_EOL; echo COLOR_GREEN . "\t check:permissions" . PHP_EOL; - echo COLOR_GREEN . "\t check:panels {ID}" . PHP_EOL; - echo COLOR_GREEN . "\t check:domains {ID}" . PHP_EOL; + echo COLOR_GREEN . "\t check:panels {ID} {fix}" . PHP_EOL; + echo COLOR_GREEN . "\t check:domains {ID} {fix}" . PHP_EOL; echo COLOR_YELLOW . "panels" . COLOR_DEFAULT . "\t all Keyhelp systems configured" . PHP_EOL; echo COLOR_GREEN . "\t panels:list" . PHP_EOL; @@ -168,7 +328,7 @@ class BindAPI echo COLOR_YELLOW . "nameservers" . COLOR_DEFAULT . " available nameservers" . PHP_EOL; echo COLOR_GREEN . "\t nameservers:list" . PHP_EOL; echo COLOR_GREEN . "\t nameservers:create {A=} {AAAA=} {apikey=}" . PHP_EOL; - echo COLOR_GREEN . "\t nameservers:update {name=} {A=} {AAAA=} {apikey=}" . PHP_EOL; + echo COLOR_GREEN . "\t nameservers:update {name=} {panel_id=} {A=} {AAAA=} {apikey=}" . PHP_EOL; echo COLOR_GREEN . "\t nameservers:delete " . PHP_EOL; echo COLOR_GREEN . "\t nameservers:apiping {}" . PHP_EOL; @@ -180,8 +340,8 @@ class BindAPI echo COLOR_YELLOW . "apikeys" . COLOR_DEFAULT . "\t API keys for other nameservers" . PHP_EOL; echo COLOR_GREEN . "\t apikeys:list" . PHP_EOL; - echo COLOR_GREEN . "\t apikeys:create" . PHP_EOL; - echo COLOR_GREEN . "\t apikeys:update " . PHP_EOL; + echo COLOR_GREEN . "\t apikeys:create {name=}" . PHP_EOL; + echo COLOR_GREEN . "\t apikeys:update name=" . PHP_EOL; echo COLOR_GREEN . "\t apikeys:delete " . PHP_EOL; echo PHP_EOL . "\033[39me.g. ./bin/console apikeys:list" . PHP_EOL; @@ -201,6 +361,8 @@ class BindAPI 'list' => $this->handleNameserversList(), 'update' => $this->handleNameserversUpdate(), 'delete' => $this->handleNameserversDelete(), + 'apiping' => $this->handleNameserversAPIPing(), + }; } catch (UnhandledMatchError) { echo 'Unknown action: ' . $subcommand . PHP_EOL; @@ -229,15 +391,70 @@ class BindAPI } + function handleNameserversAPIPing() + { + // TODO get apikey from stdin + //$test = fgets(stream: STDIN); + //echo "received: $test" . PHP_EOL; + + $error = false; + + if (!empty($this->arguments[1])) { + $id = intval(value:$this->arguments[1] ?? 0); + + if ($id != $this->arguments[1]) { + echo 'ID has to be a number.' . PHP_EOL; + exit(1); + } + } else { + $id = 0; + } + + if ($id != 0) { + if ($nameserver = $this->nameserverController->findByID($id)) { + if (!$this->checkNSPing($nameserver)) { + $error = true; + } + } else { + if ($this->config['verbose']) { + echo 'Unknown panel ID: $id' . PHP_EOL; + } + $error = true; + } + } else { + $nameservers = $this->nameserverController->findAll(); + foreach ($nameservers as $nameserver) { + if (!$this->checkNSPing(nameserver: $nameserver)) { + $error = true; + } + } + } + echo PHP_EOL; + if ($error) { + exit(1); + } else { + exit(0); + } + } + + + function handlePanelsAPIPing() { $error = false; - $id = $this->arguments[1] ?? 0; - + if (!empty($this->arguments[1])) { + $id = intval(value: $this->arguments[1] ?? 0); + if ($id != $this->arguments[1]) { + echo 'ID has to be a number.' . PHP_EOL; + exit(1); + } + } else { + $id = 0; + } if ($id != 0) { if ($panel = $this->panelController->findByID($id)) { - if (!$this->checkPing($panel)) { + if (!$this->checkPanelPing($panel)) { $error = true; } } else { @@ -249,7 +466,7 @@ class BindAPI } else { $panels = $this->panelController->findAll(); foreach ($panels as $panel) { - if (!$this->checkPing(panel: $panel)) { + if (!$this->checkPanelPing(panel: $panel)) { $error = true; } } @@ -449,7 +666,10 @@ class BindAPI */ function handleApikeysCreate(): void { - $result = $this->apiUsers->create(); + $arguments = $this->parseArguments(); + $name = $arguments['name'] ?? ''; + + $result = $this->apiUsers->create(name: $name); echo 'API key ' . $result['row'] . ' has been generated. Store it in a save place, it cannot be recovered.' . PHP_EOL; echo "\033[32m\t" . $result['tokenPrefix'] . '.' . $result['key'] . PHP_EOL; exit(0); @@ -481,7 +701,7 @@ class BindAPI */ function handleApikeysDelete(): void { - $id = intval($this->arguments[1]) ?? 0; + $id = intval(value: $this->arguments[1] ?? 0); if ($id == 0) { echo 'You need to add the ID of the API key.' . PHP_EOL; exit(1); @@ -527,7 +747,8 @@ class BindAPI $table = new ConsoleTable(); $table->setHeaders(['ID', 'Name', 'A', 'AAAA', 'API Key']); foreach ($domains as $domain) { - $table->addRow([$domain['id'], $domain['name'], $domain['a'], $domain['aaaa'], $domain['apikey']]); + $token = strtok(string: $domain['apikey'], token: '.'); + $table->addRow([$domain['id'], $domain['name'], $domain['a'], $domain['aaaa'], $token]); } $table->setPadding(value: 2); $table->display(); @@ -548,9 +769,9 @@ class BindAPI $domains = $this->domainController->findAll(); if ($domains) { $table = new ConsoleTable(); - $table->setHeaders(['ID', 'Name', 'A', 'AAAA']); + $table->setHeaders(['ID', 'Name', 'Panel', 'A', 'AAAA']); foreach ($domains as $domain) { - $table->addRow([$domain['id'], $domain['name'], $domain['a'], $domain['aaaa']]); + $table->addRow([$domain['id'], $domain['name'], $domain['panel_id'], $domain['a'], $domain['aaaa']]); } $table->setPadding(value: 2); $table->display(); @@ -584,8 +805,10 @@ class BindAPI $a = $arguments['a'] ?? ""; $aaaa = $arguments['aaaa'] ?? ""; - if (empty($a) && empty($aaaa)) { - echo 'At least one IP address is required.' . PHP_EOL; + $panelID = $arguments['panel_id'] ?? 0; + + if (empty($a) && empty($aaaa) && empty($panelID)) { + echo 'At least one IP address or panel ID is required.' . PHP_EOL; exit(0); } @@ -593,7 +816,7 @@ class BindAPI echo "Domain: $name already exists." . PHP_EOL; exit(1); } else { - $result = $this->domainController->insert($name, $a, $aaaa); + $result = $this->domainController->insert($name, $panelID, $a, $aaaa); echo "Domain $name has been created with id $result" . PHP_EOL; exit(0); } @@ -605,6 +828,8 @@ class BindAPI $id = $this->arguments[1] ?? 0; $name = $arguments['name'] ?? ''; + print_r($arguments); //findme + $panelID = intval(value: $arguments['panel_id'] ?? 0); $a = $arguments['a'] ?? ''; $aaaa = $arguments['aaaa'] ?? ''; @@ -616,7 +841,7 @@ class BindAPI echo "Domain with ID : $id doesn't exist." . PHP_EOL; exit(1); } - if ($this->domainController->update($id, $name, $a, $aaaa) !== false) { + if ($this->domainController->update($id, $name, $panelID, $a, $aaaa) !== false) { echo 'Domain server has been updated' . PHP_EOL; } else { echo 'Error while updating domain server.' . PHP_EOL;