Compare commits

...

9 Commits

15 changed files with 3541 additions and 525 deletions

7
TODO
View File

@ -1,6 +1,7 @@
b4 cron job: check panel, check nameserver1
check log file location
API Endpoint cleanup API Endpoint cleanup
check keytype of panel/bindApi check keytype of panel
check keytype of 1bindApi
check:configkey => update config.json
more UNIT tests more UNIT tests

View File

@ -10,11 +10,11 @@ if (php_sapi_name() !== 'cli') {
// check php version (must be >= 8.1) // check php version (must be >= 8.1)
/** @noinspection PhpArgumentWithoutNamedIdentifierInspection */ /** @noinspection PhpArgumentWithoutNamedIdentifierInspection */
if (version_compare(PHP_VERSION, '8.1.0', '<')) { if (version_compare(PHP_VERSION, '8.2.0', '<')) {
echo 'This application requires PHP 8.1 or newer. You are running ' . PHP_VERSION . PHP_EOL; echo 'This application requires PHP 8.2 or newer. You are running ' . PHP_VERSION . PHP_EOL;
echo 'If you are using KeyHelp, use keyhelp-php81 ' . $argv[0] . ' instead.' . PHP_EOL; echo 'If you are using KeyHelp, use keyhelp-php82 ' . $argv[0] . ' instead.' . PHP_EOL;
exit; exit;
} }
/** @noinspection PhpArgumentWithoutNamedIdentifierInspection */ /** @noinspection PhpArgumentWithoutNamedIdentifierInspection */
require dirname(__DIR__, 1) . '/src/Util/Console.php'; require dirname(__DIR__, 1) . '/src/Utilities/Console.php';

View File

@ -1,8 +1,8 @@
{ {
"name": "24unix/bindapi", "name": "tracer/bindapi",
"description": "manage Bind9 DNS server via REST API", "description": "manage Bind9 client zones for KeyHelp",
"version": "1.0.9", "version": "1.1.2",
"build_number": "374", "build_number": "380",
"authors": [ "authors": [
{ {
"name": "Micha Espey", "name": "Micha Espey",
@ -23,6 +23,7 @@
"ext-posix": "*", "ext-posix": "*",
"ext-sodium": "*", "ext-sodium": "*",
"arubacao/tld-checker": "^1.2", "arubacao/tld-checker": "^1.2",
"bartlett/php-compatinfo": "^7.1",
"monolog/monolog": "^3.1", "monolog/monolog": "^3.1",
"netresearch/jsonmapper": "^4.4", "netresearch/jsonmapper": "^4.4",
"php-di/php-di": "^6.3", "php-di/php-di": "^6.3",

2993
composer.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -1,9 +1,10 @@
{ {
"env": "prod",
"dbHost": "localhost", "dbHost": "localhost",
"dbPort": 3306, "dbPort": 3306,
"dbDatabase": "sampledb", "dbDatabase": "sampledb",
"dbUser": "sampleuser", "dbUser": "sampleuser",
"dbPassword": "secret", "dbPassword": "secret",
"encryptionKey": "changeme", "encryptionKey": "1bad::babe",
"debug": false "debug": false
} }

File diff suppressed because it is too large Load Diff

View File

@ -2,6 +2,8 @@
namespace App\Controller\Commands; namespace App\Controller\Commands;
use App\Utilities\Colors;
/** /**
* *
*/ */
@ -31,17 +33,17 @@ class CommandGroup
public function printCommands(int $longestCommandLength): void public function printCommands(int $longestCommandLength): void
{ {
echo COLOR_YELLOW . str_pad(string: $this->name, length: $longestCommandLength + 1) . COLOR_WHITE . $this->description . COLOR_DEFAULT . PHP_EOL; echo Colors::YELLOW . str_pad(string: $this->name, length: $longestCommandLength + 1) . Colors::WHITE . $this->description . Colors::DEFAULT . PHP_EOL;
foreach ($this->commands as $command) { foreach ($this->commands as $command) {
echo COLOR_GREEN . str_pad(string: ' ', length: $longestCommandLength + 1, pad_type: STR_PAD_LEFT) . $this->name . ':' . $command->getName(); echo Colors::GREEN . str_pad(string: ' ', length: $longestCommandLength + 1, pad_type: STR_PAD_LEFT) . $this->name . ':' . $command->getName();
foreach ($command->getMandatoryParameters() as $optionals) { foreach ($command->getMandatoryParameters() as $optionals) {
echo ' <' . $optionals . '>'; echo ' <' . $optionals . '>';
} }
foreach ($command->getOptionalParameters() as $mandatory) { foreach ($command->getOptionalParameters() as $mandatory) {
echo ' {' . $mandatory . '}'; echo ' {' . $mandatory . '}';
} }
echo COLOR_WHITE . ' ' . $command->getDescription(); echo Colors::WHITE . ' ' . $command->getDescription();
echo COLOR_DEFAULT . PHP_EOL; echo Colors::DEFAULT . PHP_EOL;
} }
} }

View File

@ -2,6 +2,8 @@
namespace App\Controller\Commands; namespace App\Controller\Commands;
use App\Utilities\Colors;
/** /**
* *
*/ */
@ -64,23 +66,23 @@ class CommandGroupContainer
if ($group->exec(subcommand: $subcommand)) { if ($group->exec(subcommand: $subcommand)) {
exit(0); exit(0);
} else { } else {
echo COLOR_DEFAULT . 'Unknown subcommand ' . COLOR_YELLOW . $subcommand . COLOR_DEFAULT .' for ' . COLOR_YELLOW . $command . COLOR_DEFAULT . '.' . PHP_EOL; echo Colors::DEFAULT . 'Unknown subcommand ' . Colors::YELLOW . $subcommand . Colors::DEFAULT .' for ' . Colors::YELLOW . $command . Colors::DEFAULT . '.' . PHP_EOL;
exit(1); exit(1);
} }
} else { } else {
echo COLOR_DEFAULT . 'Unknown command group ' . COLOR_YELLOW . $command . COLOR_DEFAULT . '.' . PHP_EOL; echo Colors::DEFAULT . 'Unknown command group ' . Colors::YELLOW . $command . Colors::DEFAULT . '.' . PHP_EOL;
exit(1); exit(1);
} }
} else { } else {
// check for command group and print available commands // check for command group and print available commands
foreach ($this->commandGroups as $group) { foreach ($this->commandGroups as $group) {
if ($group->getName() === $command) { if ($group->getName() === $command) {
echo 'Available subcommands for: ' . COLOR_YELLOW . $group->getName() . COLOR_DEFAULT . ':' . PHP_EOL; echo 'Available subcommands for: ' . Colors::YELLOW . $group->getName() . Colors::DEFAULT . ':' . PHP_EOL;
$group->printCommands(strlen(string: $group->getName())); $group->printCommands(strlen(string: $group->getName()));
exit(0); exit(0);
} }
} }
} }
echo COLOR_DEFAULT . 'Unknown command ' . COLOR_YELLOW . $command . COLOR_DEFAULT . '.' . PHP_EOL; echo Colors::DEFAULT . 'Unknown command ' . Colors::YELLOW . $command . Colors::DEFAULT . '.' . PHP_EOL;
} }
} }

