added support for Phinx and Phinx-Migration-Generator

This commit is contained in:
tracer 2024-04-13 20:35:20 +02:00
parent d62586feb0
commit fdc763ba7b
22 changed files with 4322 additions and 1972 deletions

3
.gitignore vendored
View File

@ -9,4 +9,7 @@
/reports/ /reports/
/bindAPI.test.log /bindAPI.test.log
/.phpunit.result.cache /.phpunit.result.cache
/config.json.dev
/config.json.test /config.json.test
/config.json.prod
keys.txt

View File

@ -101,6 +101,20 @@
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/property-info" /> <excludeFolder url="file://$MODULE_DIR$/vendor/symfony/property-info" />
<excludeFolder url="file://$MODULE_DIR$/vendor/netresearch/jsonmapper" /> <excludeFolder url="file://$MODULE_DIR$/vendor/netresearch/jsonmapper" />
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/deprecation-contracts" /> <excludeFolder url="file://$MODULE_DIR$/vendor/symfony/deprecation-contracts" />
<excludeFolder url="file://$MODULE_DIR$/vendor/cakephp/chronos" />
<excludeFolder url="file://$MODULE_DIR$/vendor/cakephp/core" />
<excludeFolder url="file://$MODULE_DIR$/vendor/cakephp/database" />
<excludeFolder url="file://$MODULE_DIR$/vendor/cakephp/datasource" />
<excludeFolder url="file://$MODULE_DIR$/vendor/cakephp/utility" />
<excludeFolder url="file://$MODULE_DIR$/vendor/league/container" />
<excludeFolder url="file://$MODULE_DIR$/vendor/odan/phinx-migrations-generator" />
<excludeFolder url="file://$MODULE_DIR$/vendor/psr/simple-cache" />
<excludeFolder url="file://$MODULE_DIR$/vendor/riimu/kit-phpencoder" />
<excludeFolder url="file://$MODULE_DIR$/vendor/robmorgan/phinx" />
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/config" />
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/console" />
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/filesystem" />
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/service-contracts" />
</content> </content>
<orderEntry type="inheritedJdk" /> <orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" /> <orderEntry type="sourceFolder" forTests="false" />

View File

@ -82,6 +82,20 @@
<path value="$PROJECT_DIR$/vendor/symfony/property-info" /> <path value="$PROJECT_DIR$/vendor/symfony/property-info" />
<path value="$PROJECT_DIR$/vendor/netresearch/jsonmapper" /> <path value="$PROJECT_DIR$/vendor/netresearch/jsonmapper" />
<path value="$PROJECT_DIR$/vendor/symfony/deprecation-contracts" /> <path value="$PROJECT_DIR$/vendor/symfony/deprecation-contracts" />
<path value="$PROJECT_DIR$/vendor/robmorgan/phinx" />
<path value="$PROJECT_DIR$/vendor/symfony/service-contracts" />
<path value="$PROJECT_DIR$/vendor/symfony/console" />
<path value="$PROJECT_DIR$/vendor/symfony/config" />
<path value="$PROJECT_DIR$/vendor/symfony/filesystem" />
<path value="$PROJECT_DIR$/vendor/psr/simple-cache" />
<path value="$PROJECT_DIR$/vendor/league/container" />
<path value="$PROJECT_DIR$/vendor/cakephp/core" />
<path value="$PROJECT_DIR$/vendor/cakephp/utility" />
<path value="$PROJECT_DIR$/vendor/cakephp/database" />
<path value="$PROJECT_DIR$/vendor/cakephp/datasource" />
<path value="$PROJECT_DIR$/vendor/cakephp/chronos" />
<path value="$PROJECT_DIR$/vendor/riimu/kit-phpencoder" />
<path value="$PROJECT_DIR$/vendor/odan/phinx-migrations-generator" />
</include_path> </include_path>
</component> </component>
<component name="PhpProjectSharedConfiguration" php_language_level="8.2"> <component name="PhpProjectSharedConfiguration" php_language_level="8.2">

11
Jenkinsfile vendored
View File

@ -1,11 +0,0 @@
pipeline {
agent any
stages {
stage('Do nothing') {
steps {
sh '/bin/true'
}
}
}
}

View File

@ -2,7 +2,7 @@
"name": "24unix/bindapi", "name": "24unix/bindapi",
"description": "manage Bind9 DNS server via REST API", "description": "manage Bind9 DNS server via REST API",
"version": "2023.0.1", "version": "2023.0.1",
"build_number": "328", "build_number": "329",
"authors": [ "authors": [
{ {
"name": "Micha Espey", "name": "Micha Espey",
@ -24,9 +24,10 @@
"ext-sodium": "*", "ext-sodium": "*",
"arubacao/tld-checker": "^1.2", "arubacao/tld-checker": "^1.2",
"monolog/monolog": "^3.1", "monolog/monolog": "^3.1",
"netresearch/jsonmapper": "^4.0", "netresearch/jsonmapper": "^4.4",
"php-di/php-di": "^6.3", "php-di/php-di": "^6.3",
"phplucidframe/console-table": "^1.2", "phplucidframe/console-table": "^1.2",
"robmorgan/phinx": "^0.15",
"symfony/property-access": "^6.1", "symfony/property-access": "^6.1",
"symfony/serializer": "^6.1", "symfony/serializer": "^6.1",
"zircote/swagger-php": "^4.2" "zircote/swagger-php": "^4.2"
@ -50,6 +51,7 @@
}, },
"require-dev": { "require-dev": {
"escapestudios/symfony2-coding-standard": "3.x-dev", "escapestudios/symfony2-coding-standard": "3.x-dev",
"odan/phinx-migrations-generator": "^6.1",
"phpunit/phpunit": "10" "phpunit/phpunit": "10"
} }
} }

944
composer.lock generated
View File