View File

@ -2,11 +2,14 @@
namespace App\Controller; namespace App\Controller;
use App\Utilities\Colors;
class ConfigController class ConfigController
{ {
private array $config; private array $config;
private static $missingEncryptionShown = false;
public function __construct(bool $quiet, bool $test = false) public function __construct(private readonly bool $quiet, bool $test = false)
{ {
if ($test) { if ($test) {
@ -35,21 +38,33 @@ class ConfigController
} }
$configJSON = file_get_contents(filename: $configFile); $configJSON = file_get_contents(filename: $configFile);
if (json_decode(json: $configJSON) === null) { // first check if json is valid, after make the assignment
if (json_decode(json: $configJSON, associative: true) === null) {
echo 'Config file is not valid JSON.' . PHP_EOL; echo 'Config file is not valid JSON.' . PHP_EOL;
echo $configJSON . PHP_EOL; echo $configJSON . PHP_EOL;
exit(1); exit(1);
} }
$this->config = json_decode(json: $configJSON, associative: true); $this->config = json_decode(json: $configJSON, associative: true);
if (!ConfigController::$missingEncryptionShown) {
$this->config['quiet'] = (bool)$quiet; if (!isset($this->config['encryptionKey']) || ($this->config['encryptionKey'] === '1bad::babe')) {
$this->config['test'] = (bool)$test; ConfigController::$missingEncryptionShown = true;
if (!$this->quiet) {
echo Colors::RED . 'Error: ' . Colors::DEFAULT . 'No encryption key, please run ' . Colors::YELLOW . './bin/console check:generatekey' . Colors::DEFAULT . PHP_EOL;
}
exit(1);
}
} }
public function getConfig(string $configKey): string }
public function getConfig(string $configKey): ?string
{ {
if (isset($this->config[$configKey])) {
return $this->config[$configKey]; return $this->config[$configKey];
} else {
return null;
}
} }
} }

View File

@ -7,6 +7,7 @@ use App\Repository\DomainRepository;
use App\Repository\NameserverRepository; use App\Repository\NameserverRepository;
use App\Repository\PanelRepository; use App\Repository\PanelRepository;
use App\Service\ApiClient; use App\Service\ApiClient;
use App\Utilities\Colors;
use Monolog\Logger; use Monolog\Logger;
error_reporting(error_level: E_ALL); error_reporting(error_level: E_ALL);
@ -82,13 +83,13 @@ class DomainController
foreach ($domains as $domain) { foreach ($domains as $domain) {
$zoneFile = $this->localZonesDir . $domain->getName(); $zoneFile = $this->localZonesDir . $domain->getName();
if (!$this->quiet) { if (!$this->quiet) {
echo ' ' . COLOR_YELLOW . str_pad(string: $domain->getName(), length: $longestEntry + 1, pad_string: " ", pad_type: STR_PAD_RIGHT) ; echo ' ' . Colors::YELLOW . str_pad(string: $domain->getName(), length: $longestEntry + 1, pad_string: " ", pad_type: STR_PAD_RIGHT) ;
} }
if (strcmp(string1: $self->getName(), string2: $domain->getPanel()) !== 0) { if (strcmp(string1: $self->getName(), string2: $domain->getPanel()) !== 0) {
if (!file_exists(filename: $zoneFile)) { if (!file_exists(filename: $zoneFile)) {
if (!$this->quiet) { if (!$this->quiet) {
echo COLOR_GREEN . ' OK' . COLOR_DEFAULT . PHP_EOL; echo Colors::GREEN . ' OK' . Colors::DEFAULT . PHP_EOL;
} }
$this->createSlaveZoneFile(domain: $domain); $this->createSlaveZoneFile(domain: $domain);
} else { } else {
@ -100,19 +101,19 @@ class DomainController
echo 'missing value: ' . $zoneFile; echo 'missing value: ' . $zoneFile;
} }
if (!$this->quiet) { if (!$this->quiet) {
echo COLOR_DEFAULT . 'Zone already exists.' . PHP_EOL; echo Colors::DEFAULT . 'Zone already exists.' . PHP_EOL;
} }
} }
} else { } else {
if (!$this->quiet) { if (!$this->quiet) {
echo COLOR_DEFAULT . 'We are master for ' . COLOR_YELLOW . $domain->getName() . PHP_EOL; echo Colors::DEFAULT . 'We are master for ' . Colors::YELLOW . $domain->getName() . PHP_EOL;
} }
} }
} }
// remove stale zones // remove stale zones
foreach ($existingZones as $zone) { foreach ($existingZones as $zone) {
if (!$this->quiet) { if (!$this->quiet) {
echo 'Removing stale zone: ' . COLOR_YELLOW . $zone . COLOR_DEFAULT . PHP_EOL; echo 'Removing stale zone: ' . Colors::YELLOW . $zone . Colors::DEFAULT . PHP_EOL;
} }
echo $zone . PHP_EOL; echo $zone . PHP_EOL;
unlink(filename: $zone); unlink(filename: $zone);
@ -190,12 +191,12 @@ class DomainController
$uid = posix_geteuid(); $uid = posix_geteuid();
} }
if (!$this->quiet) { if (!$this->quiet) {
echo "UID:\t" . COLOR_YELLOW . $uid . PHP_EOL; echo "UID:\t" . Colors::YELLOW . $uid . PHP_EOL;
} }
$pwuid = posix_getpwuid(user_id: $uid); $pwuid = posix_getpwuid(user_id: $uid);
$name = $pwuid['name']; $name = $pwuid['name'];
if (!$this->quiet) { if (!$this->quiet) {
echo COLOR_DEFAULT . "Name:\t" . COLOR_YELLOW . $name . PHP_EOL; echo Colors::DEFAULT . "Name:\t" . Colors::YELLOW . $name . PHP_EOL;
} }
if (!$bindGroup = posix_getgrnam(name: 'bind')) { if (!$bindGroup = posix_getgrnam(name: 'bind')) {
@ -204,40 +205,40 @@ class DomainController
$members = $bindGroup['members'] ?? []; $members = $bindGroup['members'] ?? [];
if (in_array(needle: $name, haystack: $members)) { if (in_array(needle: $name, haystack: $members)) {
if (!$this->quiet) { if (!$this->quiet) {
echo "\t$name" . COLOR_DEFAULT . ' is in group ' . COLOR_YELLOW . 'bind' . PHP_EOL; echo "\t$name" . Colors::DEFAULT . ' is in group ' . Colors::YELLOW . 'bind' . PHP_EOL;
} }
} else { } else {
$setupIsValid = false; $setupIsValid = false;
if (!$this->quiet) { if (!$this->quiet) {
echo COLOR_RED . "\t$name needs to be in group " . COLOR_YELLOW . 'bind' . COLOR_DEFAULT . '!' . PHP_EOL; echo Colors::RED . "\t$name needs to be in group " . Colors::YELLOW . 'bind' . Colors::DEFAULT . '!' . PHP_EOL;
} }
} }
if (!$this->quiet) { if (!$this->quiet) {
echo COLOR_DEFAULT . 'Checking ' . COLOR_YELLOW . $this->localZoneFile . PHP_EOL; echo Colors::DEFAULT . 'Checking ' . Colors::YELLOW . $this->localZoneFile . PHP_EOL;
} }
$localZoneFilePermissions = @fileperms(filename: $this->localZoneFile); $localZoneFilePermissions = @fileperms(filename: $this->localZoneFile);
if ($localZoneFilePermissions & 0x0010) { if ($localZoneFilePermissions & 0x0010) {
if (!$this->quiet) { if (!$this->quiet) {
echo COLOR_DEFAULT . "\t✅ Group has write access." . PHP_EOL; echo Colors::DEFAULT . "\t✅ Group has write access." . PHP_EOL;
} }
} else { } else {
$setupIsValid = false; $setupIsValid = false;
if (!$this->quiet) { if (!$this->quiet) {
echo COLOR_RED . "\t❌Group needs write permission!" . COLOR_DEFAULT . PHP_EOL; echo Colors::RED . "\t❌Group needs write permission!" . Colors::DEFAULT . PHP_EOL;
} }
} }
if (!$this->quiet) { if (!$this->quiet) {
echo 'Checking ' . COLOR_YELLOW . $this->namedConfLocalFile . PHP_EOL; echo 'Checking ' . Colors::YELLOW . $this->namedConfLocalFile . PHP_EOL;
} }
if (file_exists(filename: $this->namedConfLocalFile) && $namedConfLocal = file_get_contents(filename: $this->namedConfLocalFile)) { if (file_exists(filename: $this->namedConfLocalFile) && $namedConfLocal = file_get_contents(filename: $this->namedConfLocalFile)) {
if (!str_contains(haystack: $namedConfLocal, needle: $this->localZoneFile)) { if (!str_contains(haystack: $namedConfLocal, needle: $this->localZoneFile)) {
$setupIsValid = false; $setupIsValid = false;
if (!$this->quiet) { if (!$this->quiet) {
echo "\t$this->localZoneFile" . COLOR_RED . ' needs to be included in ' . COLOR_YELLOW . $this->namedConfLocalFile . PHP_EOL; echo "\t$this->localZoneFile" . Colors::RED . ' needs to be included in ' . Colors::YELLOW . $this->namedConfLocalFile . PHP_EOL;
} }
} else { } else {
if (!$this->quiet) { if (!$this->quiet) {
echo "\t$this->localZoneFile" . COLOR_DEFAULT . ' is included in ' . COLOR_YELLOW . $this->namedConfLocalFile . PHP_EOL; echo "\t$this->localZoneFile" . Colors::DEFAULT . ' is included in ' . Colors::YELLOW . $this->namedConfLocalFile . PHP_EOL;
} }
} }
} else { } else {
@ -247,7 +248,7 @@ class DomainController
} }
} }
if (!$this->quiet) { if (!$this->quiet) {
echo COLOR_DEFAULT . 'Checking directory: ' . COLOR_YELLOW . $this->localZonesDir . PHP_EOL; echo Colors::DEFAULT . 'Checking directory: ' . Colors::YELLOW . $this->localZonesDir . PHP_EOL;
} }
$localZoneDirPermissions = @fileperms(filename: $this->localZonesDir); $localZoneDirPermissions = @fileperms(filename: $this->localZonesDir);
if ($localZoneDirPermissions & 0x0010) { if ($localZoneDirPermissions & 0x0010) {
@ -257,7 +258,7 @@ class DomainController
} else { } else {
$setupIsValid = false; $setupIsValid = false;
if (!$this->quiet) { if (!$this->quiet) {
echo COLOR_RED . "\t❌Group needs write permission!" . PHP_EOL; echo Colors::RED . "\t❌Group needs write permission!" . PHP_EOL;
} }
} }
return $setupIsValid; return $setupIsValid;
@ -271,7 +272,7 @@ class DomainController
{ {
if (!file_exists(filename: $this->localZoneFile)) { if (!file_exists(filename: $this->localZoneFile)) {
if (!$this->quiet) { if (!$this->quiet) {
echo COLOR_DEFAULT . 'Local Zone file ' . COLOR_YELLOW . $this->localZoneFile . COLOR_DEFAULT . ' does not exist.' . PHP_EOL; echo Colors::DEFAULT . 'Local Zone file ' . Colors::YELLOW . $this->localZoneFile . Colors::DEFAULT . ' does not exist.' . PHP_EOL;
} }
exit(1); exit(1);
} }
@ -282,33 +283,33 @@ class DomainController
foreach ($domains as $domain) { foreach ($domains as $domain) {
$idString = '(' . $domain->getId() . ') '; $idString = '(' . $domain->getId() . ') ';
if (!$this->quiet) { if (!$this->quiet) {
echo COLOR_YELLOW . echo Colors::YELLOW .
str_pad(string: $domain->getName(), length: $maxNameLength + 1) str_pad(string: $domain->getName(), length: $maxNameLength + 1)
. COLOR_DEFAULT . Colors::DEFAULT
. str_pad(string: $idString, length: 7, pad_type: STR_PAD_LEFT); . str_pad(string: $idString, length: 7, pad_type: STR_PAD_LEFT);
} }
$hasError = false; $hasError = false;
if ($this->isMasterZone(domain: $domain)) { if ($this->isMasterZone(domain: $domain)) {
if (!$this->quiet) { if (!$this->quiet) {
echo COLOR_GREEN . 'Master Zone'; echo Colors::GREEN . 'Master Zone';
} }
} else { } else {
if (!str_contains(haystack: $localZones, needle: $domain->getName())) { if (!str_contains(haystack: $localZones, needle: $domain->getName())) {
if (!$this->quiet) { if (!$this->quiet) {
echo COLOR_RED . 'is missing in ' . COLOR_YELLOW . $this->localZoneFile . COLOR_DEFAULT; echo Colors::RED . 'is missing in ' . Colors::YELLOW . $this->localZoneFile . Colors::DEFAULT;
} }
$hasError = true; $hasError = true;
} else { } else {
if (!$this->quiet) { if (!$this->quiet) {
echo COLOR_GREEN . 'OK'; echo Colors::GREEN . 'OK';
} }
} }
$zoneFile = $this->localZonesDir . $domain->getName(); $zoneFile = $this->localZonesDir . $domain->getName();
if (!file_exists(filename: $zoneFile)) { if (!file_exists(filename: $zoneFile)) {
echo ' Missing zone file for ' . COLOR_YELLOW . $zoneFile . COLOR_DEFAULT; echo ' Missing zone file for ' . Colors::YELLOW . $zoneFile . Colors::DEFAULT;
$hasError = true; $hasError = true;
} }
@ -317,7 +318,7 @@ class DomainController
} }
} }
if (!$this->quiet) { if (!$this->quiet) {
echo COLOR_DEFAULT . PHP_EOL; echo Colors::DEFAULT . PHP_EOL;
} }
} }
@ -367,7 +368,7 @@ class DomainController
return true; return true;
} else { } else {
if (!$this->quiet) { if (!$this->quiet) {
echo COLOR_RED . ' Error: ' . COLOR_DEFAULT . 'unable to create ' . COLOR_YELLOW . $this->localZonesDir . $domainName . COLOR_DEFAULT . PHP_EOL; echo Colors::RED . ' Error: ' . Colors::DEFAULT . 'unable to create ' . Colors::YELLOW . $this->localZonesDir . $domainName . Colors::DEFAULT . PHP_EOL;
} }
return false; return false;
} }