@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically" "This file is @generated automatically"
], ],
"content-hash": "01083bcdf701c6a421d22feaa6c865c8", "content-hash": "06c636117e4391261d02c4bf3a2f356d",
"packages": [ "packages": [
{ {
"name": "arubacao/tld-checker", "name": "arubacao/tld-checker",
@ -69,6 +69,308 @@
}, },
"time": "2024-04-07T04:01:17+00:00" "time": "2024-04-07T04:01:17+00:00"
}, },
{
"name": "cakephp/chronos",
"version": "3.0.4",
"source": {
"type": "git",
"url": "https://github.com/cakephp/chronos.git",
"reference": "9cb035acd10152a6b74df936986f15c4e6015bd3"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/cakephp/chronos/zipball/9cb035acd10152a6b74df936986f15c4e6015bd3",
"reference": "9cb035acd10152a6b74df936986f15c4e6015bd3",
"shasum": ""
},
"require": {
"php": ">=8.1"
},
"require-dev": {
"cakephp/cakephp-codesniffer": "^5.0",
"phpunit/phpunit": "^10.1.0"
},
"type": "library",
"autoload": {
"psr-4": {
"Cake\\Chronos\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Brian Nesbitt",
"email": "brian@nesbot.com",
"homepage": "http://nesbot.com"
},
{
"name": "The CakePHP Team",
"homepage": "https://cakephp.org"
}
],
"description": "A simple API extension for DateTime.",
"homepage": "https://cakephp.org",
"keywords": [
"date",
"datetime",
"time"
],
"support": {
"issues": "https://github.com/cakephp/chronos/issues",
"source": "https://github.com/cakephp/chronos"
},
"time": "2023-10-17T07:41:48+00:00"
},
{
"name": "cakephp/core",
"version": "5.0.7",
"source": {
"type": "git",
"url": "https://github.com/cakephp/core.git",
"reference": "163ba348b96870de24b7cf34abdcd8d0c3794ed7"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/cakephp/core/zipball/163ba348b96870de24b7cf34abdcd8d0c3794ed7",
"reference": "163ba348b96870de24b7cf34abdcd8d0c3794ed7",
"shasum": ""
},
"require": {
"cakephp/utility": "^5.0",
"league/container": "^4.2",
"php": ">=8.1",
"psr/container": "^1.1 || ^2.0"
},
"provide": {
"psr/container-implementation": "^2.0"
},
"suggest": {
"cakephp/cache": "To use Configure::store() and restore().",
"cakephp/event": "To use PluginApplicationInterface or plugin applications.",
"league/container": "To use Container and ServiceProvider classes"
},
"type": "library",
"autoload": {
"files": [
"functions.php"
],
"psr-4": {
"Cake\\Core\\": "."
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "CakePHP Community",
"homepage": "https://github.com/cakephp/core/graphs/contributors"
}
],
"description": "CakePHP Framework Core classes",
"homepage": "https://cakephp.org",
"keywords": [
"cakephp",
"core",
"framework"
],
"support": {
"forum": "https://stackoverflow.com/tags/cakephp",
"irc": "irc://irc.freenode.org/cakephp",
"issues": "https://github.com/cakephp/cakephp/issues",
"source": "https://github.com/cakephp/core"
},
"time": "2024-03-13T17:13:27+00:00"
},
{
"name": "cakephp/database",
"version": "5.0.7",
"source": {
"type": "git",
"url": "https://github.com/cakephp/database.git",
"reference": "218f60271f65d1808272f785ce64a15491796648"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/cakephp/database/zipball/218f60271f65d1808272f785ce64a15491796648",
"reference": "218f60271f65d1808272f785ce64a15491796648",
"shasum": ""
},
"require": {
"cakephp/chronos": "^3.0.2",
"cakephp/core": "^5.0",
"cakephp/datasource": "^5.0",
"php": ">=8.1",
"psr/log": "^3.0"
},
"require-dev": {
"cakephp/i18n": "^5.0",
"cakephp/log": "^5.0",
"phpstan/phpstan": "^1.10"
},
"suggest": {
"cakephp/i18n": "If you are using locale-aware datetime formats.",
"cakephp/log": "If you want to use query logging without providing a logger yourself."
},
"type": "library",
"autoload": {
"psr-4": {
"Cake\\Database\\": "."
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "CakePHP Community",
"homepage": "https://github.com/cakephp/database/graphs/contributors"
}
],
"description": "Flexible and powerful Database abstraction library with a familiar PDO-like API",
"homepage": "https://cakephp.org",
"keywords": [
"abstraction",
"cakephp",
"database",
"database abstraction",
"pdo"
],
"support": {
"forum": "https://stackoverflow.com/tags/cakephp",
"irc": "irc://irc.freenode.org/cakephp",
"issues": "https://github.com/cakephp/cakephp/issues",
"source": "https://github.com/cakephp/database"
},
"time": "2024-03-04T21:01:09+00:00"
},
{
"name": "cakephp/datasource",
"version": "5.0.7",
"source": {
"type": "git",
"url": "https://github.com/cakephp/datasource.git",
"reference": "3b3a70d0d8ae0daf55535f45b99ef109639ed1ec"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/cakephp/datasource/zipball/3b3a70d0d8ae0daf55535f45b99ef109639ed1ec",
"reference": "3b3a70d0d8ae0daf55535f45b99ef109639ed1ec",
"shasum": ""
},
"require": {
"cakephp/core": "^5.0",
"php": ">=8.1",
"psr/simple-cache": "^2.0 || ^3.0"
},
"require-dev": {
"cakephp/cache": "^5.0",
"cakephp/collection": "^5.0",
"cakephp/utility": "^5.0",
"phpstan/phpstan": "^1.10"
},
"suggest": {
"cakephp/cache": "If you decide to use Query caching.",
"cakephp/collection": "If you decide to use ResultSetInterface.",
"cakephp/utility": "If you decide to use EntityTrait."
},
"type": "library",
"autoload": {
"psr-4": {
"Cake\\Datasource\\": "."
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "CakePHP Community",
"homepage": "https://github.com/cakephp/datasource/graphs/contributors"
}
],
"description": "Provides connection managing and traits for Entities and Queries that can be reused for different datastores",
"homepage": "https://cakephp.org",
"keywords": [
"cakephp",
"connection management",
"datasource",
"entity",
"query"
],
"support": {
"forum": "https://stackoverflow.com/tags/cakephp",
"irc": "irc://irc.freenode.org/cakephp",
"issues": "https://github.com/cakephp/cakephp/issues",
"source": "https://github.com/cakephp/datasource"
},
"time": "2024-03-11T18:07:04+00:00"
},
{
"name": "cakephp/utility",
"version": "5.0.7",
"source": {
"type": "git",
"url": "https://github.com/cakephp/utility.git",
"reference": "6d624cefc3e005ebf9bd2e7d8a1d35f5f4601ff8"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/cakephp/utility/zipball/6d624cefc3e005ebf9bd2e7d8a1d35f5f4601ff8",
"reference": "6d624cefc3e005ebf9bd2e7d8a1d35f5f4601ff8",
"shasum": ""
},
"require": {
"cakephp/core": "^5.0",
"php": ">=8.1"
},
"suggest": {
"ext-intl": "To use Text::transliterate() or Text::slug()",
"lib-ICU": "To use Text::transliterate() or Text::slug()"
},
"type": "library",
"autoload": {
"files": [
"bootstrap.php"
],
"psr-4": {
"Cake\\Utility\\": "."
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "CakePHP Community",
"homepage": "https://github.com/cakephp/utility/graphs/contributors"
}
],
"description": "CakePHP Utility classes such as Inflector, String, Hash, and Security",
"homepage": "https://cakephp.org",
"keywords": [
"cakephp",
"hash",
"inflector",
"security",
"string",
"utility"
],
"support": {
"forum": "https://stackoverflow.com/tags/cakephp",
"irc": "irc://irc.freenode.org/cakephp",
"issues": "https://github.com/cakephp/cakephp/issues",
"source": "https://github.com/cakephp/utility"
},
"time": "2024-02-24T04:42:47+00:00"
},
{ {
"name": "laravel/serializable-closure", "name": "laravel/serializable-closure",
"version": "v1.3.3", "version": "v1.3.3",
@ -129,6 +431,88 @@
}, },
"time": "2023-11-08T14:08:06+00:00" "time": "2023-11-08T14:08:06+00:00"
}, },
{
"name": "league/container",
"version": "4.2.2",
"source": {
"type": "git",
"url": "https://github.com/thephpleague/container.git",
"reference": "ff346319ca1ff0e78277dc2311a42107cc1aab88"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/thephpleague/container/zipball/ff346319ca1ff0e78277dc2311a42107cc1aab88",
"reference": "ff346319ca1ff0e78277dc2311a42107cc1aab88",
"shasum": ""
},
"require": {
"php": "^7.2 || ^8.0",
"psr/container": "^1.1 || ^2.0"
},
"provide": {
"psr/container-implementation": "^1.0"
},
"replace": {
"orno/di": "~2.0"
},
"require-dev": {
"nette/php-generator": "^3.4",
"nikic/php-parser": "^4.10",
"phpstan/phpstan": "^0.12.47",
"phpunit/phpunit": "^8.5.17",
"roave/security-advisories": "dev-latest",
"scrutinizer/ocular": "^1.8",
"squizlabs/php_codesniffer": "^3.6"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "4.x-dev",
"dev-4.x": "4.x-dev",
"dev-3.x": "3.x-dev",
"dev-2.x": "2.x-dev",
"dev-1.x": "1.x-dev"
}
},
"autoload": {
"psr-4": {
"League\\Container\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Phil Bennett",
"email": "mail@philbennett.co.uk",
"role": "Developer"
}
],
"description": "A fast and intuitive dependency injection container.",
"homepage": "https://github.com/thephpleague/container",
"keywords": [
"container",
"dependency",
"di",
"injection",
"league",
"provider",
"service"
],
"support": {
"issues": "https://github.com/thephpleague/container/issues",
"source": "https://github.com/thephpleague/container/tree/4.2.2"
},
"funding": [
{
"url": "https://github.com/philipobenito",
"type": "github"
}
],
"time": "2024-03-13T13:12:53+00:00"
},
{ {
"name": "monolog/monolog", "name": "monolog/monolog",
"version": "3.5.0", "version": "3.5.0",
@ -596,6 +980,312 @@
}, },
"time": "2021-07-14T16:46:02+00:00" "time": "2021-07-14T16:46:02+00:00"
}, },
{
"name": "psr/simple-cache",
"version": "3.0.0",
"source": {
"type": "git",
"url": "https://github.com/php-fig/simple-cache.git",
"reference": "764e0b3939f5ca87cb904f570ef9be2d78a07865"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/php-fig/simple-cache/zipball/764e0b3939f5ca87cb904f570ef9be2d78a07865",
"reference": "764e0b3939f5ca87cb904f570ef9be2d78a07865",
"shasum": ""
},
"require": {
"php": ">=8.0.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "3.0.x-dev"
}
},
"autoload": {
"psr-4": {
"Psr\\SimpleCache\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "PHP-FIG",
"homepage": "https://www.php-fig.org/"
}
],
"description": "Common interfaces for simple caching",
"keywords": [
"cache",
"caching",
"psr",
"psr-16",
"simple-cache"
],
"support": {
"source": "https://github.com/php-fig/simple-cache/tree/3.0.0"
},
"time": "2021-10-29T13:26:27+00:00"
},
{
"name": "robmorgan/phinx",
"version": "0.15.5",
"source": {
"type": "git",
"url": "https://github.com/cakephp/phinx.git",
"reference": "a81c0846256fb9131c4c06d119fbff9d01cbc198"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/cakephp/phinx/zipball/a81c0846256fb9131c4c06d119fbff9d01cbc198",
"reference": "a81c0846256fb9131c4c06d119fbff9d01cbc198",
"shasum": ""
},
"require": {
"cakephp/database": "^5.0.2",
"php-64bit": ">=8.1",
"psr/container": "^1.1|^2.0",
"symfony/config": "^3.4|^4.0|^5.0|^6.0|^7.0",
"symfony/console": "^6.0|^7.0"
},
"require-dev": {
"cakephp/cakephp": "^5.0.2",
"cakephp/cakephp-codesniffer": "^5.0",
"ext-json": "*",
"ext-pdo": "*",
"phpunit/phpunit": "^9.5.19",
"symfony/yaml": "^3.4|^4.0|^5.0|^6.0|^7.0"
},
"suggest": {
"ext-json": "Install if using JSON configuration format",
"ext-pdo": "PDO extension is needed",
"symfony/yaml": "Install if using YAML configuration format"
},
"bin": [
"bin/phinx"
],
"type": "library",
"autoload": {
"psr-4": {
"Phinx\\": "src/Phinx/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Rob Morgan",
"email": "robbym@gmail.com",
"homepage": "https://robmorgan.id.au",
"role": "Lead Developer"
},
{
"name": "Woody Gilk",
"email": "woody.gilk@gmail.com",
"homepage": "https://shadowhand.me",
"role": "Developer"
},
{
"name": "Richard Quadling",
"email": "rquadling@gmail.com",
"role": "Developer"
},
{
"name": "CakePHP Community",
"homepage": "https://github.com/cakephp/phinx/graphs/contributors",
"role": "Developer"
}
],
"description": "Phinx makes it ridiculously easy to manage the database migrations for your PHP app.",
"homepage": "https://phinx.org",
"keywords": [
"database",
"database migrations",
"db",
"migrations",
"phinx"
],
"support": {
"issues": "https://github.com/cakephp/phinx/issues",
"source": "https://github.com/cakephp/phinx/tree/0.15.5"
},
"time": "2023-12-05T13:24:00+00:00"
},
{
"name": "symfony/config",
"version": "v7.0.6",
"source": {
"type": "git",
"url": "https://github.com/symfony/config.git",
"reference": "7fc7e18a73ec8125fd95928c0340470d64760deb"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/config/zipball/7fc7e18a73ec8125fd95928c0340470d64760deb",
"reference": "7fc7e18a73ec8125fd95928c0340470d64760deb",
"shasum": ""
},
"require": {
"php": ">=8.2",
"symfony/deprecation-contracts": "^2.5|^3",
"symfony/filesystem": "^6.4|^7.0",
"symfony/polyfill-ctype": "~1.8"
},
"conflict": {
"symfony/finder": "<6.4",
"symfony/service-contracts": "<2.5"
},
"require-dev": {
"symfony/event-dispatcher": "^6.4|^7.0",
"symfony/finder": "^6.4|^7.0",
"symfony/messenger": "^6.4|^7.0",
"symfony/service-contracts": "^2.5|^3",
"symfony/yaml": "^6.4|^7.0"
},
"type": "library",
"autoload": {
"psr-4": {
"Symfony\\Component\\Config\\": ""
},
"exclude-from-classmap": [
"/Tests/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Fabien Potencier",
"email": "fabien@symfony.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Helps you find, load, combine, autofill and validate configuration values of any kind",
"homepage": "https://symfony.com",
"support": {
"source": "https://github.com/symfony/config/tree/v7.0.6"
},
"funding": [
{
"url": "https://symfony.com/sponsor",
"type": "custom"
},
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"time": "2024-03-27T19:55:25+00:00"
},
{
"name": "symfony/console",
"version": "v6.4.6",
"source": {
"type": "git",
"url": "https://github.com/symfony/console.git",
"reference": "a2708a5da5c87d1d0d52937bdeac625df659e11f"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/console/zipball/a2708a5da5c87d1d0d52937bdeac625df659e11f",
"reference": "a2708a5da5c87d1d0d52937bdeac625df659e11f",
"shasum": ""
},
"require": {
"php": ">=8.1",
"symfony/deprecation-contracts": "^2.5|^3",
"symfony/polyfill-mbstring": "~1.0",
"symfony/service-contracts": "^2.5|^3",
"symfony/string": "^5.4|^6.0|^7.0"
},
"conflict": {
"symfony/dependency-injection": "<5.4",
"symfony/dotenv": "<5.4",
"symfony/event-dispatcher": "<5.4",
"symfony/lock": "<5.4",
"symfony/process": "<5.4"
},
"provide": {
"psr/log-implementation": "1.0|2.0|3.0"
},
"require-dev": {
"psr/log": "^1|^2|^3",
"symfony/config": "^5.4|^6.0|^7.0",
"symfony/dependency-injection": "^5.4|^6.0|^7.0",
"symfony/event-dispatcher": "^5.4|^6.0|^7.0",
"symfony/http-foundation": "^6.4|^7.0",
"symfony/http-kernel": "^6.4|^7.0",
"symfony/lock": "^5.4|^6.0|^7.0",
"symfony/messenger": "^5.4|^6.0|^7.0",
"symfony/process": "^5.4|^6.0|^7.0",
"symfony/stopwatch": "^5.4|^6.0|^7.0",
"symfony/var-dumper": "^5.4|^6.0|^7.0"
},
"type": "library",
"autoload": {
"psr-4": {
"Symfony\\Component\\Console\\": ""
},
"exclude-from-classmap": [
"/Tests/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Fabien Potencier",
"email": "fabien@symfony.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Eases the creation of beautiful and testable command line interfaces",
"homepage": "https://symfony.com",
"keywords": [
"cli",
"command-line",
"console",
"terminal"
],
"support": {
"source": "https://github.com/symfony/console/tree/v6.4.6"
},
"funding": [
{
"url": "https://symfony.com/sponsor",
"type": "custom"
},
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"time": "2024-03-29T19:07:53+00:00"
},
{ {
"name": "symfony/deprecation-contracts", "name": "symfony/deprecation-contracts",
"version": "v3.4.0", "version": "v3.4.0",
@ -663,6 +1353,69 @@
], ],
"time": "2023-05-23T14:45:45+00:00" "time": "2023-05-23T14:45:45+00:00"
}, },
{
"name": "symfony/filesystem",
"version": "v7.0.6",
"source": {
"type": "git",
"url": "https://github.com/symfony/filesystem.git",
"reference": "408105dff4c104454100730bdfd1a9cdd993f04d"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/filesystem/zipball/408105dff4c104454100730bdfd1a9cdd993f04d",
"reference": "408105dff4c104454100730bdfd1a9cdd993f04d",
"shasum": ""
},
"require": {
"php": ">=8.2",
"symfony/polyfill-ctype": "~1.8",
"symfony/polyfill-mbstring": "~1.8"
},
"type": "library",
"autoload": {
"psr-4": {
"Symfony\\Component\\Filesystem\\": ""
},
"exclude-from-classmap": [
"/Tests/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Fabien Potencier",
"email": "fabien@symfony.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Provides basic utilities for the filesystem",
"homepage": "https://symfony.com",
"support": {
"source": "https://github.com/symfony/filesystem/tree/v7.0.6"
},
"funding": [
{
"url": "https://symfony.com/sponsor",
"type": "custom"
},
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"time": "2024-03-21T19:37:36+00:00"
},
{ {
"name": "symfony/finder", "name": "symfony/finder",
"version": "v7.0.0", "version": "v7.0.0",
@ -1303,6 +2056,88 @@
], ],
"time": "2024-03-27T22:00:14+00:00" "time": "2024-03-27T22:00:14+00:00"
}, },
{
"name": "symfony/service-contracts",
"version": "v3.4.2",
"source": {
"type": "git",
"url": "https://github.com/symfony/service-contracts.git",
"reference": "11bbf19a0fb7b36345861e85c5768844c552906e"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/service-contracts/zipball/11bbf19a0fb7b36345861e85c5768844c552906e",
"reference": "11bbf19a0fb7b36345861e85c5768844c552906e",
"shasum": ""
},
"require": {
"php": ">=8.1",
"psr/container": "^1.1|^2.0"
},
"conflict": {
"ext-psr": "<1.1|>=2"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "3.4-dev"
},
"thanks": {
"name": "symfony/contracts",
"url": "https://github.com/symfony/contracts"
}
},
"autoload": {
"psr-4": {
"Symfony\\Contracts\\Service\\": ""
},
"exclude-from-classmap": [
"/Test/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Nicolas Grekas",
"email": "p@tchwork.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Generic abstractions related to writing services",
"homepage": "https://symfony.com",
"keywords": [
"abstractions",
"contracts",
"decoupling",
"interfaces",
"interoperability",
"standards"
],
"support": {
"source": "https://github.com/symfony/service-contracts/tree/v3.4.2"
},
"funding": [
{
"url": "https://symfony.com/sponsor",
"type": "custom"
},
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"time": "2023-12-19T21:51:00+00:00"
},
{ {
"name": "symfony/string", "name": "symfony/string",
"version": "v7.0.4", "version": "v7.0.4",
@ -1719,6 +2554,64 @@
}, },
"time": "2024-03-05T20:51:40+00:00" "time": "2024-03-05T20:51:40+00:00"
}, },
{
"name": "odan/phinx-migrations-generator",
"version": "6.1.1",
"source": {
"type": "git",
"url": "https://github.com/odan/phinx-migrations-generator.git",
"reference": "167447e716935c6bffbde8ce86b6baeb3ce55f29"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/odan/phinx-migrations-generator/zipball/167447e716935c6bffbde8ce86b6baeb3ce55f29",
"reference": "167447e716935c6bffbde8ce86b6baeb3ce55f29",
"shasum": ""
},
"require": {
"ext-json": "*",
"ext-pdo": "*",
"php": "~8.1 || ~8.2",
"riimu/kit-phpencoder": "^2.4",
"robmorgan/phinx": "^0.15.2",
"symfony/console": "^6"
},
"require-dev": {
"friendsofphp/php-cs-fixer": "^3",
"phpstan/phpstan": "^1",
"phpunit/phpunit": "^10",
"squizlabs/php_codesniffer": "^3",
"symfony/uid": "^6"
},
"bin": [
"./bin/phinx-migrations"
],
"type": "library",
"autoload": {
"psr-4": {
"Odan\\Migration\\": "src/Migration/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"description": "Migration generator for Phinx",
"homepage": "https://github.com/odan/phinx-migrations-generator",
"keywords": [
"database",
"generator",
"migration",
"migrations",
"mysql",
"phinx"
],
"support": {
"issues": "https://github.com/odan/phinx-migrations-generator/issues",
"source": "https://github.com/odan/phinx-migrations-generator/tree/6.1.1"
},
"time": "2024-04-11T15:35:30+00:00"
},
{ {
"name": "phar-io/manifest", "name": "phar-io/manifest",
"version": "2.0.4", "version": "2.0.4",
@ -2258,6 +3151,55 @@
], ],
"time": "2023-02-03T07:16:15+00:00" "time": "2023-02-03T07:16:15+00:00"
}, },
{
"name": "riimu/kit-phpencoder",
"version": "v2.4.2",
"source": {
"type": "git",
"url": "https://github.com/Riimu/Kit-PHPEncoder.git",
"reference": "72ff7825de193b272e17b228394819dbfc638e72"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/Riimu/Kit-PHPEncoder/zipball/72ff7825de193b272e17b228394819dbfc638e72",
"reference": "72ff7825de193b272e17b228394819dbfc638e72",
"shasum": ""
},
"require": {
"php": ">=5.6.0"
},
"type": "library",
"autoload": {
"psr-4": {
"Riimu\\Kit\\PHPEncoder\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Riikka Kalliomäki",
"email": "riikka.kalliomaki@gmail.com",
"homepage": "http://riimu.net"
}
],
"description": "Highly customizable alternative to var_export for PHP code generation",
"homepage": "http://kit.riimu.net",
"keywords": [
"code",
"encoder",
"export",
"generator",
"variable"
],
"support": {
"issues": "https://github.com/Riimu/Kit-PHPEncoder/issues",
"source": "https://github.com/Riimu/Kit-PHPEncoder/tree/v2.4.2"
},
"time": "2022-12-10T18:12:25+00:00"
},
{ {
"name": "sebastian/cli-parser", "name": "sebastian/cli-parser",
"version": "2.0.1", "version": "2.0.1",

View File

@ -0,0 +1,255 @@
<?php
use Phinx\Db\Adapter\MysqlAdapter;
class TableCreation extends Phinx\Migration\AbstractMigration
{
public function change()
{
$this->table('migrations', [
'id' => false,
'engine' => 'InnoDB',
'encoding' => 'utf8mb4',
'collation' => 'utf8mb4_general_ci',
'comment' => '',
'row_format' => 'DYNAMIC',
])
->addColumn('id', 'integer', [
'null' => false,
'limit' => MysqlAdapter::INT_REGULAR,
])
->addColumn('name', 'string', [
'null' => false,
'limit' => 255,
'collation' => 'utf8mb4_general_ci',
'encoding' => 'utf8mb4',
'after' => 'id',
])
->addColumn('executedAt', 'date', [
'null' => false,
'after' => 'name',
])
->create();
$this->table('config', [
'id' => false,
'engine' => 'InnoDB',
'encoding' => 'utf8mb4',
'collation' => 'utf8mb4_general_ci',
'comment' => '',
'row_format' => 'DYNAMIC',
])
->addColumn('version', 'string', [
'null' => false,
'limit' => 11,
'collation' => 'utf8mb4_general_ci',
'encoding' => 'utf8mb4',
])
->create();
$this->table('panels', [
'id' => false,
'primary_key' => ['id'],
'engine' => 'InnoDB',
'encoding' => 'utf8mb4',
'collation' => 'utf8mb4_unicode_ci',
'comment' => '',
'row_format' => 'DYNAMIC',
])
->addColumn('id', 'integer', [
'null' => false,
'limit' => MysqlAdapter::INT_REGULAR,
'identity' => true,
])
->addColumn('name', 'string', [
'null' => false,
'limit' => 255,
'collation' => 'utf8mb4_unicode_ci',
'encoding' => 'utf8mb4',
'after' => 'id',
])
->addColumn('a', 'varbinary', [
'null' => true,
'default' => null,
'limit' => 255,
'after' => 'name',
])
->addColumn('aaaa', 'varbinary', [
'null' => true,
'default' => null,
'limit' => 255,
'after' => 'a',
])
->addColumn('apikey', 'varbinary', [
'null' => true,
'default' => null,
'limit' => 255,
'after' => 'aaaa',
])
->addColumn('apikey_prefix', 'string', [
'null' => false,
'limit' => 8,
'collation' => 'utf8mb4_unicode_ci',
'encoding' => 'utf8mb4',
'after' => 'apikey',
])
->addColumn('self', 'enum', [
'null' => false,
'default' => 'no',
'limit' => 3,
'values' => ['yes', 'no'],
'after' => 'apikey_prefix',
])
->create();
$this->table('dyndns', [
'id' => false,
'primary_key' => ['id'],
'engine' => 'InnoDB',
'encoding' => 'utf8mb4',
'collation' => 'utf8mb4_unicode_ci',
'comment' => '',
'row_format' => 'DYNAMIC',
])
->addColumn('id', 'integer', [
'null' => false,
'limit' => MysqlAdapter::INT_REGULAR,
'identity' => true,
])
->addColumn('name', 'string', [
'null' => false,
'limit' => 255,
'collation' => 'utf8mb4_unicode_ci',
'encoding' => 'utf8mb4',
'after' => 'id',
])
->addColumn('a', 'varbinary', [
'null' => false,
'limit' => 255,
'after' => 'name',
])
->addColumn('aaaa', 'varbinary', [
'null' => false,
'limit' => 255,
'after' => 'a',
])
->addColumn('last_update', 'timestamp', [
'null' => false,
'default' => 'current_timestamp()',
'update' => 'CURRENT_TIMESTAMP',
'after' => 'aaaa',
])
->create();
$this->table('domains', [
'id' => false,
'primary_key' => ['id'],
'engine' => 'InnoDB',
'encoding' => 'utf8mb4',
'collation' => 'utf8mb4_unicode_ci',
'comment' => '',
'row_format' => 'DYNAMIC',
])
->addColumn('id', 'integer', [
'null' => false,
'limit' => MysqlAdapter::INT_REGULAR,
'identity' => true,
])
->addColumn('name', 'string', [
'null' => false,
'limit' => 255,
'collation' => 'utf8mb4_unicode_ci',
'encoding' => 'utf8mb4',
'after' => 'id',
])
->addColumn('panel', 'string', [
'null' => true,
'default' => null,
'limit' => 255,
'collation' => 'utf8mb4_unicode_ci',
'encoding' => 'utf8mb4',
'after' => 'name',
])
->create();
$this->table('apikeys', [
'id' => false,
'primary_key' => ['id'],
'engine' => 'InnoDB',
'encoding' => 'utf8mb4',
'collation' => 'utf8mb4_unicode_ci',
'comment' => '',
'row_format' => 'DYNAMIC',
])
->addColumn('id', 'integer', [
'null' => false,
'limit' => MysqlAdapter::INT_REGULAR,
'identity' => true,
])
->addColumn('name', 'string', [
'null' => true,
'default' => null,
'limit' => 255,
'collation' => 'utf8mb4_unicode_ci',
'encoding' => 'utf8mb4',
'after' => 'id',
])
->addColumn('apikey_prefix', 'string', [
'null' => false,
'limit' => 13,
'collation' => 'utf8mb4_unicode_ci',
'encoding' => 'utf8mb4',
'after' => 'name',
])
->addColumn('apikey', 'string', [
'null' => false,
'limit' => 255,
'collation' => 'utf8mb4_unicode_ci',
'encoding' => 'utf8mb4',
'after' => 'apikey_prefix',
])
->create();
$this->table('nameservers', [
'id' => false,
'primary_key' => ['id'],
'engine' => 'InnoDB',
'encoding' => 'utf8mb4',
'collation' => 'utf8mb4_unicode_ci',
'comment' => '',
'row_format' => 'DYNAMIC',
])
->addColumn('id', 'integer', [
'null' => false,
'limit' => MysqlAdapter::INT_REGULAR,
'identity' => true,
])
->addColumn('name', 'string', [
'null' => false,
'limit' => 255,
'collation' => 'utf8mb4_unicode_ci',
'encoding' => 'utf8mb4',
'after' => 'id',
])
->addColumn('a', 'varbinary', [
'null' => true,
'default' => null,
'limit' => 255,
'after' => 'name',
])
->addColumn('aaaa', 'varbinary', [
'null' => true,
'default' => null,
'limit' => 255,
'after' => 'a',
])
->addColumn('apikey', 'varbinary', [
'null' => true,
'default' => null,
'limit' => 255,
'after' => 'aaaa',
])
->addColumn('apikey_prefix', 'string', [
'null' => false,
'limit' => 13,
'collation' => 'utf8mb4_unicode_ci',
'encoding' => 'utf8mb4',
'after' => 'apikey',
])
->create();
}
}

1088
db/migrations/schema.php Normal file

File diff suppressed because it is too large Load Diff

40
phinx.php Normal file
View File

@ -0,0 +1,40 @@
<?php
use App\Controller\ConfigController;
require 'vendor/autoload.php';
$configController = new ConfigController();
$dbHost = $configController->getConfig(configKey: 'dbHost');
$dbPort = $configController->getConfig(configKey: 'dbPort');
$dbDatabase = $configController->getConfig(configKey: 'dbDatabase');
$dbUser = $configController->getConfig(configKey: 'dbUser');
$dbPassword = $configController->getConfig(configKey: 'dbPassword');
// unlike the example config, we don't maintain different environments here,
// that is set globally, currently by selecting the matching config.json.
// but that might change to envfiles in the future
return
[
'paths' => [
'migrations' => '%%PHINX_CONFIG_DIR%%/db/migrations',
'seeds' => '%%PHINX_CONFIG_DIR%%/db/seeds'
],
'environments' => [
'default_migration_table' => 'phinxlog',
'default_environment' => 'default',
'default' => [
'adapter' => 'mysql',
'host' => $dbHost,
'name' => $dbDatabase,
'user' => $dbUser,
'pass' => $dbPassword,
'port' => $dbPort,
'charset' => 'utf8',
],
],
'version_order' => 'creation'
];

View File

@ -6,10 +6,6 @@ use UnhandledMatchError;
error_reporting(error_level: E_ALL); error_reporting(error_level: E_ALL);
/**
*
*/
class ApiController class ApiController
{ {

View File

@ -28,7 +28,7 @@ class BindAPI
/** /**
* @throws Exception * @throws Exception
*/ */
public function __construct($quiet = false) public function __construct()
{ {
// init the logger // init the logger
$dateFormat = "Y:m:d H:i:s"; $dateFormat = "Y:m:d H:i:s";
@ -50,8 +50,7 @@ class BindAPI
$containerBuilder = new ContainerBuilder(); $containerBuilder = new ContainerBuilder();
$containerBuilder->addDefinitions([ $containerBuilder->addDefinitions([
ConfigController::class => autowire() ConfigController::class => autowire(),
->constructorParameter(parameter: 'quiet', value: $quiet),
CLIController::class => autowire() CLIController::class => autowire()
->constructorParameter(parameter: 'logger', value: $this->logger), ->constructorParameter(parameter: 'logger', value: $this->logger),
DomainController::class => autowire() DomainController::class => autowire()

View File

@ -1,44 +1,51 @@
<?php declare(strict_types=1); <?php
declare(strict_types=1);
namespace App\Controller; namespace App\Controller;
error_reporting(error_level: E_ALL); error_reporting(error_level: E_ALL);
define(constant_name: 'COLOR_RED', value: "\033[31m"); define(constant_name: 'COLOR_RED', value: "\033[31m");
define(constant_name: 'COLOR_GREEN', value: "\033[32m"); define(constant_name: 'COLOR_GREEN', value: "\033[32m");
define(constant_name: 'COLOR_YELLOW', value: "\033[33m"); define(constant_name: 'COLOR_YELLOW', value: "\033[33m");
define(constant_name: 'COLOR_BLUE', value: "\033[34m"); define(constant_name: 'COLOR_BLUE', value: "\033[34m");
define(constant_name: 'COLOR_WHITE', value: "\033[37m"); define(constant_name: 'COLOR_WHITE', value: "\033[37m");
define(constant_name: 'COLOR_DEFAULT', value: "\033[39m"); define(constant_name: 'COLOR_DEFAULT', value: "\033[39m");
use App\Controller\Commands\Command; use App\Controller\Commands\Command;
use App\Controller\Commands\CommandGroup; use App\Controller\Commands\CommandGroup;
use App\Controller\Commands\CommandGroupContainer; use App\Controller\Commands\CommandGroupContainer;
use App\Entity\Apikey; use App\Entity\Apikey;
use App\Entity\Domain; use App\Entity\Domain;
use App\Entity\DynDNS; use App\Entity\DynDNS;
use App\Entity\KeyHelp\KeyHelpDomain; use App\Entity\KeyHelp\KeyHelpDomain;
use App\Entity\Nameserver; use App\Entity\Nameserver;
use App\Entity\Panel; use App\Entity\Panel;
use App\Repository\ApikeyRepository; use App\Repository\ApikeyRepository;
use App\Repository\DomainRepository; use App\Repository\DomainRepository;
use App\Repository\DynDNSRepository; use App\Repository\DynDNSRepository;
use App\Repository\NameserverRepository; use App\Repository\NameserverRepository;
use App\Repository\PanelRepository; use App\Repository\PanelRepository;
use Arubacao\TldChecker\Validator; use Arubacao\TldChecker\Validator;
use Exception; use Exception;
use JsonMapper; use JsonMapper;
use JsonMapper_Exception; use JsonMapper_Exception;
use LucidFrame\Console\ConsoleTable; use LucidFrame\Console\ConsoleTable;
use SodiumException; use Odan\Migration\Command\GenerateCommand;
use Phinx\Console\PhinxApplication;
use SodiumException;
use Symfony\Component\Console\Input\ArrayInput;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\ConsoleOutput;
use Symfony\Component\Console\Output\OutputInterface;
if (php_sapi_name() !== 'cli') { if (php_sapi_name() !== 'cli') {
exit; exit;
} }
class CLIController class CLIController
{ {
private array $arguments; private array $arguments;
private CommandGroupContainer $commandGroupContainer; private CommandGroupContainer $commandGroupContainer;
@ -62,126 +69,126 @@ class CLIController
$this->commandGroupContainer = (new CommandGroupContainer()) $this->commandGroupContainer = (new CommandGroupContainer())
->addCommandGroup(commandGroup: (new CommandGroup(name: 'check', description: 'health checks the system can perform')) ->addCommandGroup(commandGroup: (new CommandGroup(name: 'check', description: 'health checks the system can perform'))
->addCommand(command: new Command( ->addCommand(command: new Command(
name: 'permissions', name : 'permissions',
callback: function () { callback : function () {
$this->checkPermissions(); $this->checkPermissions();
}, },
description: 'check file permissions')) description: 'check file permissions'))
->addCommand(command: new Command( ->addCommand(command: new Command(
name: 'panels', name : 'panels',
callback: function () { callback : function () {
$this->checkPanels(); $this->checkPanels();
}, },
optionalParameters: ['ID', 'fix=xes'])) optionalParameters: ['ID', 'fix=xes']))
->addCommand(command: new Command( ->addCommand(command: new Command(
name: 'domains', name : 'domains',
callback: function () { callback: function () {
$this->checkDomains(); $this->checkDomains();
})) }))
->addCommand(command: new Command( ->addCommand(command: new Command(
name: 'mail', name : 'mail',
callback: function () { callback: function () {
$this->checkMail(); $this->checkMail();
})) }))
->addCommand(command: new Command( ->addCommand(command: new Command(
name: 'showincludes', name : 'showincludes',
callback: function () { callback : function () {
$this->checkShowIncludes(); $this->checkShowIncludes();
}, },
description: 'Shows needed setting on panels')) description: 'Shows needed setting on panels'))
->addCommand(command: new Command( ->addCommand(command: new Command(
name: 'generatekey', name : 'generatekey',
callback: function () { callback : function () {
$this->checkGenerateKey(); $this->checkGenerateKey();
}, },
description: 'Generates a a new key for encryption')) description: 'Generates a a new key for encryption'))
->addCommand(command: new Command( ->addCommand(command: new Command(
name: 'setup', name : 'setup',
callback: function () { callback : function () {
$this->checkSetup(); $this->checkSetup();
}, },
mandatoryParameters: ['username'], mandatoryParameters: ['username'],
description: 'Adapt filesystem permissions (requires elaborated permissions)')) description : 'Adapt filesystem permissions (requires elaborated permissions)'))
->addCommand(command: new Command( ->addCommand(command: new Command(
name: 'version', name : 'version',
callback: function () { callback : function () {
$this->checksVersion(); $this->checksVersion();
}, },
optionalParameters: ['major:minor:patch'], optionalParameters: ['major:minor:patch'],
description: 'Read or set the bindApi version in the database'))) description : 'Read or set the bindApi version in the database')))
->addCommandGroup(commandGroup: (new CommandGroup(name: 'panels', description: 'all KeyHelp systems configured')) ->addCommandGroup(commandGroup: (new CommandGroup(name: 'panels', description: 'all KeyHelp systems configured'))
->addCommand(command: new Command( ->addCommand(command: new Command(
name: 'list', name : 'list',
callback: function () { callback: function () {
$this->panelsList(); $this->panelsList();
})) }))
->addCommand(command: new Command( ->addCommand(command: new Command(
name: 'create', name : 'create',
callback: function () { callback : function () {
$this->panelsCreate(); $this->panelsCreate();
}, },
mandatoryParameters: ['name'], mandatoryParameters: ['name'],
optionalParameters: ['A=<IPv4>', 'AAAA=<IPv6>', 'apikey=<API-Key>'])) optionalParameters : ['A=<IPv4>', 'AAAA=<IPv6>', 'apikey=<API-Key>']))
->addCommand(command: new Command( ->addCommand(command: new Command(
name: 'update', name : 'update',
callback: function () { callback : function () {
$this->panelsUpdate(); $this->panelsUpdate();
}, },
mandatoryParameters: ['ID'], mandatoryParameters: ['ID'],
optionalParameters: ['name=<name>', 'A=<IPv4>', 'AAAA=<IPv6>', 'apikey=<API-Key>', 'self=<0|1>'])) optionalParameters : ['name=<name>', 'A=<IPv4>', 'AAAA=<IPv6>', 'apikey=<API-Key>', 'self=<0|1>']))
->addCommand(command: new Command( ->addCommand(command: new Command(
name: 'delete', name : 'delete',
callback: function () { callback : function () {
$this->panelsDelete(); $this->panelsDelete();
}, },
mandatoryParameters: ['ID'])) mandatoryParameters: ['ID']))
->addCommand(command: new Command( ->addCommand(command: new Command(
name: 'apiping', name : 'apiping',
callback: function () { callback : function () {
$this->apiPing(type: 'panel'); $this->apiPing(type: 'panel');
}, },
optionalParameters: ['ID']))) optionalParameters: ['ID'])))
->addCommandGroup(commandGroup: (new CommandGroup(name: 'nameservers', description: 'available nameservers')) ->addCommandGroup(commandGroup: (new CommandGroup(name: 'nameservers', description: 'available nameservers'))
->addCommand(command: new Command( ->addCommand(command: new Command(
name: 'list', name : 'list',
callback: function () { callback: function () {
$this->nameserversList(); $this->nameserversList();
})) }))
->addCommand(command: new Command( ->addCommand(command: new Command(
name: 'create', name : 'create',
callback: function () { callback : function () {
$this->nameserversCreate(); $this->nameserversCreate();
}, },
mandatoryParameters: ['name'], mandatoryParameters: ['name'],
optionalParameters: ['A=<IPv4>', 'AAAA=<IPv6>', 'apikey=<API-Key>'])) optionalParameters : ['A=<IPv4>', 'AAAA=<IPv6>', 'apikey=<API-Key>']))
->addCommand(command: new Command( ->addCommand(command: new Command(
name: 'update', name : 'update',
callback: function () { callback : function () {
$this->nameserversUpdate(); $this->nameserversUpdate();
}, },
mandatoryParameters: ['ID'], mandatoryParameters: ['ID'],
optionalParameters: ['name=<name>', 'A=<IPv4>', 'AAAA=<IPv6>', 'apikey=<API-Key>'])) optionalParameters : ['name=<name>', 'A=<IPv4>', 'AAAA=<IPv6>', 'apikey=<API-Key>']))
->addCommand(command: new Command( ->addCommand(command: new Command(
name: 'delete', name : 'delete',
callback: function () { callback : function () {
$this->nameserversDelete(); $this->nameserversDelete();
}, },
mandatoryParameters: ['ID'])) mandatoryParameters: ['ID']))
->addCommand(command: new Command( ->addCommand(command: new Command(
name: 'apiping', name : 'apiping',
callback: function () { callback : function () {
$this->apiPing(type: 'nameserver'); $this->apiPing(type: 'nameserver');
}, },
optionalParameters: ['ID']))) optionalParameters: ['ID'])))
->addCommandGroup(commandGroup: (new CommandGroup(name: 'domains', description: 'configured domains')) ->addCommandGroup(commandGroup: (new CommandGroup(name: 'domains', description: 'configured domains'))
->addCommand(command: new Command( ->addCommand(command: new Command(
name: 'list', name : 'list',
callback: function () { callback: function () {
$this->domainsList(); $this->domainsList();
})) }))
->addCommand(command: new Command( ->addCommand(command: new Command(
name: 'refresh', name : 'refresh',
callback: function () { callback : function () {
$this->domainsRefresh(); $this->domainsRefresh();
}, },
// mandatoryParameters: ['name'], // mandatoryParameters: ['name'],
@ -189,56 +196,81 @@ class CLIController
description: 'Refresh domains'))) description: 'Refresh domains')))
->addCommandGroup(commandGroup: (new CommandGroup(name: 'dyndns', description: 'handle DynDNS entries')) ->addCommandGroup(commandGroup: (new CommandGroup(name: 'dyndns', description: 'handle DynDNS entries'))
->addCommand(command: new Command( ->addCommand(command: new Command(
name: 'list', name : 'list',
callback: function () { callback: function () {
$this->dynDnsList(); $this->dynDnsList();
})) }))
->addCommand(command: new Command( ->addCommand(command: new Command(
name: 'create', name : 'create',
callback: function () { callback : function () {
$this->dynDnsCreate(); $this->dynDnsCreate();
}, },
mandatoryParameters: ['hostname.example.com', 'password'], mandatoryParameters: ['hostname.example.com', 'password'],
optionalParameters: ['A=<IPv4>', 'AAAA=<IPv6>'], optionalParameters : ['A=<IPv4>', 'AAAA=<IPv6>'],
description: 'FQDN within a domain where this server is master')) description : 'FQDN within a domain where this server is master'))
->addCommand(command: new Command( ->addCommand(command: new Command(
name: 'update', name : 'update',
callback: function () { callback : function () {
$this->dynDnyUpdate(); $this->dynDnyUpdate();
}, },
mandatoryParameters: ['hostname.example.com',], mandatoryParameters: ['hostname.example.com',],
optionalParameters: ['password=<password>', 'A=<IPv4>', 'AAAA=<IPv6>'])) optionalParameters : ['password=<password>', 'A=<IPv4>', 'AAAA=<IPv6>']))
->addCommand(command: new Command( ->addCommand(command: new Command(
name: 'delete', name : 'delete',
callback: function () { callback : function () {
$this->dynDnsDelete(); $this->dynDnsDelete();
}, },
mandatoryParameters: ['ID']))) mandatoryParameters: ['ID'])))
->addCommandGroup(commandGroup: (new CommandGroup(name: 'apikeys', description: 'API keys to access this bindAPI')) ->addCommandGroup(commandGroup: (new CommandGroup(name: 'apikeys', description: 'API keys to access this bindAPI'))
->addCommand(command: new Command( ->addCommand(command: new Command(
name: 'list', name : 'list',
callback: function () { callback: function () {
$this->apikeysList(); $this->apikeysList();
})) }))
->addCommand(command: new Command( ->addCommand(command: new Command(
name: 'create', name : 'create',
callback: function () { callback : function () {
$this->apikeysCreate(); $this->apikeysCreate();
}, },
optionalParameters: ['name=<name>'])) optionalParameters: ['name=<name>']))
->addCommand(command: new Command( ->addCommand(command: new Command(
name: 'update', name : 'update',
callback: function () { callback : function () {
$this->apikeysUpdate(); $this->apikeysUpdate();
}, },
mandatoryParameters: ['ID',], mandatoryParameters: ['ID',],
optionalParameters: ['name=<name>'])) optionalParameters : ['name=<name>']))
->addCommand(command: new Command( ->addCommand(command: new Command(
name: 'delete', name : 'delete',
callback: function () { callback : function () {
$this->apikeysDelete(); $this->apikeysDelete();
}, },
mandatoryParameters: ['ID']))); mandatoryParameters: ['ID'])))
->addCommandGroup(commandGroup: (new CommandGroup(name: 'migrations', description: 'maintain database migrations'))
->addCommand(command: new Command(
name : 'status',
callback : function () {
$this->migrationsStatus();
},
description: 'List information about migrations'
))
->addCommand(command: new Command(
name : 'make',
callback : function () {
$this->migrationsMake();
},
description: 'Build a new migration file'
))
->addCommand(command: new Command(
name : 'migrate',
callback : function () {
$this->migrationsMigrate();
},
description: 'Apply a new migration file'
))
);
// ->addCommandGroup(commandGroup: (new CommandGroup(name: 'webmail', description: 'manage webmail setup')) // ->addCommandGroup(commandGroup: (new CommandGroup(name: 'webmail', description: 'manage webmail setup'))
// ->addCommand(command: new Command( // ->addCommand(command: new Command(
// name: 'check', // name: 'check',
@ -265,7 +297,7 @@ class CLIController
function runCheckSetup(): void function runCheckSetup(): void
{ {
if (!$this->domainController->checkPermissions(quiet: true)) { if (!$this->domainController->checkPermissions(quiet: true)) {
echo COLOR_RED . 'You need to setup the bindAPI permission first.' . COLOR_DEFAULT .PHP_EOL; echo COLOR_RED . 'You need to setup the bindAPI permission first.' . COLOR_DEFAULT . PHP_EOL;
echo 'Run ' . COLOR_YELLOW . './bin/console check:setup' . COLOR_DEFAULT . ' as root or with sudo.' . PHP_EOL; echo 'Run ' . COLOR_YELLOW . './bin/console check:setup' . COLOR_DEFAULT . ' as root or with sudo.' . PHP_EOL;
} }
@ -398,7 +430,7 @@ class CLIController
// check /etc/bind/local.zones permissions // check /etc/bind/local.zones permissions
echo 'Found ' . COLOR_YELLOW . $this->domainController->localZoneFile . COLOR_DEFAULT . '.' . PHP_EOL; echo 'Found ' . COLOR_YELLOW . $this->domainController->localZoneFile . COLOR_DEFAULT . '.' . PHP_EOL;
echo 'Check permissions for ' . COLOR_YELLOW . $this->domainController->localZoneFile . COLOR_DEFAULT . ' …' ; echo 'Check permissions for ' . COLOR_YELLOW . $this->domainController->localZoneFile . COLOR_DEFAULT . ' …';
// dont repeat yourself, use check from DomainController FIXME // dont repeat yourself, use check from DomainController FIXME
$this->domainController->checkPermissions(impersonatedUserId: $impersonatedUserId); $this->domainController->checkPermissions(impersonatedUserId: $impersonatedUserId);
@ -485,19 +517,19 @@ class CLIController
if (empty($panel->getA())) { if (empty($panel->getA())) {
$panelRequest = $this->apiController->sendCommand( $panelRequest = $this->apiController->sendCommand(
requestType: 'GET', requestType: 'GET',
serverName: $panel->getName(), serverName : $panel->getName(),
versionIP: 6, versionIP : 6,
apiKey: $decryptedKey, apiKey : $decryptedKey,
command: '/server', command : '/server',
serverType: 'panel'); serverType : 'panel');
} else { } else {
$panelRequest = $this->apiController->sendCommand( $panelRequest = $this->apiController->sendCommand(
requestType: 'GET', requestType: 'GET',
serverName: $panel->getName(), serverName : $panel->getName(),
versionIP: 4, versionIP : 4,
apiKey: $decryptedKey, apiKey : $decryptedKey,
command: '/server', command : '/server',
serverType: 'panel'); serverType : 'panel');
} }
$panelData = json_decode(json: $panelRequest['data']); $panelData = json_decode(json: $panelRequest['data']);
if (!empty($panelData)) { if (!empty($panelData)) {
@ -512,20 +544,20 @@ class CLIController
if (empty($panel->getA())) { if (empty($panel->getA())) {
$result = $this->apiController->sendCommand( $result = $this->apiController->sendCommand(
requestType: 'GET', requestType: 'GET',
serverName: $panel->getName(), serverName : $panel->getName(),
versionIP: 6, versionIP : 6,
apiKey: $decryptedKey, apiKey : $decryptedKey,
command: 'domains?sort=domain&subdomains=false', command : 'domains?sort=domain&subdomains=false',
serverType: 'panel' serverType : 'panel'
); );
} else { } else {
$result = $this->apiController->sendCommand( $result = $this->apiController->sendCommand(
requestType: 'GET', requestType: 'GET',
serverName: $panel->getName(), serverName : $panel->getName(),
versionIP: 4, versionIP : 4,
apiKey: $decryptedKey, apiKey : $decryptedKey,
command: 'domains?sort=domain&subdomains=false', command : 'domains?sort=domain&subdomains=false',
serverType: 'panel'); serverType : 'panel');
} }
if (!empty($result['error'])) { if (!empty($result['error'])) {
@ -551,7 +583,7 @@ class CLIController
try { try {
$domainObject = $mapper->map(json: $domain, object: new KeyHelpDomain()); $domainObject = $mapper->map(json: $domain, object: new KeyHelpDomain());
} catch (JsonMapper_Exception $e) { } catch (JsonMapper_Exception $e) {
die($e->getMessage() . PHP_EOL); exit($e->getMessage() . PHP_EOL);
} }
$tmpDomainList[] = $domainObject; $tmpDomainList[] = $domainObject;
if (strlen(string: $domain->domain) > $maxDomainNameLength) { if (strlen(string: $domain->domain) > $maxDomainNameLength) {
@ -578,7 +610,7 @@ class CLIController
try { try {
sodium_memzero(string: $decryptedKey); sodium_memzero(string: $decryptedKey);
} catch (SodiumException $e) { } catch (SodiumException $e) {
die($e->getMessage() . PHP_EOL); exit($e->getMessage() . PHP_EOL);
} }
} }
@ -673,19 +705,19 @@ class CLIController
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: $decryptedKey, apiKey : $decryptedKey,
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: $decryptedKey(), apiKey : $decryptedKey(),
command: 'domains/name/', command : 'domains/name/',
serverType: 'nameserver' . $domainName); serverType : 'nameserver' . $domainName);
} }
switch ($result['header']) { switch ($result['header']) {
@ -706,21 +738,21 @@ class CLIController
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: $decryptedKey, apiKey : $decryptedKey,
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: $decryptedKey(), apiKey : $decryptedKey(),
command: 'domains', command : 'domains',
serverType: 'nameserver', serverType : 'nameserver',
body: $body); body : $body);
} }
if ($create['header'] != 201) { if ($create['header'] != 201) {
print_r(value: $create); print_r(value: $create);
@ -928,11 +960,15 @@ class CLIController
} else { } else {
$servers = $this->nameserverRepository->findAll(); $servers = $this->nameserverRepository->findAll();
} }
if ($servers) {
foreach ($servers as $server) { foreach ($servers as $server) {
if (!$this->checkPing(server: $server, type: $type)) { if (!$this->checkPing(server: $server, type: $type)) {
$error = true; $error = true;
} }
} }
} else {
echo 'No Servers of type ' . $type . ' defined';
}
} }
if ($error) { if ($error) {
exit(1); exit(1);
@ -944,8 +980,7 @@ class CLIController
/** /**
* @return int|void * @return int|void
*/ */
public public function getId()
function getId()
{ {
if (!empty($this->arguments[1])) { if (!empty($this->arguments[1])) {
$id = intval(value: $this->arguments[1] ?? 0); $id = intval(value: $this->arguments[1] ?? 0);
@ -960,17 +995,9 @@ class CLIController
return $id; return $id;
} }
/** public function checkPing(Panel|Nameserver $server, string $type): bool
* @param Panel|Nameserver $server
* @param String $type
*
* @return bool
*/
public
function checkPing(Panel|Nameserver $server, string $type): bool
{ {
$this->logger->debug(message: "checkPing() - server, type: " . $server->getName() . ', ' . $type); $this->logger->debug(message: "checkPing() - server, type: " . $server->getName() . ', ' . $type);
$error = false; $error = false;
if ($type == 'nameserver') { if ($type == 'nameserver') {
@ -989,6 +1016,8 @@ class CLIController
$encryptionKey = $this->configController->getConfig(configKey: 'encryptionKey'); $encryptionKey = $this->configController->getConfig(configKey: 'encryptionKey');
$decryptedKey = $this->encryptionController->safeDecrypt(encrypted: $server->getApikey(), key: $encryptionKey); $decryptedKey = $this->encryptionController->safeDecrypt(encrypted: $server->getApikey(), key: $encryptionKey);
echo 'server: ' . $server->getName() . PHP_EOL;
echo 'decrypted key: ' . $decryptedKey . PHP_EOL;
$a = $server->getA() ?? ''; $a = $server->getA() ?? '';
if (!empty($a)) { if (!empty($a)) {
@ -998,11 +1027,11 @@ class CLIController
} }
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: $decryptedKey, apiKey : $decryptedKey,
command: 'ping', command : 'ping',
serverType: $type)) { serverType : $type)) {
if (!$this->configController->getConfig(configKey: 'quiet')) { if (!$this->configController->getConfig(configKey: 'quiet')) {
if ($result['data'] == 'pong') { if ($result['data'] == 'pong') {
echo ' ' . COLOR_GREEN . $result['data']; echo ' ' . COLOR_GREEN . $result['data'];
@ -1025,11 +1054,11 @@ class CLIController
} }
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: $decryptedKey, apiKey : $decryptedKey,
command: 'ping', command : 'ping',
serverType: $type)) { serverType : $type)) {
if (!$this->configController->getConfig(configKey: 'quiet')) { if (!$this->configController->getConfig(configKey: 'quiet')) {
if ($result['data'] == 'pong') { if ($result['data'] == 'pong') {
echo ' ' . COLOR_GREEN . $result['data']; echo ' ' . COLOR_GREEN . $result['data'];
@ -1047,7 +1076,7 @@ class CLIController
try { try {
sodium_memzero(string: $decryptedKey); sodium_memzero(string: $decryptedKey);
} catch (SodiumException $e) { } catch (SodiumException $e) {
die($e->getMessage() . PHP_EOL); exit($e->getMessage() . PHP_EOL);
} }
if (!$this->configController->getConfig(configKey: 'quiet')) { if (!$this->configController->getConfig(configKey: 'quiet')) {
@ -1068,7 +1097,7 @@ class CLIController
try { try {
$apikeyRand = bin2hex(string: random_bytes(length: 24)); $apikeyRand = bin2hex(string: random_bytes(length: 24));
} catch (Exception $e) { } catch (Exception $e) {
die($e->getMessage() . PHP_EOL); exit($e->getMessage() . PHP_EOL);
} }
$passphrase = password_hash(password: $apiKeyPrefix . '.' . $apikeyRand, algo: PASSWORD_ARGON2ID); $passphrase = password_hash(password: $apiKeyPrefix . '.' . $apikeyRand, algo: PASSWORD_ARGON2ID);
@ -1621,19 +1650,19 @@ class CLIController
if (!empty($panel->getAaaa())) { if (!empty($panel->getAaaa())) {
$result = $this->apiController->sendCommand( $result = $this->apiController->sendCommand(
requestType: 'POST', requestType: 'POST',
serverName: $panel->getName(), serverName : $panel->getName(),
versionIP: 6, versionIP : 6,
apiKey: $decryptedKey, apiKey : $decryptedKey,
command: 'dyndns/' . $hostName, command : 'dyndns/' . $hostName,
serverType: 'nameserver'); serverType : 'nameserver');
} else { } else {
$result = $this->apiController->sendCommand( $result = $this->apiController->sendCommand(
requestType: 'POST', requestType: 'POST',
serverName: $panel->getName(), serverName : $panel->getName(),
versionIP: 4, versionIP : 4,
apiKey: $decryptedKey(), apiKey : $decryptedKey(),
command: 'dyndns/' . $hostName, command : 'dyndns/' . $hostName,
serverType: 'nameserver'); serverType : 'nameserver');
} }
if ($result['header'] == 200) { if ($result['header'] == 200) {
@ -1665,7 +1694,7 @@ class CLIController
echo PHP_EOL; echo PHP_EOL;
exit(0); exit(0);
} catch (SodiumException $e) { } catch (SodiumException $e) {
die($e->getMessage() . PHP_EOL); exit($e->getMessage() . PHP_EOL);
} }
} }
@ -1683,23 +1712,26 @@ class CLIController
$encryptionKey = $this->configController->getConfig(configKey: 'encryptionKey'); $encryptionKey = $this->configController->getConfig(configKey: 'encryptionKey');
$decryptedKey = $this->encryptionController->safeDecrypt(encrypted: $panel->getApikey(), key: $encryptionKey); $decryptedKey = $this->encryptionController->safeDecrypt(encrypted: $panel->getApikey(), key: $encryptionKey);
$currentDomains = $this->domainRepository->findByPanel(name: $panel->getName());
var_dump($currentDomains);
if (empty($panel->getA())) { if (empty($panel->getA())) {
$result = $this->apiController->sendCommand( $result = $this->apiController->sendCommand(
requestType: 'GET', requestType: 'GET',
serverName: $panel->getName(), serverName : $panel->getName(),
versionIP: 6, versionIP : 6,
apiKey: $decryptedKey, apiKey : $decryptedKey,
command: 'domains?sort=domain&subdomains=false', command : 'domains?sort=domain&subdomains=false',
serverType: 'panel' serverType : 'panel'
); );
} else { } else {
$result = $this->apiController->sendCommand( $result = $this->apiController->sendCommand(
requestType: 'GET', requestType: 'GET',
serverName: $panel->getName(), serverName : $panel->getName(),
versionIP: 4, versionIP : 4,
apiKey: $decryptedKey, apiKey : $decryptedKey,
command: 'domains?sort=domain&subdomains=false', command : 'domains?sort=domain&subdomains=false',
serverType: 'panel'); serverType : 'panel');
} }
if (!empty($result['error'])) { if (!empty($result['error'])) {
@ -1718,25 +1750,39 @@ class CLIController
foreach ($domains as $domain) { foreach ($domains as $domain) {
$domainCount++; $domainCount++;
echo COLOR_YELLOW . ' ' . $domain->domain; echo COLOR_YELLOW . ' ' . $domain->domain;
echo PHP_EOL;
if ($domain = $this->domainRepository->findByName(name: $domain->domain)) { if ($domain = $this->domainRepository->findByName(name: $domain->domain)) {
$currentPanel = $domain->getPanel(); $currentPanel = $domain->getPanel();
$panelName = $panel->getName(); $panelName = $panel->getName();
if ($currentPanel !== $panelName) { echo 'current Panel: ' . $panelName . PHP_EOL;
echo 'panel name: ' . $panelName . PHP_EOL;
if (strcmp(string1: $currentPanel, string2: $panelName)) {
$domain->setPanel(panel: $panelName); $domain->setPanel(panel: $panelName);
} }
$this->domainRepository->update(domain: $domain); $this->domainRepository->update(domain: $domain);
echo COLOR_DEFAULT . ' updated to: ' . COLOR_YELLOW .$panelName; echo COLOR_DEFAULT . ' updated to: ' . COLOR_YELLOW . $panelName;
echo COLOR_GREEN . ' OK' . COLOR_DEFAULT . PHP_EOL; echo COLOR_GREEN . ' OK' . COLOR_DEFAULT . PHP_EOL;
} else { } else {
$newDomain = new Domain(name: $domain->getName(), panel: $panel->getName()); $newDomain = new Domain(name: $domain->getName(), panel: $panel->getName());
$result = $this->domainRepository->insert(domain: $newDomain); $result = $this->domainRepository->insert(domain: $newDomain);
echo COLOR_DEFAULT . ' has been created with id ' . COLOR_YELLOW . $result . COLOR_DEFAULT . '.' . PHP_EOL; echo COLOR_DEFAULT . ' has been created with id ' . COLOR_YELLOW . $result . COLOR_DEFAULT . '.' . PHP_EOL;
} }
unset($currentDomains[$domain->getName()]);
} }
} }
if ($domainCount == 0) { if ($domainCount == 0) {
echo 'No second level domains found.' . COLOR_DEFAULT . PHP_EOL; echo 'No second level domains found.' . COLOR_DEFAULT . PHP_EOL;
} }
//clean up stale domains
if (count($currentDomains) > 0) {
echo 'Dropping stale domains:' . PHP_EOL;
foreach ($currentDomains as $domain) {
echo $domain->getName() . PHP_EOL;
$this->domainRepository->delete(domain: $domain);
}
}
} }
$this->domainController->updateSlaveZones(); $this->domainController->updateSlaveZones();
} }
@ -1786,22 +1832,22 @@ class CLIController
} }
$result = $this->apiController->sendCommand( $result = $this->apiController->sendCommand(
requestType: 'GET', requestType: 'GET',
serverName: $panel->getName(), serverName : $panel->getName(),
versionIP: 6, versionIP : 6,
apiKey: $decryptedKey, apiKey : $decryptedKey,
command: 'domains/name/' . $webmailDomain, command : 'domains/name/' . $webmailDomain,
serverType: 'panel'); serverType : 'panel');
} else { } else {
if (!$quiet) { if (!$quiet) {
echo 'Check using IPv4: ' . COLOR_YELLOW . $panel->getA() . COLOR_DEFAULT . PHP_EOL; echo 'Check using IPv4: ' . COLOR_YELLOW . $panel->getA() . COLOR_DEFAULT . PHP_EOL;
} }
$result = $this->apiController->sendCommand( $result = $this->apiController->sendCommand(
requestType: 'GET', requestType: 'GET',
serverName: $panel->getName(), serverName : $panel->getName(),
versionIP: 4, versionIP : 4,
apiKey: $decryptedKey, apiKey : $decryptedKey,
command: 'domains/name/' . $webmailDomain, command : 'domains/name/' . $webmailDomain,
serverType: 'panel'); serverType : 'panel');
} }
if ($result['header'] === 404) { if ($result['header'] === 404) {
@ -1817,7 +1863,7 @@ class CLIController
if ($v4 = dns_get_record(hostname: $webmailDomain, type: DNS_A)[0]) { if ($v4 = dns_get_record(hostname: $webmailDomain, type: DNS_A)[0]) {
if (!$quiet) { if (!$quiet) {
echo "Found IPv4 entry: " . COLOR_YELLOW . $v4['ip'] . COLOR_DEFAULT . '.' .PHP_EOL; echo "Found IPv4 entry: " . COLOR_YELLOW . $v4['ip'] . COLOR_DEFAULT . '.' . PHP_EOL;
} }
$v4Test = $this->apiController->fileGetContents(url: $webmailDomain, versionIP: 4); $v4Test = $this->apiController->fileGetContents(url: $webmailDomain, versionIP: 4);
@ -1905,21 +1951,73 @@ class CLIController
private function checkMail(): void private function checkMail(): void
{ {
echo 'Not yet implemented.' . PHP_EOL;
} }
private function checksVersion(): void private function checksVersion(): void
{ {
echo 'Not yet implemented.' . PHP_EOL;
} }
private function dynDnyUpdate(): void private function dynDnyUpdate(): void
{ {
echo 'Not yet implemented.' . PHP_EOL;
} }
private function dynDnsDelete(): void private function dynDnsDelete(): void
{ {
echo 'Not yet implemented.' . PHP_EOL;
} }
private function webmailDelete(): void private function webmailDelete(): void
{ {
} }
}
private function migrationsStatus(): void
{
$phinx = new PhinxApplication('Phinx', '0.9.2');
// use DI later when moving to symfony
$input = new \Symfony\Component\Console\Input\ArgvInput();
$output = new \Symfony\Component\Console\Output\ConsoleOutput();
echo 'show migration status' . PHP_EOL;
$command = $phinx->find(name: 'status'); // change 'migrate' to 'status'
$arguments = [
'command' => 'status',
];
$phinxOutput = new ConsoleOutput();
$returnCode = $command->run(input: new ArrayInput(parameters: $arguments), output: $phinxOutput);
echo 'return code: ' . $returnCode . PHP_EOL;
}
private function migrationsMake()
{
$phinx = new PhinxApplication();
$phinx->add(new GenerateCommand());
$arguments = [
'command' => 'generate',
];
$output = new ConsoleOutput();
$returnCode = $phinx->run(input: new ArrayInput(parameters: $arguments), output: $output);
}
private function migrationsMigrate(): void
{
$phinx = new PhinxApplication('Phinx', '0.9.2');
echo 'show migration status' . PHP_EOL;
$command = $phinx->find(name: 'migrate');
$arguments = [
'command' => 'migrate',
];
$phinxOutput = new ConsoleOutput();
$returnCode = $command->run(input: new ArrayInput(parameters: $arguments), output: $phinxOutput);
}
}

View File

@ -9,18 +9,14 @@ class ConfigController
{ {
private array $config; private array $config;
/** public function __construct( bool $test = false)
* @param bool $quiet
* @param bool $test
*/
public function __construct(private readonly bool $quiet = false, bool $test = false)
{ {
if ($test) { if ($test) {
$configFile = dirname(path: __DIR__, levels: 2) . "/config.json.test"; $configFile = dirname(path: __DIR__, levels: 2) . "/config.json.test";
if (!file_exists(filename: $configFile)) { if (!file_exists(filename: $configFile)) {
echo 'No testing (config.json.test) config has benn setup.' . PHP_EOL; echo 'No testing (config.json.test) config has benn setup.' . PHP_EOL;
die(1); exit(1);
} }
} else { } else {
$configFile = dirname(path: __DIR__, levels: 2) . "/config.json.local"; $configFile = dirname(path: __DIR__, levels: 2) . "/config.json.local";
@ -50,13 +46,17 @@ class ConfigController
$this->config = json_decode(json: $configJSON, associative: true); $this->config = json_decode(json: $configJSON, associative: true);
$this->config['quiet'] = (bool)$quiet;
$this->config['test'] = (bool)$test; $this->config['test'] = (bool)$test;
} }
public function getConfig(string $configKey): string public function getConfig(string $configKey): string
{ {
if ($configKey === 'quiet') {
echo 'FIXME: handle quiet …';
return '';
} else {
return $this->config[$configKey]; return $this->config[$configKey];
} }
}
} }

View File

@ -44,7 +44,6 @@ class DatabaseConnection
} }
if (!$this->configController->getConfig(configKey: 'test')) { if (!$this->configController->getConfig(configKey: 'test')) {
// TODO create config => encryption key
try { try {
$sql = "SHOW TABLES"; $sql = "SHOW TABLES";
@ -54,68 +53,7 @@ class DatabaseConnection
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 'Error: Cannot find tables.' . PHP_EOL; echo 'Error: Cannot find tables.' . PHP_EOL;
if (confirm(message: 'Should I try to create them?')) { echo 'run the migration …' . PHP_EOL;
$sql = "
CREATE TABLE `apikeys` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`api_token_prefix` varchar(13) COLLATE utf8mb4_unicode_ci NOT NULL,
`api_token` varchar(255) COLLATE utf8mb4_unicode_ci 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();
$sql = "
CREATE TABLE `domains` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
`panel` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci";
$statement = $this->dbConnection->prepare(query: $sql);
$statement->execute();
$sql = "
CREATE TABLE `nameservers` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
`a` varbinary(255) DEFAULT NULL,
`aaaa` varbinary(255) DEFAULT NULL,
`apikey` varbinary(255) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci";
$statement = $this->dbConnection->prepare(query: $sql);
$statement->execute();
$sql = "
CREATE TABLE `panels` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
`a` varbinary(255) DEFAULT NULL,
`aaaa` varbinary(255) DEFAULT NULL,
`apikey` varbinary(255) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci";
$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);
} }
} catch (PDOException $exception) { } catch (PDOException $exception) {
echo $exception->getMessage() . PHP_EOL; echo $exception->getMessage() . PHP_EOL;
@ -131,13 +69,6 @@ class DatabaseConnection
} }
} }
} }
/**
* @param int $length
*
* @return string
*/
function generatePassword(int $length = 8): string function generatePassword(int $length = 8): string
{ {
$chars = '23456789bcdfhkmnprstvzBCDFHJKLMNPRSTVZ'; $chars = '23456789bcdfhkmnprstvzBCDFHJKLMNPRSTVZ';
@ -145,9 +76,6 @@ class DatabaseConnection
return mb_substr(string: $shuffled, start: 0, length: $length); return mb_substr(string: $shuffled, start: 0, length: $length);
} }
/**
* @return PDO
*/
public function getConnection(): PDO public function getConnection(): PDO
{ {
return $this->dbConnection; return $this->dbConnection;

View File

@ -299,7 +299,7 @@ class DomainController
$panelName = $domain->getPanel(); $panelName = $domain->getPanel();
if (!$panel = $this->panelRepository->findByName(name: $panelName)) { if (!$panel = $this->panelRepository->findByName(name: $panelName)) {
echo "Error: Panel $panelName doesn't exist." . PHP_EOL; echo "Error: Panel $panelName doesn't exist." . PHP_EOL;
die(); exit(1);
} }
$a = $panel->getA(); $a = $panel->getA();
$aaaa = $panel->getAaaa(); $aaaa = $panel->getAaaa();

View File

@ -28,7 +28,7 @@ class EncryptionController
sodium_memzero(string: $binKey); sodium_memzero(string: $binKey);
return $cipher; return $cipher;
} catch (Exception|SodiumException $e) { } catch (Exception|SodiumException $e) {
die($e->getMessage() . PHP_EOL); exit($e->getMessage() . PHP_EOL);
} }
} }
@ -64,7 +64,7 @@ class EncryptionController
sodium_memzero(string: $key); sodium_memzero(string: $key);
return $plain; return $plain;
} catch(Exception|SodiumException $e) { } catch(Exception|SodiumException $e) {
die($e->getMessage()); exit($e->getMessage());
} }
} }

View File

@ -32,7 +32,7 @@ class Apikey
try { try {
$this->apikey = $encryptionController->safeEncrypt(message: $this->passphrase, key: $encryptionKey); $this->apikey = $encryptionController->safeEncrypt(message: $this->passphrase, key: $encryptionKey);
} catch (Exception|SodiumException $e) { } catch (Exception|SodiumException $e) {
die($e->getMessage() . PHP_EOL); exit($e->getMessage() . PHP_EOL);
} }
} }
} }

View File

@ -44,7 +44,7 @@ class Nameserver
try { try {
$this->apikey = $encryptionController->safeEncrypt(message: $this->passphrase, key: $encryptionKey); $this->apikey = $encryptionController->safeEncrypt(message: $this->passphrase, key: $encryptionKey);
} catch (Exception|SodiumException $e) { } catch (Exception|SodiumException $e) {
die($e->getMessage() . PHP_EOL); exit($e->getMessage() . PHP_EOL);
} }
} }

View File

@ -12,16 +12,6 @@ use SodiumException;
*/ */
class Panel class Panel
{ {
/**
* @param string $name
* @param int $id
* @param string $a
* @param string $aaaa
* @param string $passphrase
* @param string $apikey
* @param string $apikeyPrefix
* @param string $self
*/
public function __construct( public function __construct(
private string $name, private string $name,
private int $id = 0, private int $id = 0,
@ -44,7 +34,7 @@ class Panel
try { try {
$this->apikey = $encryptionController->safeEncrypt(message: $this->passphrase, key: $encryptionKey); $this->apikey = $encryptionController->safeEncrypt(message: $this->passphrase, key: $encryptionKey);
} catch (Exception|SodiumException $e) { } catch (Exception|SodiumException $e) {
die($e->getMessage() . PHP_EOL); exit($e->getMessage() . PHP_EOL);
} }
} }
} }

View File

@ -12,12 +12,12 @@ use PDOException;
/** /**
* *
*/ */
class DomainRepository readonly class DomainRepository
{ {
public function __construct( public function __construct(
private readonly DatabaseConnection $databaseConnection, private DatabaseConnection $databaseConnection,
private readonly ConfigController $configController, private ConfigController $configController,
private readonly Logger $logger) private Logger $logger)
{ {
$this->logger->debug(message: "DomainRepository::__construct()"); $this->logger->debug(message: "DomainRepository::__construct()");
@ -50,12 +50,30 @@ class DomainRepository
} }
} }
public function findByPanel(string $name): array
{
$this->logger->debug(message: "findByPanel($name)");
$domains = [];
$sql = "
SELECT id, name, panel
FROM . " . DatabaseConnection::TABLE_DOMAINS . "
WHERE panel = :panel";
try {
$statement = $this->databaseConnection->getConnection()->prepare(query: $sql);
$statement->bindParam(param: ':panel', var: $name);
$statement->execute();
while ($result = $statement->fetch(mode: PDO::FETCH_ASSOC)) {
$domain = new Domain(name: $result['name'], panel: $result['panel'], id: $result['id']);
$domains[$result['name']] = $domain;
}
return $domains;
} catch (PDOException $e) {
exit($e->getMessage());
}
}
/**
* @param int $id
*
* @return bool|\App\Entity\Domain
*/
public function findByID(int $id): bool|Domain public function findByID(int $id): bool|Domain
{ {
$this->logger->debug(message: "findById($id)"); $this->logger->debug(message: "findById($id)");
@ -81,11 +99,7 @@ class DomainRepository
} }
/**
* @param String $name
*
* @return \App\Entity\Domain|bool
*/
public function findByName(string $name): Domain|bool public function findByName(string $name): Domain|bool
{ {
$this->logger->debug(message: "findByName($name)"); $this->logger->debug(message: "findByName($name)");
@ -110,11 +124,6 @@ class DomainRepository
} }
/**
* @param string $host
*
* @return \App\Entity\Domain|bool
*/
public function findByHost(string $host): Domain|bool public function findByHost(string $host): Domain|bool
{ {
$this->logger->debug(message: "findByHost($host)"); $this->logger->debug(message: "findByHost($host)");
@ -137,11 +146,6 @@ class DomainRepository
} }
/**
* @param \App\Entity\Domain $domain
*
* @return string|false
*/
public function insert(Domain $domain): bool|string public function insert(Domain $domain): bool|string
{ {
$domainName = $domain->getName(); $domainName = $domain->getName();
@ -210,12 +214,6 @@ class DomainRepository
} }
} }
/**
* @param \App\Entity\Domain $domain
*
* @return int
*/
public function delete(Domain $domain): int public function delete(Domain $domain): int
{ {
$domainName = $domain->getName(); $domainName = $domain->getName();
@ -237,12 +235,6 @@ class DomainRepository
} }
} }
/**
* @param String $field
*
* @return int
*/
public function getLongestEntry(string $field): int public function getLongestEntry(string $field): int
{ {
$sql = " $sql = "

View File

@ -207,7 +207,7 @@ class NameserverRepository
try { try {
sodium_memzero(string: $apikey); sodium_memzero(string: $apikey);
} catch(SodiumException $e) { } catch(SodiumException $e) {
die($e->getMessage() . PHP_EOL); exit($e->getMessage() . PHP_EOL);
} }
return intval(value: $statement->rowCount()); return intval(value: $statement->rowCount());
} catch (PDOException $e) { } catch (PDOException $e) {

View File

@ -5,7 +5,7 @@ use App\Controller\BindAPI;
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')) {
die('Required runtime components are missing. Try running "composer install".' . PHP_EOL); exit('Required runtime components are missing. Try running "composer install".' . PHP_EOL);
} }
require dirname(path: __DIR__, levels: 2) . '/vendor/autoload.php'; require dirname(path: __DIR__, levels: 2) . '/vendor/autoload.php';
@ -38,11 +38,11 @@ if (array_key_exists(key: 'v', array: $options) || array_key_exists(key: 'versio
$authorName = $authors[0]->name; $authorName = $authors[0]->name;
$authorEmail = $authors[0]->email; $authorEmail = $authors[0]->email;
echo "Name: $name\n"; echo 'Name: $name' . PHP_EOL;
echo "Description: $description\n"; echo 'Description: $description' . PHP_EOL;
echo "Version: $version\n"; echo 'Version: $version' . PHP_EOL;
echo "Build Number: $buildNumber\n"; echo 'Build Number: $buildNumber' . PHP_EOL;
echo "Author: $authorName ($authorEmail)\n"; echo 'Author: $authorName ($authorEmail)' . PHP_EOL;
exit(0); exit(0);
} }
@ -58,7 +58,7 @@ if (array_key_exists(key: 'q', array: $options) || array_key_exists(key: 'quiet'
try { try {
$app = new BindAPI(quiet: $quiet); $app = new BindAPI();
} catch (Exception $e) { } catch (Exception $e) {
echo 'Could not initialize the application: ' . $e->getMessage() . PHP_EOL; echo 'Could not initialize the application: ' . $e->getMessage() . PHP_EOL;
exit(1); exit(1);