View File

@ -58,7 +58,7 @@ class EncryptionController
$plain = sodium_crypto_secretbox_open(ciphertext: $ciphertext, nonce: $nonce, key: $binKey); $plain = sodium_crypto_secretbox_open(ciphertext: $ciphertext, nonce: $nonce, key: $binKey);
if ($plain === false) { if ($plain === false) {
throw new Exception(message: ' Incorrect key.'); throw new Exception(message: ' Incorrect key.' . PHP_EOL);
} }
sodium_memzero(string: $ciphertext); sodium_memzero(string: $ciphertext);
sodium_memzero(string: $key); sodium_memzero(string: $key);

View File

@ -15,6 +15,19 @@ class Security
private bool $hstsInclude; private bool $hstsInclude;
private bool $hstsPreload; private bool $hstsPreload;
private bool $isPreferHttps;
public function isPreferHttps(): bool
{
return $this->isPreferHttps;
}
public function setIsPreferHttps(bool $isPreferHttps): void
{
$this->isPreferHttps = $isPreferHttps;
}
/** /**
* @return int * @return int
*/ */

View File

@ -5,6 +5,7 @@ namespace App\Provider;
//error_reporting(error_level: E_ALL); //error_reporting(error_level: E_ALL);
use App\Utilities\Colors;
use PDO; use PDO;
use PDOException; use PDOException;
use PHPUnit\Exception; use PHPUnit\Exception;
@ -27,11 +28,29 @@ class DatabaseConnection
public function __construct(private readonly ConfigController $configController) public function __construct(private readonly ConfigController $configController)
{ {
$dbHost = $this->configController->getConfig(configKey: 'dbHost'); $errors = [];
$dbPort = $this->configController->getConfig(configKey: 'dbPort'); if (!$dbHost = $this->configController->getConfig(configKey: 'dbHost')) {
$dbDatabase = $this->configController->getConfig(configKey: 'dbDatabase'); $errors[] = Colors::RED . 'Error: ' . Colors::DEFAULT . 'Missing config: dbHost' . PHP_EOL;
$dbUser = $this->configController->getConfig(configKey: 'dbUser'); }
$dbPassword = $this->configController->getConfig(configKey: 'dbPassword'); if (!$dbPort = $this->configController->getConfig(configKey: 'dbPort')) {
$errors[] = Colors::RED . 'Error: ' . Colors::DEFAULT . 'Missing config: dbPort}' . PHP_EOL;
}
if (!$dbDatabase = $this->configController->getConfig(configKey: 'dbDatabase')) {
$errors[] = Colors::RED . 'Error: ' . Colors::DEFAULT . 'Missing config: dbDatabase' . PHP_EOL;
}
if (!$dbUser = $this->configController->getConfig(configKey: 'dbUser')) {
$errors[] = Colors::RED . 'Error: ' . Colors::DEFAULT . 'Missing config: dbUser' . PHP_EOL;
}
if (!$dbPassword = $this->configController->getConfig(configKey: 'dbPassword')) {
$errors[] = Colors::RED . 'Error: ' . Colors::DEFAULT . 'Missing config: dbPassword' . PHP_EOL;
}
if ($errors) {
foreach ($errors as $error) {
echo $error;
}
exit(1);
}
try { try {
$this->dbConnection = new PDO( $this->dbConnection = new PDO(
@ -54,8 +73,8 @@ class DatabaseConnection
$result = $statement->fetch(); $result = $statement->fetch();
if (empty($result)) { if (empty($result)) {
// ALTER TABLE `domains` ADD `panel_id` INT NULL AFTER `id`; // ALTER TABLE `domains` ADD `panel_id` INT NULL AFTER `id`;
echo COLOR_RED . 'Error: ' . COLOR_DEFAULT . 'Cannot find tables.' . PHP_EOL; echo Colors::RED . 'Error: ' . Colors::DEFAULT . 'Cannot find tables.' . PHP_EOL;
echo 'Run the migration: ' . COLOR_YELLOW . './bin/console migrations:migrate' . COLOR_DEFAULT . PHP_EOL; echo 'Run the migration: ' . Colors::YELLOW . './bin/console migrations:migrate' . Colors::DEFAULT . PHP_EOL;
} }
} catch (PDOException $exception) { } catch (PDOException $exception) {
echo $exception->getMessage() . PHP_EOL; echo $exception->getMessage() . PHP_EOL;
@ -71,6 +90,7 @@ class DatabaseConnection
} }
} }
} }
function generatePassword(int $length = 8): string function generatePassword(int $length = 8): string
{ {
$chars = '23456789bcdfhkmnprstvzBCDFHJKLMNPRSTVZ'; $chars = '23456789bcdfhkmnprstvzBCDFHJKLMNPRSTVZ';

13
src/Utilities/Colors.php Normal file
View File

@ -0,0 +1,13 @@
<?php
namespace App\Utilities;
class Colors
{
const RED = "\033[31m";
const GREEN = "\033[32m";
const YELLOW = "\033[33m";
const BLUE = "\033[34m";
const WHITE = "\033[37m";
const DEFAULT = "\033[39m";
}

View File

@ -1,11 +1,12 @@
<?php <?php
use App\Service\BindAPI; use App\Service\BindAPI;
use App\Utilities\Colors;
error_reporting(error_level: E_ALL & ~E_DEPRECATED); error_reporting(error_level: E_ALL & ~E_DEPRECATED);
if (!is_file(filename: dirname(path: __DIR__, levels: 2) . '/vendor/autoload.php')) { if (!is_file(filename: dirname(path: __DIR__, levels: 2) . '/vendor/autoload.php')) {
echo 'Required runtime components are missing. Try running "' . COLOR_YELLOW . 'composer install' . COLOR_DEFAULT . '".' . PHP_EOL; echo 'Required runtime components are missing. Try running "' . Colors::YELLOW . 'composer install' . Colors::DEFAULT . '".' . PHP_EOL;
exit(1); exit(1);
} }