Compare commits

..

No commits in common. "master" and "1.0.0" have entirely different histories.

88 changed files with 4613 additions and 28860 deletions

14
.gitignore vendored
View File

@ -3,17 +3,3 @@
/config.json /config.json
/scratch /scratch
/swagger-ui/ /swagger-ui/
/config.json.local
/bindAPI.log
/reports/
/bindAPI.test.log
/.phpunit.result.cache
/config.json.dev
/config.json.test
/config.json.prod
keys.txt
/.phpunit.cache
/var/log/*
/public/openapi/bindapi.json
/public/openapi/bootstrap.php

8
.idea/.gitignore vendored Normal file
View File

@ -0,0 +1,8 @@
# Default ignored files
/shelf/
/workspace.xml
# Editor-based HTTP Client requests
/httpRequests/
# Datasource local storage ignored files
/dataSources/
/dataSources.local.xml

48
.idea/bindAPI.iml Normal file
View File

@ -0,0 +1,48 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="WEB_MODULE" version="4">
<component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/bindAPI/src" isTestSource="false" packagePrefix="App\" />
<sourceFolder url="file://$MODULE_DIR$/spec" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/tests" isTestSource="true" />
<excludeFolder url="file://$MODULE_DIR$/bindAPI/vendor/composer" />
<excludeFolder url="file://$MODULE_DIR$/bindAPI/vendor/phplucidframe/console-table" />
<excludeFolder url="file://$MODULE_DIR$/bindAPI/vendor/phpspec/prophecy" />
<excludeFolder url="file://$MODULE_DIR$/bindAPI/vendor/sebastian/comparator" />
<excludeFolder url="file://$MODULE_DIR$/bindAPI/vendor/myclabs/deep-copy" />
<excludeFolder url="file://$MODULE_DIR$/bindAPI/vendor/symfony/polyfill-ctype" />
<excludeFolder url="file://$MODULE_DIR$/bindAPI/vendor/phpdocumentor/reflection-docblock" />
<excludeFolder url="file://$MODULE_DIR$/bindAPI/vendor/phpdocumentor/type-resolver" />
<excludeFolder url="file://$MODULE_DIR$/bindAPI/vendor/phpunit/php-file-iterator" />
<excludeFolder url="file://$MODULE_DIR$/bindAPI/vendor/phpdocumentor/reflection-common" />
<excludeFolder url="file://$MODULE_DIR$/bindAPI/vendor/phpunit/php-invoker" />
<excludeFolder url="file://$MODULE_DIR$/bindAPI/vendor/webmozart/assert" />
<excludeFolder url="file://$MODULE_DIR$/bindAPI/vendor/phpunit/php-code-coverage" />
<excludeFolder url="file://$MODULE_DIR$/bindAPI/vendor/phpunit/php-text-template" />
<excludeFolder url="file://$MODULE_DIR$/bindAPI/vendor/phpunit/phpunit" />
<excludeFolder url="file://$MODULE_DIR$/bindAPI/vendor/phpunit/php-timer" />
<excludeFolder url="file://$MODULE_DIR$/bindAPI/vendor/doctrine/instantiator" />
<excludeFolder url="file://$MODULE_DIR$/bindAPI/vendor/phar-io/version" />
<excludeFolder url="file://$MODULE_DIR$/bindAPI/vendor/phar-io/manifest" />
<excludeFolder url="file://$MODULE_DIR$/bindAPI/vendor/sebastian/resource-operations" />
<excludeFolder url="file://$MODULE_DIR$/bindAPI/vendor/sebastian/exporter" />
<excludeFolder url="file://$MODULE_DIR$/bindAPI/vendor/sebastian/environment" />
<excludeFolder url="file://$MODULE_DIR$/bindAPI/vendor/sebastian/code-unit" />
<excludeFolder url="file://$MODULE_DIR$/bindAPI/vendor/sebastian/cli-parser" />
<excludeFolder url="file://$MODULE_DIR$/bindAPI/vendor/sebastian/version" />
<excludeFolder url="file://$MODULE_DIR$/bindAPI/vendor/sebastian/type" />
<excludeFolder url="file://$MODULE_DIR$/bindAPI/vendor/sebastian/lines-of-code" />
<excludeFolder url="file://$MODULE_DIR$/bindAPI/vendor/sebastian/recursion-context" />
<excludeFolder url="file://$MODULE_DIR$/bindAPI/vendor/nikic/php-parser" />
<excludeFolder url="file://$MODULE_DIR$/bindAPI/vendor/sebastian/diff" />
<excludeFolder url="file://$MODULE_DIR$/bindAPI/vendor/sebastian/code-unit-reverse-lookup" />
<excludeFolder url="file://$MODULE_DIR$/bindAPI/vendor/sebastian/complexity" />
<excludeFolder url="file://$MODULE_DIR$/bindAPI/vendor/theseer/tokenizer" />
<excludeFolder url="file://$MODULE_DIR$/bindAPI/vendor/sebastian/object-reflector" />
<excludeFolder url="file://$MODULE_DIR$/bindAPI/vendor/sebastian/object-enumerator" />
<excludeFolder url="file://$MODULE_DIR$/bindAPI/vendor/sebastian/global-state" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>

View File

@ -0,0 +1,5 @@
<component name="ProjectCodeStyleConfiguration">
<state>
<option name="PREFERRED_PROJECT_CODE_STYLE" value="Default" />
</state>
</component>

15
.idea/deployment.xml Normal file
View File

@ -0,0 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="PublishConfigData" autoUpload="Always" serverName="executor.24unix.net" autoUploadExternalChanges="true">
<serverData>
<paths name="executor.24unix.net">
<serverdata>
<mappings>
<mapping deploy="/home/users/tfunix/www" local="$PROJECT_DIR$" web="/public" />
</mappings>
</serverdata>
</paths>
</serverData>
<option name="myAutoUpload" value="ALWAYS" />
</component>
</project>

View File

@ -0,0 +1,107 @@
<component name="InspectionProjectProfileManager">
<profile version="1.0">
<option name="myName" value="Project Default" />
<inspection_tool class="DuplicatedCode" enabled="true" level="WEAK WARNING" enabled_by_default="true">
<Languages>
<language minSize="115" name="PHP" />
</Languages>
</inspection_tool>
<inspection_tool class="Eslint" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="JSClassNamingConvention" enabled="true" level="WARNING" enabled_by_default="true">
<option name="m_minLength" value="3" />
</inspection_tool>
<inspection_tool class="JSXNamespaceValidation" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
<inspection_tool class="MsBuiltinInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="MsOrderByInspection" enabled="false" level="ERROR" enabled_by_default="false" />
<inspection_tool class="MysqlLoadDataPathInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="MysqlParsingInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="PhpArgumentWithoutNamedIdentifierInspection" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="PhpArrayShapeAttributeCanBeAddedInspection" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
<inspection_tool class="PhpCSValidationInspection" enabled="false" level="WEAK WARNING" enabled_by_default="false">
<option name="CODING_STANDARD" value="Custom" />
<option name="CUSTOM_RULESET_PATH" value="$PROJECT_DIR$/phpcs.xml.dist" />
<option name="USE_INSTALLED_PATHS" value="true" />
<option name="INSTALLED_PATHS" value="$PROJECT_DIR$/vendor/doctrine/coding-standard/lib/Doctrine" />
<option name="EXTENSIONS" value="php,js,css,inc" />
</inspection_tool>
<inspection_tool class="PhpCastIsUnnecessaryInspection" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
<inspection_tool class="PhpClassNamingConventionInspection" enabled="true" level="WARNING" enabled_by_default="true">
<option name="m_minLength" value="3" />
<option name="m_maxLength" value="24" />
</inspection_tool>
<inspection_tool class="PhpConstantNamingConventionInspection" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="PhpFunctionNamingConventionInspection" enabled="true" level="WARNING" enabled_by_default="true">
<option name="m_regex" value="[a-z][A-Za-z\d]*" />
<option name="m_minLength" value="2" />
<option name="m_maxLength" value="50" />
</inspection_tool>
<inspection_tool class="PhpMethodNamingConventionInspection" enabled="true" level="WARNING" enabled_by_default="true">
<option name="m_minLength" value="2" />
<option name="m_maxLength" value="48" />
</inspection_tool>
<inspection_tool class="PhpMissingDocCommentInspection" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="PhpNamedArgumentUsageInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="PhpNoReturnAttributeCanBeAddedInspection" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
<inspection_tool class="PhpNonCanonicalElementsOrderInspection" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
<inspection_tool class="PhpPropertyNamingConventionInspection" enabled="true" level="WARNING" enabled_by_default="true">
<option name="m_regex" value="[a-z][A-Z_a-z\d]*" />
<option name="m_minLength" value="1" />
<option name="m_maxLength" value="24" />
</inspection_tool>
<inspection_tool class="PhpPureAttributeCanBeAddedInspection" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
<inspection_tool class="PhpVariableNamingConventionInspection" enabled="true" level="WARNING" enabled_by_default="true">
<option name="m_regex" value="[a-z][A-Za-z\d]*" />
<option name="m_minLength" value="1" />
<option name="m_maxLength" value="24" />
</inspection_tool>
<inspection_tool class="SqlAddNotNullColumnInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="SqlAggregatesInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="SqlAmbiguousColumnInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="SqlAutoIncrementDuplicateInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="SqlCallNotationInspection" enabled="false" level="ERROR" enabled_by_default="false" />
<inspection_tool class="SqlCaseVsCoalesceInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="SqlCaseVsIfInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="SqlCheckUsingColumnsInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="SqlConstantConditionInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="SqlConstantExpressionInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="SqlCurrentSchemaInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="SqlDeprecateTypeInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="SqlDerivedTableAliasInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="SqlDialectInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="SqlDropIndexedColumnInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="SqlDtInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="SqlDuplicateColumnInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="SqlIdentifierInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="SqlIllegalCursorStateInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="SqlInsertIntoGeneratedColumnInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="SqlInsertNullIntoNotNullInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="SqlInsertValuesInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="SqlJoinWithoutOnInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="SqlMisleadingReferenceInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="SqlMissingReturnInspection" enabled="false" level="ERROR" enabled_by_default="false" />
<inspection_tool class="SqlMultipleLimitClausesInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="SqlNoDataSourceInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="SqlNullComparisonInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="SqlRedundantAliasInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="SqlRedundantCodeInCoalesceInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="SqlRedundantElseNullInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="SqlRedundantLimitInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="SqlRedundantOrderingDirectionInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="SqlResolveInspection" enabled="false" level="ERROR" enabled_by_default="false" />
<inspection_tool class="SqlShadowingAliasInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="SqlShouldBeInGroupByInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="SqlSideEffectsInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="SqlSignatureInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="SqlStorageInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="SqlStringLengthExceededInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="SqlTransactionStatementInTriggerInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="SqlTriggerTransitionInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="SqlTypeInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="SqlUnicodeStringLiteralInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="SqlUnreachableCodeInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="SqlUnusedCteInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="SqlUnusedSubqueryItemInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="SqlUnusedVariableInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="SqlWithoutWhereInspection" enabled="false" level="WARNING" enabled_by_default="false" />
</profile>
</component>

8
.idea/modules.xml Normal file
View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/bindAPI.iml" filepath="$PROJECT_DIR$/.idea/bindAPI.iml" />
</modules>
</component>
</project>

11
.idea/php.xml Normal file
View File

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="PhpProjectSharedConfiguration" php_language_level="8.1">
<option name="suggestChangeDefaultLanguageLevel" value="false" />
</component>
<component name="PhpUnit">
<phpunit_settings>
<PhpUnitSettings custom_loader_path="$PROJECT_DIR$/vendor/autoload.php" phpunit_phar_path="" />
</phpunit_settings>
</component>
</project>

7
.idea/vcs.xml Normal file
View File

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$" vcs="Git" />
<mapping directory="$PROJECT_DIR$/swagger-ui" vcs="Git" />
</component>
</project>

10
LICENCE
View File

@ -1,10 +0,0 @@
In short: it's just the MIT license:
Copyright 2022 Micha Espey (tracer@24unix.net)
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

BIN
NOTES

Binary file not shown.

View File

@ -3,12 +3,7 @@
3. [Installation](#3-installation) 3. [Installation](#3-installation)
4. [Configuration](#4-configuration) 4. [Configuration](#4-configuration)
5. [The API](#5-the-api) 5. [The API](#5-the-api)
6. [DynDNS](#6-dyndns) 6. [Conclusion](#6-conclusion)
7. [Conclusion](#7-conclusion)
NOTICE: This documentation is not current as of September 2022.
After I finished the refactoring I'll upgrade it.
<a name="overview"></a> <a name="overview"></a>
# 1. Overview # 1. Overview
@ -29,7 +24,7 @@ The CLI is used to perform configuration and some checks:
* check * check
- Permissions: The API needs to be able to access some files and create new ones - Permissions: The API needs to be able to access some files and create new ones
- Panels: This checks one or all panels if every nameserver is aware of all domains - Panels: This checks one or all panels if every nameserver is aware of all domains
- Domain: Check is all support files for domains on this NS are existing - Domain: TODO
* panels * panels
- List: List all panels which are configured on this server - List: List all panels which are configured on this server
- Create: Adds a new panel to the configuration - Create: Adds a new panel to the configuration
@ -44,16 +39,19 @@ The CLI is used to perform configuration and some checks:
* apikeys * apikeys
- manage the keys to access this nameserver via API - manage the keys to access this nameserver via API
## 2.2. API # 2.2. API
![OpenAPI](https://bindapi.24unix.net/assets/bindAPI_api1.png) ![OpenAPI](https://bindapi.24unix.net/assets/bindAPI_api1.png)
The API is a RESTful API, there is a self explaining Swagger/OpenAPI available. The APi is a RESTful API, there is a self explaining Swagger/OpenAPI available.
<a name="installation"></a> <a name="installation"></a>
# 3. Installation # 3. Installation
You can install the bindAPI on either a standalone server or an existing KeyHelp Panel. However, slave zones are only managed for masters which lie on Keyhelp panels. You can install the bindAPi on either a standalone server or an existing KeyHelp Panel.
However, slave zones are only managed for masters which lie on Keyhelp panels.
## 3.1. Installation on a KeyHelp panel ## 3.1. Installation on a KeyHelp panel
@ -96,7 +94,7 @@ Here I will install it under /usr/local/bin, in the example with the standalone
`wget https://getcomposer.org/installer` `wget https://getcomposer.org/installer`
`php installer --install-dir=/usr/local/bin --filename=composer` `php composer-setup.php --install-dir=/usr/local/bin --filename=composer`
Now we can change into our new user, remind to give him shell access in the panel. Now we can change into our new user, remind to give him shell access in the panel.
@ -117,13 +115,7 @@ Remove the defaults files:
`rm *` `rm *`
Next, we'll need to fetch the bindAPI. As of now, the latest release is 1.0.1: Next, we'll need to fetch the bindAPI (currently it has no release tag, that will change later)
https://git.24unix.net/tracer/bindAPI/archive/1.0.1.tar.gz
I'd suggest checking here for the latest version:
https://git.24unix.net/tracer/bindAPI/releases
Or just use git to check out the latest update:
``` ```
git clone https://git.24unix.net/tracer/bindAPI.git git clone https://git.24unix.net/tracer/bindAPI.git
@ -140,11 +132,11 @@ We need to pull the dependencies for composer:
`/usr/bin/keyhelp-php81 /usr/local/bin/composer update` `/usr/bin/keyhelp-php81 /usr/local/bin/composer update`
You might notice a quite strange command. We need to call php with full path, and explicitly the 8.1 version. KeyHelp You might notice a quite strange command.
relies on the default PHP installation, so the php binary will always point to 7.4 when you're on Debian Bullseye. We need to call php with full path, and explicitly the 8.1 version.
KeyHelp relies on the default PHP installation, so the php binary will always point to 7.4 when your on Debian Bullseye.
So, in bin/console the path to /usr/bin/keyhelp-php81 is hardcoded after the shebang, a step we have to remind if we So, in bin/console the path to /usr/bin/keyhelp-php81 is hardcoded after the shebang, a step we have to remind if we install the standalone version.
install the standalone version.
Now make the CLI executable: Now make the CLI executable:
@ -159,19 +151,19 @@ Should I create a new config based on config.json.sample? (y/N): n
You first have to setup the bindAPI. Bye. You first have to setup the bindAPI. Bye.
``` ```
So now we can head back to our panel and set the Document root to /home/users/tfunix/ns1.24unix.net/bindAPI/public. So now we can head back to our panel and set the Document root to
/home/users/tfunix/ns1.24unix.net/bindAPI/public.
Additionally, we have to change the open_basedir directive: Additionally, we have to change the open_basedir directive:
##DOCROOT##/www:##DOCROOT##/files:##DOCROOT##/tmp:/etc/bind:/etc/bind/local.zones
`##DOCROOT##/www:##DOCROOT##/files:##DOCROOT##/tmp:/etc/bind:/etc/bind/local.zones` TODO: Screenshot
![Php Interpreter](https://bindapi.24unix.net/assets/bindAPI_phpsetting.png)
and remove exec from disabled functions. and remove exec from disabled functions.
OK, we are finished with the installation and head over to the [4. Configuration](#4-configuration). OK, we are finished with the installation and head over to the [4. Configuration](#4-configuration).
## 3.2. Installation on a plain Debian Bullseye ## 3.2. Installation on a plain debian Bullseye
So, at first you should read and understand all steps in 3.1, as we will learn only the differences. So, at first you should read and understand all steps in 3.1, as we will learn only the differences.
@ -300,10 +292,10 @@ GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, INDEX, DROP, ALTER, CREATE TEMPORA
There is no need to run FLUSH PRIVILEGES when using GRANT! There is no need to run FLUSH PRIVILEGES when using GRANT!
``` ```
So, now it offers us the SQL statements to create a new user and database and set permissions. If were on plain debian, So, now it offers us the SQL statements to create a new user and database and set permissions.
we just can copy and paste (the password is random) this as root into mysql. If were on plain debian, we just can copy and paste (the password is random) this as root into mysql.
If we're using the panel, lets create a database and write down the credentials and update config.json. If we're using hte panel, lets create a database and write down the credentials and update config.json.
And another call to the console: And another call to the console:
@ -314,7 +306,7 @@ Should I try to create them? (y/N): y
Tables have been created. Tables have been created.
``` ```
When we now call the console it displays its options: When we now call the console it displays it's options:
![CLI Interface](https://bindapi.24unix.net/assets/bindAPI_cli.png) ![CLI Interface](https://bindapi.24unix.net/assets/bindAPI_cli.png)
@ -413,7 +405,7 @@ No second level domains found.
Keyhelp-Panel: tector.24unix.net Keyhelp-Panel: tector.24unix.net
No second level domains found. No second level domains found.
``` ```
The output is a bit ugly, maybe I'll come up with something nicer. The output is a little bit ugly, maybe I'll come up with something nicer.
So, now we have our nameservers, our panels. So, now we have our nameservers, our panels.
@ -424,7 +416,7 @@ We create a new key:
``` ```
$ ./bin/console apikeys:create $ ./bin/console apikeys:create
API key 1 has been generated. Store it in a save place, it cannot be recovered. API key 1 has been generated. Store it in a save place, it cannot be recovered.
6213acb116613.[truncated] 6213acb116613.[truncated]]
``` ```
And add it to our list of nameservers: And add it to our list of nameservers:
@ -567,7 +559,7 @@ Keyhelp-Panel: paz.24unix.net
Domain: tzazicke.de ns1.24unix.net OK ns2.24unix.net OK ns3.24unix.net OK Domain: tzazicke.de ns1.24unix.net OK ns2.24unix.net OK ns3.24unix.net OK
``` ```
Yes, all our domains from the given panel have been added to our nameserver. Yes, all our domains from the given panel have been added to out nameserver.
Voila. Voila.
@ -603,14 +595,10 @@ curl -X 'GET' \
-H 'X-API-Key: 61f27a57c9d1f.[truncated]' -H 'X-API-Key: 61f27a57c9d1f.[truncated]'
``` ```
A helpful tool when dealing with API is [Postman](https://www.postman.com/), if offers the same options as from the A helpful tool when dealing with API is [Postman](https://www.postman.com/), if offers the same options as from the OpenAPI interface or via shell with curl.
OpenAPI interface or via shell with curl.
![Php Interpreter](https://bindapi.24unix.net/assets/bindAPI_api6.png) ![Php Interpreter](https://bindapi.24unix.net/assets/bindAPI_api6.png)
<a name="conclusion"></a> <a name="conclusion"></a>
# 6. Conclusion
# 6. DynDns
# 7. Conclusion

7
TODO
View File

@ -1,7 +0,0 @@
API Endpoint cleanup
check keytype of panel
check keytype of 1bindApi
check:configkey => update config.json
more UNIT tests

View File

@ -1,6 +1,3 @@
1.0.1 (2022-03-01)
- added /dyndns endpoint to API
1.0.0 (2022-03-01) 1.0.0 (2022-03-01)
- official release - official release

View File

@ -1,20 +1,128 @@
#!/usr/bin/env php #!/usr/bin/keyhelp-php81
<?php declare(strict_types=1); <?php declare(strict_types=1);
namespace App\Controller; namespace App\Controller;
// & ~E_DEPRECATED is needed because of a bug in PhpStorm
use DI\DependencyException;
use DI\NotFoundException;
use Exception;
error_reporting(error_level: E_ALL & ~E_DEPRECATED);
if (php_sapi_name() !== 'cli') { if (php_sapi_name() !== 'cli') {
echo 'This application must be run on the command line.' . PHP_EOL; exit;
exit;
} }
// check php version (must be >= 8.1) // version, store that somewhere else
/** @noinspection PhpArgumentWithoutNamedIdentifierInspection */ $version = '0.0.1';
if (version_compare(PHP_VERSION, '8.2.0', '<')) {
echo 'This application requires PHP 8.2 or newer. You are running ' . PHP_VERSION . PHP_EOL; require dirname(path: __DIR__) . '/vendor/autoload.php';
echo 'If you are using KeyHelp, use keyhelp-php82 ' . $argv[0] . ' instead.' . PHP_EOL;
exit; $configFile = dirname(path: __DIR__) ."/config.json.local";
if (!file_exists(filename: $configFile)) {
$configFile = dirname(path: __DIR__) ."/config.json";
}
if (!file_exists(filename: $configFile)) {
echo 'Missing config file' . PHP_EOL;
if (confirm(message: 'Should I create a new config based on config.json.sample?')) {
copy(from: 'config.json.sample', to: 'config.json');
echo 'Config file has been generated. Adjust it to your needs, then proceed to database setup.' . PHP_EOL;
} else {
echo 'You first have to setup the bindAPI. Bye.' . PHP_EOL;
exit(0);
}
exit(1);
}
$configJSON = file_get_contents(filename: $configFile);
if (!$config = json_decode(json: $configJSON, associative: true)) {
echo 'Error parsing the config file.' . PHP_EOL;
echo $configJSON;
}
$shortOpts = 'v::'; // version
$shortOpts .= "V::"; // verbose
$shortOpts .= "h::"; // help
$longOpts = [
'version::',
'verbose::',
'help::'
];
$options = getopt(short_options: $shortOpts, long_options: $longOpts, rest_index: $restIndex);
if (array_key_exists(key: 'v', array: $options) || array_key_exists(key: 'version', array: $options) ) {
print("bindAPI version: $version" . PHP_EOL);
exit(0);
}
if (array_key_exists(key: 'h', array: $options) || array_key_exists(key: 'help', array: $options) ) {
print("Help …" . PHP_EOL);
exit(0);
}
if (array_key_exists(key: 'V', array: $options) || array_key_exists(key: 'verbose', array: $options) ) {
$config['verbose'] = true;
} else {
$config['verbose'] = false;
}
$arguments = array_slice(array: $argv, offset: $restIndex);
try {
$app = new BindAPI(config: $config, argumentsCount: count(value: $arguments), arguments: $arguments);
$app->runCommand();
} catch (DependencyException|NotFoundException $e) {
echo $e->getMessage();
exit(1);
} catch (Exception $e) {
echo $e->getMessage();
}
/**
* @param String $message
* @param array $options
* @param string $default
*
* @return bool
*/
function confirm(String $message = 'Are you sure? ', array $options = ['y', 'n'], string $default ='n'): bool
{
// first $options means true, any other false
echo $message, ' (';
$first = true;
foreach ($options as $option) {
// mark default
if ($option == $default) {
$option = strtoupper(string: $option);
}
if ($first) {
echo $option;
$first = false;
} else {
echo '/', $option;
}
}
echo '): ';
$handle = fopen(filename: "php://stdin", mode: 'r');
$line = trim(string: fgetc(stream: $handle));
fclose(stream: $handle);
if ($line == '') {
// enter
$line = $default;
}
if ($line == $options[0]) {
$result = true;
} else {
$result = false;
}
return $result;
} }
/** @noinspection PhpArgumentWithoutNamedIdentifierInspection */
require dirname(__DIR__, 1) . '/src/Utilities/Console.php';

View File

@ -1,148 +0,0 @@
{
"openapi": "3.0.0",
"info": {
"title": "bindAPI",
"version": "1.0.9"
},
"servers": [
{
"url": "{schema}://{hostname}/api",
"description": "The bindAPI URL.",
"variables": {
"schema": {
"enum": [
"http",
"https"
],
"default": "https"
},
"hostname": {
"enum": [
"ns1.24unix.net",
"ns2.24unix.net"
],
"default": "ns2.24unix.net"
}
}
}
],
"paths": {
"/ping": {
"get": {
"tags": [
"Server"
],
"description": "Checks for connectivity and valid APIkey",
"operationId": "ping",
"responses": {
"200": {
"description": "OK"
},
"401": {
"description": "API key is missing or invalid."
}
},
"security": [
{
"Authorization": []
}
]
}
},
"/version": {
"get": {
"tags": [
"Server"
],
"description": "Check the API version of the nameserver.",
"operationId": "version",
"responses": {
"200": {
"description": "x.y.z, aka major, minor, patch"
},
"401": {
"description": "API key is missing or invalid."
}
},
"security": [
{
"Authorization": []
}
]
}
},
"/domains": {
"get": {
"tags": [
"Domains"
],
"summary": "List all domains.",
"description": "Returns a list of all domains on this server.",
"operationId": "getAllDomains",
"responses": {
"200": {
"description": "OK"
},
"401": {
"description": "API key is missing or invalid."
},
"404": {
"description": "Domain not found."
}
},
"security": [
{
"Authorization": []
}
]
}
},
"/domains/{name}": {
"get": {
"tags": [
"Domains"
],
"summary": "Returns a single domain.",
"description": "Returns information of a single domain specified by its domain name.",
"operationId": "getSingleDomain",
"parameters": [
{
"name": "name",
"in": "path",
"required": true,
"schema": {
"type": "string"
}
}
],
"responses": {
"200": {
"description": "OK"
},
"401": {
"description": "API key is missing or invalid."
},
"404": {
"description": "Domain not found."
}
},
"security": []
}
}
},
"components": {
"securitySchemes": {
"Authorization": {
"type": "apiKey",
"description": "Api Authentication",
"name": "X-API-Key",
"in": "header"
}
}
},
"tags": [
{
"name": "Server"
}
]
}

View File

@ -1,58 +1,44 @@
{ {
"name": "tracer/bindapi", "name": "tracer/bindppi",
"description": "manage Bind9 client zones for KeyHelp", "authors": [
"version": "1.1.2", {
"build_number": "380", "name": "Micha Espey",
"authors": [ "email": "tracer@24unix.net"
{ }
"name": "Micha Espey", ],
"email": "tracer@24unix.net" "type": "project",
} "license": "proprietary",
], "minimum-stability": "stable",
"type": "project", "prefer-stable": true,
"license": "MIT", "require": {
"minimum-stability": "stable", "php": ">=8.1",
"prefer-stable": true, "ext-curl": "*",
"require": { "ext-json": "*",
"php": ">=8.2", "ext-pdo": "*",
"ext-curl": "*", "arubacao/tld-checker": "^1.2",
"ext-json": "*", "monolog/monolog": "^2.3",
"ext-mbstring": "*", "php-di/php-di": "^6.3",
"ext-openssl": "*", "phplucidframe/console-table": "^1.2",
"ext-pdo": "*", "zircote/swagger-php": "^4.2"
"ext-posix": "*",
"ext-sodium": "*",
"arubacao/tld-checker": "^1.2",
"bartlett/php-compatinfo": "^7.1",
"monolog/monolog": "^3.1",
"netresearch/jsonmapper": "^4.4",
"php-di/php-di": "^6.3",
"phplucidframe/console-table": "^1.2",
"robmorgan/phinx": "^0.15",
"symfony/property-access": "^6.1",
"symfony/serializer": "^6.1",
"zircote/swagger-php": "^4.8"
},
"config": {
"optimize-autoloader": true,
"preferred-install": {
"*": "dist"
}, },
"sort-packages": true "config": {
}, "optimize-autoloader": true,
"autoload": { "preferred-install": {
"psr-4": { "*": "dist"
"App\\": "src/" },
"sort-packages": true
},
"autoload": {
"psr-4": {
"App\\": "src/"
}
},
"autoload-dev": {
"psr-4": {
"Src\\": "src/"
}
},
"require-dev": {
"phpunit/phpunit": "^9.5"
} }
},
"autoload-dev": {
"psr-4": {
"Src\\": "src/"
}
},
"require-dev": {
"escapestudios/symfony2-coding-standard": "3.x-dev",
"odan/phinx-migrations-generator": "^6.1",
"phpunit/phpunit": "10"
}
} }

5779
composer.lock generated

File diff suppressed because it is too large Load Diff

View File

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

View File

@ -1,255 +0,0 @@
<?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();
}
}

View File

@ -1,33 +0,0 @@
<?php
use Phinx\Db\Adapter\MysqlAdapter;
class ConfigTable extends Phinx\Migration\AbstractMigration
{
public function change()
{
$this->table('config', [
'id' => false,
'engine' => 'InnoDB',
'encoding' => 'utf8mb4',
'collation' => 'utf8mb4_general_ci',
'comment' => '',
'row_format' => 'DYNAMIC',
])
->addColumn('name', 'string', [
'null' => false,
'limit' => 256,
'collation' => 'utf8mb4_general_ci',
'encoding' => 'utf8mb4',
])
->addColumn('value', 'string', [
'null' => false,
'limit' => 256,
'collation' => 'utf8mb4_general_ci',
'encoding' => 'utf8mb4',
'after' => 'name',
])
->removeColumn('version')
->save();
}
}

View File

@ -1,24 +0,0 @@
<?php
use Phinx\Db\Adapter\MysqlAdapter;
class ApiKeyCreationDate extends Phinx\Migration\AbstractMigration
{
public function change()
{
$this->table('apikeys', [
'id' => false,
'primary_key' => ['id'],
'engine' => 'InnoDB',
'encoding' => 'utf8mb4',
'collation' => 'utf8mb4_unicode_ci',
'comment' => '',
'row_format' => 'DYNAMIC',
])
->addColumn('created_at', 'timestamp', [
'null' => false,
'after' => 'apikey',
])
->save();
}
}

View File

@ -1,24 +0,0 @@
<?php
use Phinx\Db\Adapter\MysqlAdapter;
class UniqueConfigValues extends Phinx\Migration\AbstractMigration
{
public function change()
{
$this->table('config', [
'id' => false,
'primary_key' => ['name'],
'engine' => 'InnoDB',
'encoding' => 'utf8mb4',
'collation' => 'utf8mb4_general_ci',
'comment' => '',
'row_format' => 'DYNAMIC',
])
->addIndex(['name'], [
'name' => 'name',
'unique' => true,
])
->save();
}
}

View File

@ -1,25 +0,0 @@
<?php
use Phinx\Db\Adapter\MysqlAdapter;
class TimeStampDefaultforApiKeys extends Phinx\Migration\AbstractMigration
{
public function change()
{
$this->table('apikeys', [
'id' => false,
'primary_key' => ['id'],
'engine' => 'InnoDB',
'encoding' => 'utf8mb4',
'collation' => 'utf8mb4_unicode_ci',
'comment' => '',
'row_format' => 'DYNAMIC',
])
->changeColumn('created_at', 'timestamp', [
'null' => true,
'default' => 'current_timestamp()',
'after' => 'apikey',
])
->save();
}
}

View File

@ -1,37 +0,0 @@
<?php
use Phinx\Db\Adapter\MysqlAdapter;
class AddSelfToNameservers extends Phinx\Migration\AbstractMigration
{
public function change()
{
// $this->table('domains', [
// 'id' => false,
// 'primary_key' => ['id'],
// 'engine' => 'InnoDB',
// 'encoding' => 'utf8mb4',
// 'collation' => 'utf8mb4_unicode_ci',
// 'comment' => '',
// 'row_format' => 'DYNAMIC',
// ])
// ->removeColumn('self')
// ->save();
$this->table('nameservers', [
'id' => false,
'primary_key' => ['id'],
'engine' => 'InnoDB',
'encoding' => 'utf8mb4',
'collation' => 'utf8mb4_unicode_ci',
'comment' => '',
'row_format' => 'DYNAMIC',
])
->addColumn('self', 'enum', [
'null' => false,
'limit' => 3,
'values' => ['yes', 'no'],
'after' => 'apikey_prefix',
])
->save();
}
}

View File

@ -1,41 +0,0 @@
<?php
use Phinx\Db\Adapter\MysqlAdapter;
class UUIDForConfig extends Phinx\Migration\AbstractMigration
{
public function change()
{
$this->table('config', [
'id' => false,
'primary_key' => ['id'],
'engine' => 'InnoDB',
'encoding' => 'utf8mb4',
'collation' => 'utf8mb4_general_ci',
'comment' => '',
'row_format' => 'DYNAMIC',
])
->addColumn('id', 'uuid', [
'null' => false,
])
->changeColumn('name', 'string', [
'null' => false,
'limit' => 256,
'collation' => 'utf8mb4_general_ci',
'encoding' => 'utf8mb4',
'after' => 'id',
])
->changeColumn('value', 'string', [
'null' => false,
'limit' => 256,
'collation' => 'utf8mb4_general_ci',
'encoding' => 'utf8mb4',
'after' => 'name',
])
->addIndex(['id'], [
'name' => 'id',
'unique' => true,
])
->save();
}
}

View File

@ -1,24 +0,0 @@
<?php
use Phinx\Db\Adapter\MysqlAdapter;
class DefaultUUIDforConfig extends Phinx\Migration\AbstractMigration
{
public function change()
{
$this->table('config', [
'id' => false,
'primary_key' => ['id'],
'engine' => 'InnoDB',
'encoding' => 'utf8mb4',
'collation' => 'utf8mb4_general_ci',
'comment' => '',
'row_format' => 'DYNAMIC',
])
->changeColumn('id', 'uuid', [
'null' => false,
'default' => 'uuid()',
])
->save();
}
}

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +0,0 @@
Copy these files to /etc/systems/system, adapt the path in the service unit and enable the timer by issuing:
systemctl daemon-reload
systemctl enable bindAPI.timer
systemctl start bindAPI.timer
systemctl list-timers

View File

@ -1,6 +0,0 @@
[Unit]
Description=BindAPI Service to check zone file and reload configuration
[Service]
User=<paneluser>
ExecStart=/home/users/<user>/<bindApi>/bin/console -q cron:run

View File

@ -1,10 +0,0 @@
[Unit]
Description=Runs BindAPI every minute
[Timer]
OnBootSec=1min
OnUnitActiveSec=1min
Unit=bindAPI.service
[Install]
WantedBy=timers.target

View File

@ -1,8 +0,0 @@
#!/bin/bash
# calculate build number
build_number=$(git rev-list --count HEAD)
# add build number to composer.json using jq
jq --arg bn "$build_number" '.build_number = $bn' composer.json > tmp.$$.json && mv tmp.$$.json composer.json

1
log.txt Normal file
View File

@ -0,0 +1 @@

View File

@ -1,40 +0,0 @@
<?php
use App\Controller\ConfigController;
require 'vendor/autoload.php';
$configController = new ConfigController(quiet: true);
$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

@ -1,27 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" <phpunit bootstrap="vendor/autoload.php">
xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/9.5/phpunit.xsd"
bootstrap="vendor/autoload.php"
cacheResultFile=".phpunit.cache/test-results"
executionOrder="depends,defects"
forceCoversAnnotation="false"
beStrictAboutCoversAnnotation="true"
beStrictAboutOutputDuringTests="true"
beStrictAboutTodoAnnotatedTests="true"
convertDeprecationsToExceptions="true"
failOnRisky="true"
failOnWarning="true"
verbose="true">
<testsuites> <testsuites>
<testsuite name="default"> <testsuite name="bindAPI Test Suite">
<directory>tests</directory> <directory suffix=".php">./tests/</directory>
</testsuite> </testsuite>
</testsuites> </testsuites>
</phpunit>
<coverage cacheDirectory=".phpunit.cache/code-coverage"
processUncoveredFiles="true">
<include>
<directory suffix=".php">src</directory>
</include>
</coverage>
</phpunit>

1
public/.gitignore vendored
View File

@ -1 +0,0 @@
log.txt

View File

@ -1,47 +1,54 @@
<?php declare(strict_types=1); <?php declare(strict_types=1);
use App\Service\BindAPI; namespace App\Controller;
use Exception;
error_reporting(error_level: E_ALL); error_reporting(error_level: E_ALL);
require dirname(path: __DIR__) . '/vendor/autoload.php'; require dirname(path: __DIR__) . '/vendor/autoload.php';
$parsedUrl = parse_url(url: $_SERVER['REQUEST_URI'], component: PHP_URL_PATH); // read config
$uri = explode(separator: '/', string: $parsedUrl); $configFile = dirname(path: __DIR__) . "/config.json";
$configJSON = file_get_contents(filename: $configFile);
$baseRoutes = ['app', 'api']; $config = json_decode(json: $configJSON, associative: true);
$uriPrefix = $uriFirstThreeLetters = substr(string: $uri[1], offset: 0, length: 3);
if (!in_array(needle: $uriPrefix, haystack: $baseRoutes)) { // TODO make a log class
// only handle $baseRoutes, elso go to swagger ui $oFile = fopen(filename: 'log.txt', mode: 'a');
$uri = parse_url(url: $_SERVER['REQUEST_URI'], component: PHP_URL_PATH);
fputs(stream: $oFile, data: $uri . PHP_EOL);
fputs(stream: $oFile, data: "here");
$uri = explode(separator: '/', string: $uri);
fclose(stream: $oFile);
if ($uri[1] !== 'api') {
$scheme = $_SERVER['REQUEST_SCHEME']; $scheme = $_SERVER['REQUEST_SCHEME'];
$host = $_SERVER['SERVER_NAME']; $host = $_SERVER['SERVER_NAME'];
$header = "$scheme://$host/openapi/index.html"; $header = "$scheme://$host/openapi/index.html";
header(header: "Location: $header"); header(header: "Location: $header");
exit(0); exit(0);
} }
// TODO only valid clients?
header(header: "Access-Control-Allow-Origin: *"); header(header: "Access-Control-Allow-Origin: *");
header(header: "Content-Type: application/json; charset=UTF-8"); header(header: "Content-Type: application/json; charset=UTF-8");
header(header: "Access-Control-Allow-Methods: OPTIONS,GET,POST,PUT,DELETE"); header(header: "Access-Control-Allow-Methods: OPTIONS,GET,POST,PUT,DELETE");
header(header: "Access-Control-Max-Age: 3600"); header(header: "Access-Control-Max-Age: 3600");
header(header: "Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With, x-api-key"); header(header: "Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With");
$requestMethod = $_SERVER["REQUEST_METHOD"]; $requestMethod = $_SERVER["REQUEST_METHOD"];
if ($requestMethod === "OPTIONS") {
// Respond with OK status code for preflight requests
http_response_code(response_code: 200);
exit();
}
try { try {
$app = new BindAPI(quiet: false); $controller = new RequestController(config: $config, requestMethod: $requestMethod, uri: $uri);
$app->handleRequest(requestMethod: $requestMethod, uri: $uri); $controller->processRequest();
} catch (Exception $e) { } catch (Exception $e) {
echo json_encode(value: [ echo json_encode(value: [
'error' => $e->getMessage() 'error' => $e->getMessage()
]); ]);
} }

View File

@ -1,949 +0,0 @@
nothing to do
====
[11-Oct-2022 17:47:01] INFO --> load tasks... nothing to do
====
[11-Oct-2022 17:48:02] INFO --> load tasks... nothing to do
====
[11-Oct-2022 17:49:01] INFO --> load tasks... nothing to do
====
[11-Oct-2022 17:50:01] INFO --> load tasks... nothing to do
====
[11-Oct-2022 17:51:01] INFO --> load tasks... nothing to do
====
[11-Oct-2022 17:52:01] INFO --> load tasks... nothing to do
====
[11-Oct-2022 17:53:01] INFO --> load tasks... nothing to do
====
[11-Oct-2022 17:54:02] INFO --> load tasks... nothing to do
====
[11-Oct-2022 17:55:01] INFO --> load tasks... nothing to do
====
[11-Oct-2022 17:56:01] INFO --> load tasks... nothing to do
====
[11-Oct-2022 17:57:01] INFO --> load tasks... nothing to do
====
[11-Oct-2022 17:58:02] INFO --> load tasks... nothing to do
====
[11-Oct-2022 17:59:01] INFO --> load tasks... nothing to do
====
[11-Oct-2022 18:00:01] INFO --> load tasks... nothing to do
====
[11-Oct-2022 18:01:01] INFO --> load tasks... nothing to do
====
[11-Oct-2022 18:02:01] INFO --> load tasks... nothing to do
====
[11-Oct-2022 18:03:01] INFO --> load tasks... nothing to do
====
[11-Oct-2022 18:04:01] INFO --> load tasks... nothing to do
====
[11-Oct-2022 18:05:02] INFO --> load tasks... nothing to do
====
[11-Oct-2022 18:06:01] INFO --> load tasks... nothing to do
====
[11-Oct-2022 18:07:01] INFO --> load tasks... nothing to do
====
[11-Oct-2022 18:08:01] INFO --> load tasks... nothing to do
====
[11-Oct-2022 18:09:01] INFO --> load tasks... nothing to do
====
[11-Oct-2022 18:10:01] INFO --> load tasks... nothing to do
====
[11-Oct-2022 18:11:01] INFO --> load tasks... nothing to do
====
[11-Oct-2022 18:12:02] INFO --> load tasks... nothing to do
====
[11-Oct-2022 18:13:01] INFO --> load tasks... nothing to do
====
[11-Oct-2022 18:14:01] INFO --> load tasks... nothing to do
====
[11-Oct-2022 18:15:01] INFO --> load tasks... nothing to do
====
[11-Oct-2022 18:16:01] INFO --> load tasks... nothing to do
====
[11-Oct-2022 18:17:01] INFO --> load tasks... nothing to do
====
[11-Oct-2022 18:18:01] INFO --> load tasks... nothing to do
====
[11-Oct-2022 18:19:01] INFO --> load tasks... nothing to do
====
[11-Oct-2022 18:20:01] INFO --> load tasks... nothing to do
====
[11-Oct-2022 18:21:01] INFO --> load tasks... nothing to do
====
[11-Oct-2022 18:22:02] INFO --> load tasks... nothing to do
====
[11-Oct-2022 18:23:01] INFO --> load tasks... nothing to do
====
[11-Oct-2022 18:24:01] INFO --> load tasks... nothing to do
====
[11-Oct-2022 18:25:01] INFO --> load tasks... nothing to do
====
[11-Oct-2022 18:26:01] INFO --> load tasks... nothing to do
====
[11-Oct-2022 18:27:01] INFO --> load tasks... nothing to do
====
[11-Oct-2022 18:28:01] INFO --> load tasks... nothing to do
====
[11-Oct-2022 18:29:01] INFO --> load tasks... nothing to do
====
[11-Oct-2022 18:30:02] INFO --> load tasks... nothing to do
====
[11-Oct-2022 18:31:01] INFO --> load tasks... nothing to do
====
[11-Oct-2022 18:32:01] INFO --> load tasks... nothing to do
====
[11-Oct-2022 18:33:01] INFO --> load tasks... nothing to do
====
[11-Oct-2022 18:34:01] INFO --> load tasks... nothing to do
====
[11-Oct-2022 18:35:01] INFO --> load tasks... nothing to do
====
[11-Oct-2022 18:36:01] INFO --> load tasks... nothing to do
====
[11-Oct-2022 18:37:02] INFO --> load tasks... nothing to do
====
[11-Oct-2022 18:38:01] INFO --> load tasks... nothing to do
====
[11-Oct-2022 18:39:01] INFO --> load tasks... nothing to do
====
[11-Oct-2022 18:40:01] INFO --> load tasks... nothing to do
====
[11-Oct-2022 18:41:01] INFO --> load tasks... nothing to do
====
[11-Oct-2022 18:42:01] INFO --> load tasks... nothing to do
====
[11-Oct-2022 18:43:01] INFO --> load tasks... nothing to do
====
[11-Oct-2022 18:44:02] INFO --> load tasks... nothing to do
====
[11-Oct-2022 18:45:01] INFO --> load tasks... nothing to do
====
[11-Oct-2022 18:46:01] INFO --> load tasks... nothing to do
====
[11-Oct-2022 18:47:01] INFO --> load tasks... nothing to do
====
[11-Oct-2022 18:48:01] INFO --> load tasks... notp
[PID-31506] [11-Oct-2022 20:32:01] INFO --> >>> trying to run "update"
[PID-31506] [11-Oct-2022 20:32:01] INFO --> lock "update" acquired
[PID-31506] [11-Oct-2022 20:32:01] INFO --> processing the job ...
[PID-31506] [11-Oct-2022 20:32:01] INFO --> <<< job done, releasing lock "update"
====
[PID-31633] [11-Oct-2022 20:33:01] INFO --> jobs to run: update.php
[PID-31633] [11-Oct-2022 20:33:01] INFO --> >>> trying to run "update"
[PID-31633] [11-Oct-2022 20:33:01] INFO --> lock "update" acquired
[PID-31633] [11-Oct-2022 20:33:01] INFO --> processing the job ...
[PID-31633] [11-Oct-2022 20:33:01] INFO --> <<< job done, releasing lock "update"
====
[PID-31726] [11-Oct-2022 20:34:01] INFO --> jobs to run: update.php
[PID-31726] [11-Oct-2022 20:34:01] INFO --> >>> trying to run "update"
[PID-31726] [11-Oct-2022 20:34:01] INFO --> lock "update" acquired
[PID-31726] [11-Oct-2022 20:34:01] INFO --> processing the job ...
[PID-31726] [11-Oct-2022 20:34:01] INFO --> <<< job done, releasing lock "update"
====
[PID-31803] [11-Oct-2022 20:35:01] INFO --> jobs to run: update.php
[PID-31803] [11-Oct-2022 20:35:01] INFO --> >>> trying to run "update"
[PID-31803] [11-Oct-2022 20:35:01] INFO --> lock "update" acquired
[PID-31803] [11-Oct-2022 20:35:01] INFO --> processing the job ...
[PID-31803] [11-Oct-2022 20:35:01] INFO --> <<< job done, releasing lock "update"
====
[PID-31896] [11-Oct-2022 20:36:01] INFO --> jobs to run: update.php
[PID-31896] [11-Oct-2022 20:36:01] INFO --> >>> trying to run "update"
[PID-31896] [11-Oct-2022 20:36:01] INFO --> lock "update" acquired
[PID-31896] [11-Oct-2022 20:36:01] INFO --> processing the job ...
[PID-31896] [11-Oct-2022 20:36:01] INFO --> <<< job done, releasing lock "update"
====
[PID-31978] [11-Oct-2022 20:37:01] INFO --> jobs to run: update.php
[PID-31978] [11-Oct-2022 20:37:01] INFO --> >>> trying to run "update"
[PID-31978] [11-Oct-2022 20:37:01] INFO --> lock "update" acquired
[PID-31978] [11-Oct-2022 20:37:01] INFO --> processing the job ...
[PID-31978] [11-Oct-2022 20:37:01] INFO --> <<< job done, releasing lock "update"
====
[PID-32071] [11-Oct-2022 20:38:01] INFO --> jobs to run: update.php
[PID-32071] [11-Oct-2022 20:38:01] INFO --> >>> trying to run "update"
[PID-32071] [11-Oct-2022 20:38:01] INFO --> lock "update" acquired
[PID-32071] [11-Oct-2022 20:38:01] INFO --> processing the job ...
[PID-32071] [11-Oct-2022 20:38:01] INFO --> <<< job done, releasing lock "update"
====
[PID-32160] [11-Oct-2022 20:39:02] INFO --> jobs to run: update.php
[PID-32160] [11-Oct-2022 20:39:02] INFO --> >>> trying to run "update"
[PID-32160] [11-Oct-2022 20:39:02] INFO --> lock "update" acquired
[PID-32160] [11-Oct-2022 20:39:02] INFO --> processing the job ...
[PID-32160] [11-Oct-2022 20:39:02] INFO --> <<< job done, releasing lock "update"
====
[PID-32325] [11-Oct-2022 20:40:01] INFO --> jobs to run: update.php
[PID-32325] [11-Oct-2022 20:40:01] INFO --> >>> trying to run "update"
[PID-32325] [11-Oct-2022 20:40:01] INFO --> lock "update" acquired
[PID-32325] [11-Oct-2022 20:40:01] INFO --> processing the job ...
[PID-32325] [11-Oct-2022 20:40:01] INFO --> <<< job done, releasing lock "update"
====
[PID-32420] [11-Oct-2022 20:41:01] INFO --> jobs to run: update.php
[PID-32420] [11-Oct-2022 20:41:01] INFO --> >>> trying to run "update"
[PID-32420] [11-Oct-2022 20:41:01] INFO --> lock "update" acquired
[PID-32420] [11-Oct-2022 20:41:01] INFO --> processing the job ...
[PID-32420] [11-Oct-2022 20:41:01] INFO --> <<< job done, releasing lock "update"
====
[PID-32507] [11-Oct-2022 20:42:01] INFO --> jobs to run: update.php
[PID-32507] [11-Oct-2022 20:42:01] INFO --> >>> trying to run "update"
[PID-32507] [11-Oct-2022 20:42:01] INFO --> lock "update" acquired
[PID-32507] [11-Oct-2022 20:42:01] INFO --> processing the job ...
[PID-32507] [11-Oct-2022 20:42:01] INFO --> <<< job done, releasing lock "update"
====
[PID-32590] [11-Oct-2022 20:43:01] INFO --> jobs to run: update.php
[PID-32590] [11-Oct-2022 20:43:01] INFO --> >>> trying to run "update"
[PID-32590] [11-Oct-2022 20:43:01] INFO --> lock "update" acquired
[PID-32590] [11-Oct-2022 20:43:01] INFO --> processing the job ...
[PID-32590] [11-Oct-2022 20:43:01] INFO --> <<< job done, releasing lock "update"
====
[PID-32684] [11-Oct-2022 20:44:01] INFO --> jobs to run: update.php
[PID-32684] [11-Oct-2022 20:44:01] INFO --> >>> trying to run "update"
[PID-32684] [11-Oct-2022 20:44:01] INFO --> lock "update" acquired
[PID-32684] [11-Oct-2022 20:44:01] INFO --> processing the job ...
[PID-32684] [11-Oct-2022 20:44:01] INFO --> <<< job done, releasing lock "update"
====
[PID-32775] [11-Oct-2022 20:45:01] INFO --> jobs to run: update.php
[PID-32775] [11-Oct-2022 20:45:01] INFO --> >>> trying to run "update"
[PID-32775] [11-Oct-2022 20:45:01] INFO --> lock "update" acquired
[PID-32775] [11-Oct-2022 20:45:01] INFO --> processing the job ...
[PID-32775] [11-Oct-2022 20:45:01] INFO --> <<< job done, releasing lock "update"
====
[PID-32852] [11-Oct-2022 20:46:01] INFO --> jobs to run: update.php
[PID-32852] [11-Oct-2022 20:46:01] INFO --> >>> trying to run "update"
[PID-32852] [11-Oct-2022 20:46:01] INFO --> lock "update" acquired
[PID-32852] [11-Oct-2022 20:46:01] INFO --> processing the job ...
[PID-32852] [11-Oct-2022 20:46:01] INFO --> <<< job done, releasing lock "update"
====
[PID-32944] [11-Oct-2022 20:47:01] INFO --> jobs to run: update.php
[PID-32944] [11-Oct-2022 20:47:01] INFO --> >>> trying to run "update"
[PID-32944] [11-Oct-2022 20:47:01] INFO --> lock "update" acquired
[PID-32944] [11-Oct-2022 20:47:02] INFO --> processing the job ...
[PID-32944] [11-Oct-2022 20:47:02] INFO --> <<< job done, releasing lock "update"
====
[PID-33036] [11-Oct-2022 20:48:01] INFO --> jobs to run: update.php
[PID-33036] [11-Oct-2022 20:48:01] INFO --> >>> trying to run "update"
[PID-33036] [11-Oct-2022 20:48:01] INFO --> lock "update" acquired
[PID-33036] [11-Oct-2022 20:48:01] INFO --> processing the job ...
[PID-33036] [11-Oct-2022 20:48:01] INFO --> <<< job done, releasing lock "update"
====
[PID-33113] [11-Oct-2022 20:49:01] INFO --> jobs to run: update.php
[PID-33113] [11-Oct-2022 20:49:01] INFO --> >>> trying to run "update"
[PID-33113] [11-Oct-2022 20:49:01] INFO --> lock "update" acquired
[PID-33113] [11-Oct-2022 20:49:01] INFO --> processing the job ...
[PID-33113] [11-Oct-2022 20:49:01] INFO --> <<< job done, releasing lock "update"
====
[PID-33215] [11-Oct-2022 20:50:01] INFO --> jobs to run: update.php
[PID-33215] [11-Oct-2022 20:50:01] INFO --> >>> trying to run "update"
[PID-33215] [11-Oct-2022 20:50:01] INFO --> lock "update" acquired
[PID-33215] [11-Oct-2022 20:50:01] INFO --> processing the job ...
[PID-33215] [11-Oct-2022 20:50:01] INFO --> <<< job done, releasing lock "update"
====
[PID-33295] [11-Oct-2022 20:51:01] INFO --> jobs to run: update.php
[PID-33295] [11-Oct-2022 20:51:01] INFO --> >>> trying to run "update"
[PID-33295] [11-Oct-2022 20:51:01] INFO --> lock "update" acquired
[PID-33295] [11-Oct-2022 20:51:01] INFO --> processing the job ...
[PID-33295] [11-Oct-2022 20:51:01] INFO --> <<< job done, releasing lock "update"
====
[PID-33386] [11-Oct-2022 20:52:01] INFO --> jobs to run: update.php, diskspace.php
[PID-33386] [11-Oct-2022 20:52:01] INFO --> >>> trying to run "update"
[PID-33386] [11-Oct-2022 20:52:01] INFO --> lock "update" acquired
[PID-33386] [11-Oct-2022 20:52:01] INFO --> processing the job ...
[PID-33386] [11-Oct-2022 20:52:01] INFO --> <<< job done, releasing lock "update"
[PID-33386] [11-Oct-2022 20:52:01] INFO --> >>> trying to run "diskspace"
[PID-33386] [11-Oct-2022 20:52:01] INFO --> lock "diskspace" acquired
[PID-33386] [11-Oct-2022 20:52:01] INFO --> processing the job ...
[PID-33386] [11-Oct-2022 20:52:01] INFO --> <<< job done, releasing lock "diskspace"
====
[PID-33495] [11-Oct-2022 20:53:01] INFO --> jobs to run: update.php
[PID-33495] [11-Oct-2022 20:53:01] INFO --> >>> trying to run "update"
[PID-33495] [11-Oct-2022 20:53:01] INFO --> lock "update" acquired
[PID-33495] [11-Oct-2022 20:53:01] INFO --> processing the job ...
[Pdo
====
[11-Oct-2022 20:53:01] INFO --> load tasks... nothing to do
====
[11-Oct-2022 20:54:01] INFO --> load tasks... nothing to do
====
[11-Oct-2022 20:55:02] INFO --> load tasks... nothing to do
====
[11-Oct-2022 20:56:01] INFO --> load tasks... nothing to do
====
[11-Oct-2022 20:57:01] INFO --> load tasks... nothing to do
====
[11-Oct-2022 20:58:01] INFO --> load tasks... nothing to do
====
[11-Oct-2022 20:59:01] INFO --> load tasks... nothing to do
====
[11-Oct-2022 21:00:01] INFO --> load tasks... nothing to do
====
[11-Oct-2022 21:01:01] INFO --> load tasks... nothing to do
====
[11-Oct-2022 21:02:01] INFO --> load tasks... nothing to do
====
[11-Oct-2022 21:03:01] INFO --> load tasks... nothing to do
====
[11-Oct-2022 21:04:02] INFO --> load tasks... nothing to do
====
[11-Oct-2022 21:05:01] INFO --> load tasks... nothing to do
====
[11-Oct-2022 21:06:01] INFO --> load tasks... nothing to do
====
[11-Oct-2022 21:07:01] INFO --> load tasks... nothing to do
====
[11-Oct-2022 21:08:01] INFO --> load tasks... nothing to do
====
[11-Oct-2022 21:09:01] INFO --> load tasks... nothing to do
====
[11-Oct-2022 21:10:01] INFO --> load tasks... nothing to do
====
[11-Oct-2022 21:11:01] INFO --> load tasks... nothing to do
====
[11-Oct-2022 21:12:02] INFO --> load tasks... nothing to do
====
[11-Oct-2022 21:13:01] INFO --> load tasks... nothing to do
====
[11-Oct-2022 21:14:01] INFO --> load tasks... nothing to do
====
[11-Oct-2022 21:15:01] INFO --> load tasks... nothing to do
====
[11-Oct-2022 21:16:01] INFO --> load tasks... nothing to do
====
[11-Oct-2022 21:17:01] INFO --> load tasks... nothing to do
====
[11-Oct-2022 21:18:01] INFO --> load tasks... nothing to do
====
[11-Oct-2022 21:19:01] INFO --> load tasks... nothing to do
====
[11-Oct-2022 21:20:01] INFO --> load tasks... nothing to do
====
[11-Oct-2022 21:21:01] INFO --> load tasks... nothing to do
====
[11-Oct-2022 21:22:01] INFO --> load tasks... nothing to do
====
[11-Oct-2022 21:23:01] INFO --> load tasks... nothing to do
====
[11-Oct-2022 21:24:01] INFO --> load tasks... nothing to do
====
[11-Oct-2022 21:25:01] INFO --> load tasks... nothing to do
====
[11-Oct-2022 21:26:02] INFO --> load tasks... nothing to do
====
[11-Oct-2022 21:27:01] INFO --> load tasks... nothing to do
====
[11-Oct-2022 21:28:01] INFO --> load tasks... nothing to do
====
[11-Oct-2022 21:29:01] INFO --> load tasks... nothing to do
====
[11-Oct-2022 21:30:01] INFO --> load tasks... nothing to do
====
[11-Oct-2022 21:31:01] INFO --> load tasks... nothing to do
====
[11-Oct-2022 21:32:01] INFO --> load tasks... nothing to do
====
[11-Oct-2022 21:33:01] INFO --> load tasks... nothing to do
====
[11-Oct-2022 21:34:02] INFO --> load tasks... nothing to do
====
[11-Oct-2022 21:35:01] INFO --> load tasks... nothing to do
====
[11-Oct-2022 21:36:01] INFO --> load tasks... nothing to do
====
[11-Oct-2022 21:37:01] INFO --> load tasks... nothing to do
====
[11-Oct-2022 21:38:01] INFO --> load tasks... nothing to do
====
[11-Oct-2022 21:39:01] INFO --> load tasks... nothing to do
====
[11-Oct-2022 21:40:01] INFO --> load tasks... nothing to do
====
[11-Oct-2022 21:41:02] INFO --> load tasks... nothing to do
====
[11-Oct-2022 21:42:01] INFO --> load tasks... nothing to do
====
[11-Oct-2022 21:43:01] INFO --> load tasks... nothing to do
====
[11-Oct-2022 21:44:01] INFO --> load tasks... nothing to do
====
[11-Oct-2022 21:45:02] INFO --> load tasks... nothing to do
====
[11-Oct-2022 21:46:01] INFO --> load tasks... nothing to do
====
[11-Oct-2022 21:47:01] INFO --> load tasks... nothing to do
====
[11-Oct-2022 21:48:01] INFO --> load tasks... nothing to do
====
[11-Oct-2022 21:49:01] INFO --> load tasks... nothing to do
====
[11-Oct-2022 21:50:01] INFO --> load tasks... nothing to do
====
[11-Oct-2022 21:51:01] INFO --> load tasks... nothing to do
====
[11-Oct-2022 21:52:01] INFO --> load tasks... nothing to do
====
[11-Oct-2022 21:53:02] INFO --> load tasks... nothing to do
====
[11-Oct-2022 21:54:01] INFO --> load tasks... nothing to do
=ID-33495] [11-Oct-2022 20:53:01] INFO --> <<< job done, releasing lock "update"
====
[PID-33581] [11-Oct-2022 20:54:01] INFO --> jobs to run: update.php
[PID-33581] [11-Oct-2022 20:54:01] INFO --> >>> trying to run "update"
[PID-33581] [11-Oct-2022 20:54:01] INFO --> lock "update" acquired
[PID-33581] [11-Oct-2022 20:54:01] INFO --> processing the job ...
[PID-33581] [11-Oct-2022 20:54:01] INFO --> <<< job done, releasing lock "update"
====
[PID-33663] [11-Oct-2022 20:55:02] INFO --> jobs to run: update.php
[PID-33663] [11-Oct-2022 20:55:02] INFO --> >>> trying to run "update"
[PID-33663] [11-Oct-2022 20:55:02] INFO --> lock "update" acquired
[PID-33663] [11-Oct-2022 20:55:02] INFO --> processing the job ...
[PID-33663] [11-Oct-2022 20:55:02] INFO --> <<< job done, releasing lock "update"
====
[PID-33746] [11-Oct-2022 20:56:01] INFO --> jobs to run: update.php
[PID-33746] [11-Oct-2022 20:56:01] INFO --> >>> trying to run "update"
[PID-33746] [11-Oct-2022 20:56:01] INFO --> lock "update" acquired
[PID-33746] [11-Oct-2022 20:56:01] INFO --> processing the job ...
[PID-33746] [11-Oct-2022 20:56:01] INFO --> <<< job done, releasing lock "update"
====
[PID-33838] [11-Oct-2022 20:57:01] INFO --> jobs to run: update.php
[PID-33838] [11-Oct-2022 20:57:01] INFO --> >>> trying to run "update"
[PID-33838] [11-Oct-2022 20:57:01] INFO --> lock "update" acquired
[PID-33838] [11-Oct-2022 20:57:01] INFO --> processing the job ...
[PID-33838] [11-Oct-2022 20:57:01] INFO --> <<< job done, releasing lock "update"
====
[PID-33931] [11-Oct-2022 20:58:01] INFO --> jobs to run: update.php
[PID-33931] [11-Oct-2022 20:58:01] INFO --> >>> trying to run "update"
[PID-33931] [11-Oct-2022 20:58:01] INFO --> lock "update" acquired
[PID-33931] [11-Oct-2022 20:58:01] INFO --> processing the job ...
[PID-33931] [11-Oct-2022 20:58:01] INFO --> <<< job done, releasing lock "update"
====
[PID-34011] [11-Oct-2022 20:59:01] INFO --> jobs to run: update.php
[PID-34011] [11-Oct-2022 20:59:01] INFO --> >>> trying to run "update"
[PID-34011] [11-Oct-2022 20:59:01] INFO --> lock "update" acquired
[PID-34011] [11-Oct-2022 20:59:01] INFO --> processing the job ...
[PID-34011] [11-Oct-2022 20:59:01] INFO --> <<< job done, releasing lock "update"
====
[PID-34105] [11-Oct-2022 21:00:01] INFO --> jobs to run: update.php
[PID-34105] [11-Oct-2022 21:00:01] INFO --> >>> trying to run "update"
[PID-34105] [11-Oct-2022 21:00:01] INFO --> lock "update" acquired
[PID-34105] [11-Oct-2022 21:00:01] INFO --> processing the job ...
[PID-34105] [11-Oct-2022 21:00:01] INFO --> <<< job done, releasing lock "update"
====
[PID-34199] [11-Oct-2022 21:01:01] INFO --> jobs to run: update.php
[PID-34199] [11-Oct-2022 21:01:01] INFO --> >>> trying to run "update"
[PID-34199] [11-Oct-2022 21:01:01] INFO --> lock "update" acquired
[PID-34199] [11-Oct-2022 21:01:01] INFO --> processing the job ...
[PID-34199] [11-Oct-2022 21:01:01] INFO --> <<< job done, releasing lock "update"
====
[PID-34275] [11-Oct-2022 21:02:01] INFO --> jobs to run: update.php
[PID-34275] [11-Oct-2022 21:02:01] INFO --> >>> trying to run "update"
[PID-34275] [11-Oct-2022 21:02:01] INFO --> lock "update" acquired
[PID-34275] [11-Oct-2022 21:02:01] INFO --> processing the job ...
[PID-34275] [11-Oct-2022 21:02:01] INFO --> <<< job done, releasing lock "update"
====
[PID-34417] [11-Oct-2022 21:03:01] INFO --> jobs to run: update.php
[PID-34417] [11-Oct-2022 21:03:01] INFO --> >>> trying to run "update"
[PID-34417] [11-Oct-2022 21:03:01] INFO --> lock "update" acquired
[PID-34417] [11-Oct-2022 21:03:01] INFO --> processing the job ...
[PID-34417] [11-Oct-2022 21:03:01] INFO --> <<< job done, releasing lock "update"
====
[PID-34500] [11-Oct-2022 21:04:02] INFO --> jobs to run: update.php
[PID-34500] [11-Oct-2022 21:04:02] INFO --> >>> trying to run "update"
[PID-34500] [11-Oct-2022 21:04:02] INFO --> lock "update" acquired
[PID-34500] [11-Oct-2022 21:04:02] INFO --> processing the job ...
[PID-34500] [11-Oct-2022 21:04:02] INFO --> <<< job done, releasing lock "update"
-> <<< job done, releasing lock "update"
====
[PID-37992] [11-Oct-2022 21:50:01] INFO --> jobs to run: update.php
[PID-37992] [11-Oct-2022 21:50:01] INFO --> >>> trying to run "update"
[PID-37992] [11-Oct-2022 21:50:01] INFO --> lock "update" acquired
[PID-37992] [11-Oct-2022 21:50:01] INFO --> processing the job ...
[PID-37992] [11-Oct-2022 21:50:01] INFO --> <<< job done, releasing lock "update"
====
[PID-38040] [11-Oct-2022 21:51:01] INFO --> jobs to run: update.php
[PID-38040] [11-Oct-2022 21:51:01] INFO --> >>> trying to run "update"
[PID-38040] [11-Oct-2022 21:51:01] INFO --> lock "update" acquired
[PID-38040] [11-Oct-2022 21:51:01] INFO --> processing the job ...
[PID-38040] [11-Oct-2022 21:51:01] INFO --> <<< job done, releasing lock "update"
====
[PID-38096] [11-Oct-2022 21:52:01] INFO --> jobs to run: update.php, diskspace.php
[PID-38096] [11-Oct-2022 21:52:01] INFO --> >>> trying to run "update"
[PID-38096] [11-Oct-2022 21:52:01] INFO --> lock "update" acquired
[PID-38096] [11-Oct-2022 21:52:01] INFO --> processing the job ...
[PID-38096] [11-Oct-2022 21:52:01] INFO --> <<< job done, releasing lock "update"
[PID-38096] [11-Oct-2022 21:52:01] INFO --> >>> trying to run "diskspace"
[PID-38096] [11-Oct-2022 21:52:01] INFO --> lock "diskspace" acquired
[PID-38096] [11-Oct-2022 21:52:01] INFO --> processing the job ...
[PID-38096] [11-Oct-2022 21:52:01] INFO --> <<< job done, releasing lock "diskspace"
====
[PID-38166] [11-Oct-2022 21:53:02] INFO --> jobs to run: update.php
[PID-38166] [11-Oct-2022 21:53:02] INFO --> >>> trying to run "update"
[PID-38166] [11-Oct-2022 21:53:02] INFO --> lock "update" acquired
[PID-38166] [11-Oct-2022 21:53:02] INFO --> processing the job ...
[PID-38166] [11-Oct-2022 21:53:02] INFO --> <<< job done, releasing lock "update"
====
[PID-38232] [11-Oct-2022 21:54:01] INFO --> jobs to run: update.php
[PID-38232] [11-Oct-2022 21:54:01] INFO --> >>> trying to run "update"
[PID-38232] [11-Oct-2022 21:54:01] INFO --> lock "update" acquired
[PID-38232] [11-Oct-2022 21:54:01] INFO --> processing the job ...
[PID-38232] [11-Oct-2022 21:54:01] INFO --> <<< job done, releasing lock "update"
====
[PID-38287] [11-Oct-2022 21:55:01] INFO --> jobs to run: update.php
[PID-38287] [11-Oct-2022 21:55:01] INFO --> >>> trying to run "update"
[PID-38287] [11-Oct-2022 21:55:01] INFO --> lock "update" acquired
[PID-38287] [11-Oct-2022 21:55:01] INFO --> processing the job ...
[PID-38287] [11-Oct-2022 21:55:01] INFO --> <<< job done, releasing lock "update"
====
[PID-38343] [11-Oct-2022 21:56:01] INFO --> jobs to run: update.php
[PID-38343] [11-Oct-2022 21:56:01] INFO --> >>> trying to run "update"
[PID-38343] [11-Oct-2022 21:56:01] INFO --> lock "update" acquired
[PID-38343] [11-Oct-2022 21:56:01] INFO --> processing the job ...
[PID-38343] [11-Oct-2022 21:56:01] INFO --> <<< job done, releasing lock "update"
====
[PID-38392] [11-Oct-2022 21:57:01] INFO --> jobs to run: update.php
[PID-38392] [11-Oct-2022 21:57:01] INFO --> >>> trying to run "update"
[PID-38392] [11-Oct-2022 21:57:01] INFO --> lock "update" acquired
[PID-38392] [11-Oct-2022 21:57:01] INFO --> processing the job ...
[PID-38392] [11-Oct-2022 21:57:01] INFO --> <<< job done, releasing lock "update"
====
[PID-38451] [11-Oct-2022 21:58:01] INFO --> jobs to run: update.php
[PID-38451] [11-Oct-2022 21:58:01] INFO --> >>> trying to run "update"
[PID-38451] [11-Oct-2022 21:58:01] INFO --> lock "update" acquired
[PID-38451] [11-Oct-2022 21:58:01] INFO --> processing the job ...
[PID-38451] [11-Oct-2022 21:58:01] INFO --> <<< job done, releasing lock "update"
====
[PID-38506] [11-Oct-2022 21:59:01] INFO --> jobs to run: update.php
[PID-38506] [11-Oct-2022 21:59:01] INFO --> >>> trying to run "update"
[PID-38506] [11-Oct-2022 21:59:01] INFO --> lock "update" acquired
[PID-38506] [11-Oct-2022 21:59:01] INFO --> processing the job ...
[PID-38506] [11-Oct-2022 21:59:01] INFO --> <<< job done, releasing lock "update"
====
[PID-38552] [11-Oct-2022 22:00:01] INFO --> jobs to run: update.php
[PID-38552] [11--2022 21:52:01] INFO --> = email total: 180.00 KiB
[11-Oct-2022 21:52:01] INFO --> databases
[11-Oct-2022 21:52:01] INFO --> database "tracer_db1": 112.00 KiB
[11-Oct-2022 21:52:01] INFO --> database "tracer_db2": 544.00 KiB
[11-Oct-2022 21:52:01] INFO --> database "tracer_db3": 0 B
[11-Oct-2022 21:52:01] INFO --> = database total: 656.00 KiB
[11-Oct-2022 21:52:01] INFO --> = user "tracer" total: 28.73 MiB / unlimited - 0.00 %
====
[11-Oct-2022 22:52:01] INFO --> loading user...
[11-Oct-2022 22:52:01] INFO --> select user "tracer"
[11-Oct-2022 22:52:01] INFO --> webspace
[11-Oct-2022 22:52:01] INFO --> = webspace total: 27.91 MiB
[11-Oct-2022 22:52:01] INFO --> email
[11-Oct-2022 22:52:01] INFO --> mailbox "tracer@lab.24unix.net": 180.00 KiB / 1.00 GiB - 0.02 %
[11-Oct-2022 22:52:01] INFO --> = email total: 180.00 KiB
[11-Oct-2022 22:52:01] INFO --> databases
[11-Oct-2022 22:52:01] INFO --> database "tracer_db1": 112.00 KiB
[11-Oct-2022 22:52:01] INFO --> database "tracer_db2": 544.00 KiB
[11-Oct-2022 22:52:01] INFO --> database "tracer_db3": 0 B
[11-Oct-2022 22:52:01] INFO --> = database total: 656.00 KiB
[11-Oct-2022 22:52:01] INFO --> = user "tracer" total: 28.73 MiB / unlimited - 0.00 %
====
[11-Oct-2022 23:52:02] INFO --> loading user...
[11-Oct-2022 23:52:02] INFO --> select user "tracer"
[11-Oct-2022 23:52:02] INFO --> webspace
[11-Oct-2022 23:52:02] INFO --> = webspace total: 27.91 MiB
[11-Oct-2022 23:52:02] INFO --> email
[11-Oct-2022 23:52:02] INFO --> mailbox "tracer@lab.24unix.net": 180.00 KiB / 1.00 GiB - 0.02 %
[11-Oct-2022 23:52:02] INFO --> = email total: 180.00 KiB
[11-Oct-2022 23:52:02] INFO --> databases
[11-Oct-2022 23:52:02] INFO --> database "tracer_db1": 112.00 KiB
[11-Oct-2022 23:52:02] INFO --> database "tracer_db2": 544.00 KiB
[11-Oct-2022 23:52:02] INFO --> database "tracer_db3": 0 B
[11-Oct-2022 23:52:02] INFO --> = database total: 656.00 KiB
[11-Oct-2022 23:52:02] INFO --> = user "tracer" total: 28.73 MiB / unlimited - 0.00 %
====
[12-Oct-2022 00:52:01] INFO --> loading user...
[12-Oct-2022 00:52:01] INFO --> select user "tracer"
[12-Oct-2022 00:52:01] INFO --> webspace
[12-Oct-2022 00:52:01] INFO --> = webspace total: 27.91 MiB
[12-Oct-2022 00:52:01] INFO --> email
[12-Oct-2022 00:52:01] INFO --> mailbox "tracer@lab.24unix.net": 180.00 KiB / 1.00 GiB - 0.02 %
[12-Oct-2022 00:52:01] INFO --> = email total: 180.00 KiB
[12-Oct-2022 00:52:01] INFO --> databases
[12-Oct-2022 00:52:01] INFO --> database "tracer_db1": 112.00 KiB
[12-Oct-2022 00:52:01] INFO --> database "tracer_db2": 544.00 KiB
[12-Oct-2022 00:52:01] INFO --> database "tracer_db3": 0 B
[12-Oct-2022 00:52:01] INFO --> = database total: 656.00 KiB
[12-Oct-2022 00:52:01] INFO --> = user "tracer" total: 28.73 MiB / unlimited - 0.00 %
====
[12-Oct-2022 01:52:01] INFO --> loading user...
[12-Oct-2022 01:52:01] INFO --> select user "tracer"
[12-Oct-2022 01:52:01] INFO --> webspace
[12-Oct-2022 01:52:01] INFO --> = webspace total: 27.91 MiB
[12-Oct-2022 01:52:01] INFO --> email
[12-Oct-2022 01:52:01] INFO --> mailbox "tracer@lab.24unix.net": 180.00 KiB / 1.00 GiB - 0.02 %
[12-Oct-2022 01:52:01] INFO --> = email total: 180.00 KiB
[12-Oct-2022 01:52:01] INFO --> databases
[12-Oct-2022 01:52:01] INFO --> database "tracer_db1": 112.00 KiB
[12-Oct-2022 01:52:01] INFO --> database "tracer_db2": 544.00 KiB
[12-Oct-2022 01:52:01] INFO --> database "tracer_db3": 0 B
[12-Oct-2022 01:52:01] INFO --> = database total: 656.00 KiB
[12-Oct-2022 01:52:01] INFO --> = user "tracer" total: 28.73 MiB / unlimited - 0.00 %
====
[12-Oct-2022 02:52:01] INFO --> loading user...
[12-Oct-2022 02:52:01] INFO --> select user "tracer"
[12-Oct-2022 02:52:01] INFO --> webspace
[12-Oct-2022 02:52:01] INFO --> = webspace total: 27.91 MiB
[12-Oct-2022 02:52:01] INFO --> email
[12-Oct-2022 02:52:01] INFO --> mailbox "tracer@lab.24unix.===
[11-Oct-2022 21:55:01] INFO --> load tasks... nothing to do
====
[11-Oct-2022 21:56:01] INFO --> load tasks... nothing to do
====
[11-Oct-2022 21:57:01] INFO --> load tasks... nothing to do
====
[11-Oct-2022 21:58:01] INFO --> load tasks... nothing to do
====
[11-Oct-2022 21:59:01] INFO --> load tasks... nothing to do
====
[11-Oct-2022 22:00:01] INFO --> load tasks... nothing to do
====
[11-Oct-2022 22:01:02] INFO --> load tasks... nothing to do
====
[11-Oct-2022 22:02:01] INFO --> load tasks... nothing to do
====
[11-Oct-2022 22:03:01] INFO --> load tasks... nothing to do
====
[11-Oct-2022 22:04:01] INFO --> load tasks... nothing to do
====
[11-Oct-2022 22:05:01] INFO --> load tasks... nothing to do
====
[11-Oct-2022 22:06:01] INFO --> load tasks... nothing to do
====
[11-Oct-2022 22:07:01] INFO --> load tasks... nothing to do
====
[11-Oct-2022 22:08:01] INFO --> load tasks... nothing to do
====
[11-Oct-2022 22:09:02] INFO --> load tasks... nothing to do
====
[11-Oct-2022 22:10:01] INFO --> load tasks... nothing to do
====
[11-Oct-2022 22:11:01] INFO --> load tasks... nothing to do
====
[11-Oct-2022 22:12:01] INFO --> load tasks... nothing to do
====
[11-Oct-2022 22:13:01] INFO --> load tasks... nothing to do
====
[11-Oct-2022 22:14:01] INFO --> load tasks... nothing to do
====
[11-Oct-2022 22:15:01] INFO --> load tasks... nothing to do
====
[11-Oct-2022 22:16:02] INFO --> load tasks... nothing to do
====
[11-Oct-2022 22:17:01] INFO --> load tasks... nothing to do
====
[11-Oct-2022 22:18:01] INFO --> load tasks... nothing to do
====
[11-Oct-2022 22:19:01] INFO --> load tasks... nothing to do
====
[11-Oct-2022 22:20:01] INFO --> load tasks... nothing to do
====
[11-Oct-2022 22:21:01] INFO --> load tasks... nothing to do
====
[11-Oct-2022 22:22:01] INFO --> load tasks... nothing to do
====
[11-Oct-2022 22:23:01] INFO --> load tasks... nothing to do
====
[11-Oct-2022 22:24:01] INFO --> load tasks... nothing to do
====
[11-Oct-2022 22:25:02] INFO --> load tasks... nothing to do
====
[11-Oct-2022 22:26:01] INFO --> load tasks... nothing to do
====
[11-Oct-2022 22:27:01] INFO --> load tasks... nothing to do
====
[11-Oct-2022 22:28:01] INFO --> load tasks... nothing to do
====
[11-Oct-2022 22:29:01] INFO --> load tasks... nothing to do
====
[11-Oct-2022 22:30:01] INFO --> load tasks... nothing to do
====
[11-Oct-2022 22:31:01] INFO --> load tasks... nothing to do
====
[11-Oct-2022 22:32:01] INFO --> load tasks... nothing to do
====
[11-Oct-2022 22:33:02] INFO --> load tasks... nothing to do
====
[11-Oct-2022 22:34:01] INFO --> load tasks... nothing to do
====
[11-Oct-2022 22:35:01] INFO --> load tasks... nothing to do
====
[11-Oct-2022 22:36:01] INFO --> load tasks... nothing to do
====
[11-Oct-2022 22:37:01] INFO --> load tasks... nothing to do
====
[11-Oct-2022 22:38:01] INFO --> load tasks... nothing to do
====
[11-Oct-2022 22:39:01] INFO --> load tasks... nothing to do
====
[11-Oct-2022 22:40:01] INFO --> load tasks... nothing to do
====
[11-Oct-2022 22:41:02] INFO --> load tasks... nothing to do
====
[11-Oct-2022 22:42:01] INFO --> load tasks... nothing to do
====
[11-Oct-2022 22:43:01] INFO --> load tasks... nothing to do
====
[11-Oct-2022 22:44:01] INFO --> load tasks... nothing to do
====
[11-Oct-2022 22:45:01] INFO --> load tasks... nothing to do
====
[11-Oct-2022 22:46:01] INFO --> load tasks... nothing to do
====
[11-Oct-2022 22:47:01] INFO --> load tasks... nothing to do
====
[11-Oct-2022 22:48:01] INFO --> load tasks... nothing to do
====
[11-Oct-2022 22:49:02] INFO --> load tasks... nothing to do
====
[11-Oct-2022 22:50:01] INFO --> load tasks... nothing to do
====
[11-Oct-2022 22:51:01] INFO --> load tasks... nothing to do
====
[11-Oct-2022 22:52:01] INFO --> load tasks... nothing to do
====
[11-Oct-2022 22:53:01] INFO --> load tasks... nothing to do
====
[11-Oct-2022 22:54:01] INFO --> load tasks... nothing to do
====
[11-Oct-2022 22:55:01] INFO --> load tasks... nothing to do
====
[11-Oct-2022 22:56:01] INFO --> load tasks... nothing to do
====
Oct-2022 22:00:01] INFO --> >>> trying to run "update"
[PID-38552] [11-Oct-2022 22:00:01] INFO --> lock "update" acquired
[PID-38552] [11-Oct-2022 22:00:01] INFO --> processing the job ...
[PID-38552] [11-Oct-2022 22:00:01] INFO --> <<< job done, releasing lock "update"
====
[PID-38613] [11-Oct-2022 22:01:02] INFO --> jobs to run: update.php
[PID-38613] [11-Oct-2022 22:01:02] INFO --> >>> trying to run "update"
[PID-38613] [11-Oct-2022 22:01:02] INFO --> lock "update" acquired
[PID-38613] [11-Oct-2022 22:01:02] INFO --> processing the job ...
[PID-38613] [11-Oct-2022 22:01:02] INFO --> <<< job done, releasing lock "update"
====
[PID-38660] [11-Oct-2022 22:02:01] INFO --> jobs to run: update.php
[PID-38660] [11-Oct-2022 22:02:01] INFO --> >>> trying to run "update"
[PID-38660] [11-Oct-2022 22:02:01] INFO --> lock "update" acquired
[PID-38660] [11-Oct-2022 22:02:01] INFO --> processing the job ...
[PID-38660] [11-Oct-2022 22:02:01] INFO --> <<< job done, releasing lock "update"
====
[PID-38718] [11-Oct-2022 22:03:01] INFO --> jobs to run: update.php
[PID-38718] [11-Oct-2022 22:03:01] INFO --> >>> trying to run "update"
[PID-38718] [11-Oct-2022 22:03:01] INFO --> lock "update" acquired
[PID-38718] [11-Oct-2022 22:03:01] INFO --> processing the job ...
[PID-38718] [11-Oct-2022 22:03:01] INFO --> <<< job done, releasing lock "update"
====
[PID-38764] [11-Oct-2022 22:04:01] INFO --> jobs to run: update.php
[PID-38764] [11-Oct-2022 22:04:01] INFO --> >>> trying to run "update"
[PID-38764] [11-Oct-2022 22:04:01] INFO --> lock "update" acquired
[PID-38764] [11-Oct-2022 22:04:01] INFO --> processing the job ...
[PID-38764] [11-Oct-2022 22:04:01] INFO --> <<< job done, releasing lock "update"
====
[PID-38825] [11-Oct-2022 22:05:01] INFO --> jobs to run: update.php
[PID-38825] [11-Oct-2022 22:05:01] INFO --> >>> trying to run "update"
[PID-38825] [11-Oct-2022 22:05:01] INFO --> lock "update" acquired
[PID-38825] [11-Oct-2022 22:05:01] INFO --> processing the job ...
[PID-38825] [11-Oct-2022 22:05:01] INFO --> <<< job done, releasing lock "update"
====
[PID-38883] [11-Oct-2022 22:06:01] INFO --> jobs to run: update.php
[PID-38883] [11-Oct-2022 22:06:01] INFO --> >>> trying to run "update"
[PID-38883] [11-Oct-2022 22:06:01] INFO --> lock "update" acquired
[PID-38883] [11-Oct-2022 22:06:01] INFO --> processing the job ...
[PID-38883] [11-Oct-2022 22:06:01] INFO --> <<< job done, releasing lock "update"
====
[PID-38941] [11-Oct-2022 22:07:01] INFO --> jobs to run: update.php
[PID-38941] [11-Oct-2022 22:07:01] INFO --> >>> trying to run "update"
[PID-38941] [11-Oct-2022 22:07:01] INFO --> lock "update" acquired
[PID-38941] [11-Oct-2022 22:07:01] INFO --> processing the job ...
[PID-38941] [11-Oct-2022 22:07:01] INFO --> <<< job done, releasing lock "update"
====
[PID-38987] [11-Oct-2022 22:08:01] INFO --> jobs to run: update.php
[PID-38987] [11-Oct-2022 22:08:01] INFO --> >>> trying to run "update"
[PID-38987] [11-Oct-2022 22:08:01] INFO --> lock "update" acquired
[PID-38987] [11-Oct-2022 22:08:01] INFO --> processing the job ...
[PID-38987] [11-Oct-2022 22:08:01] INFO --> <<< job done, releasing lock "update"
====
[PID-39048] [11-Oct-2022 22:09:02] INFO --> jobs to run: update.php
[PID-39048] [11-Oct-2022 22:09:02] INFO --> >>> trying to run "update"
[PID-39048] [11-Oct-2022 22:09:02] INFO --> lock "update" acquired
[PID-39048] [11-Oct-2022 22:09:02] INFO --> processing the job ...
[PID-39048] [11-Oct-2022 22:09:02] INFO --> <<< job done, releasing lock "update"
====
[PID-39168] [11-Oct-2022 22:10:01] INFO --> jobs to run: update.php
[PID-39168] [11-Oct-2022 22:10:01] INFO --> >>> trying to run "update"
[PID-39168] [11-Oct-2022 22:10:01] INFO --> lock "update" acquired
[PID-39168] [11-Oct-2022 22:10:01] INFO --> processing the job ...
[PID-39168] [11-Oct-2022 22:10:01] INFO --> <<< job done, releasing lock "update"
====
[PID-39214] [11-Oct-2022 22:11:01] INFO --> jobs to run: update.php
[PID-39214] [11-Oct-2022 22:11:01] INFO --> >>> trying to run "update"
[PID-39214] [11-Oct-2022 --> <<< job done, releasing lock "update"
====
[PID-16869] [11-Oct-2022 18:09:01] INFO --> jobs to run: update.php
[PID-16869] [11-Oct-2022 18:09:01] INFO --> >>> trying to run "update"
[PID-16869] [11-Oct-2022 18:09:01] INFO --> lock "update" acquired
[PID-16869] [11-Oct-2022 18:09:01] INFO --> processing the job ...
[PID-16869] [11-Oct-2022 18:09:01] INFO --> <<< job done, releasing lock "update"
====
[PID-17042] [11-Oct-2022 18:10:01] INFO --> jobs to run: update.php
[PID-17042] [11-Oct-2022 18:10:01] INFO --> >>> trying to run "update"
[PID-17042] [11-Oct-2022 18:10:01] INFO --> lock "update" acquired
[PID-17042] [11-Oct-2022 18:10:01] INFO --> processing the job ...
[PID-17042] [11-Oct-2022 18:10:01] INFO --> <<< job done, releasing lock "update"
====
[PID-17193] [11-Oct-2022 18:11:01] INFO --> jobs to run: update.php
[PID-17193] [11-Oct-2022 18:11:01] INFO --> >>> trying to run "update"
[PID-17193] [11-Oct-2022 18:11:01] INFO --> lock "update" acquired
[PID-17193] [11-Oct-2022 18:11:01] INFO --> processing the job ...
[PID-17193] [11-Oct-2022 18:11:01] INFO --> <<< job done, releasing lock "update"
====
[PID-17331] [11-Oct-2022 18:12:02] INFO --> jobs to run: update.php
[PID-17331] [11-Oct-2022 18:12:02] INFO --> >>> trying to run "update"
[PID-17331] [11-Oct-2022 18:12:02] INFO --> lock "update" acquired
[PID-17331] [11-Oct-2022 18:12:02] INFO --> processing the job ...
[PID-17331] [11-Oct-2022 18:12:02] INFO --> <<< job done, releasing lock "update"
====
[PID-17410] [11-Oct-2022 18:13:01] INFO --> jobs to run: update.php
[PID-17410] [11-Oct-2022 18:13:01] INFO --> >>> trying to run "update"
[PID-17410] [11-Oct-2022 18:13:01] INFO --> lock "update" acquired
[PID-17410] [11-Oct-2022 18:13:01] INFO --> processing the job ...
[PID-17410] [11-Oct-2022 18:13:01] INFO --> <<< job done, releasing lock "update"
====
[PID-17540] [11-Oct-2022 18:14:01] INFO --> jobs to run: update.php
[PID-17540] [11-Oct-2022 18:14:01] INFO --> >>> trying to run "update"
[PID-17540] [11-Oct-2022 18:14:01] INFO --> lock "update" acquired
[PID-17540] [11-Oct-2022 18:14:01] INFO --> processing the job ...
[PID-17540] [11-Oct-2022 18:14:01] INFO --> <<< job done, releasing lock "update"
====
[PID-17677] [11-Oct-2022 18:15:01] INFO --> jobs to run: update.php
[PID-17677] [11-Oct-2022 18:15:01] INFO --> >>> trying to run "update"
[PID-17677] [11-Oct-2022 18:15:01] INFO --> lock "update" acquired
[PID-17677] [11-Oct-2022 18:15:01] INFO --> processing the job ...
[PID-17677] [11-Oct-2022 18:15:01] INFO --> <<< job done, releasing lock "update"
====
[PID-17778] [11-Oct-2022 18:16:01] INFO --> jobs to run: update.php
[PID-17778] [11-Oct-2022 18:16:01] INFO --> >>> trying to run "update"
[PID-17778] [11-Oct-2022 18:16:01] INFO --> lock "update" acquired
[PID-17778] [11-Oct-2022 18:16:01] INFO --> processing the job ...
[PID-17778] [11-Oct-2022 18:16:01] INFO --> <<< job done, releasing lock "update"
====
[PID-17917] [11-Oct-2022 18:17:01] INFO --> jobs to run: update.php
[PID-17917] [11-Oct-2022 18:17:01] INFO --> >>> trying to run "update"
[PID-17917] [11-Oct-2022 18:17:01] INFO --> lock "update" acquired
[PID-17917] [11-Oct-2022 18:17:01] INFO --> processing the job ...
[PID-17917] [11-Oct-2022 18:17:01] INFO --> <<< job done, releasing lock "update"
====
[PID-18023] [11-Oct-2022 18:18:01] INFO --> jobs to run: update.php
[PID-18023] [11-Oct-2022 18:18:01] INFO --> >>> trying to run "update"
[PID-18023] [11-Oct-2022 18:18:01] INFO --> lock "update" acquired
[PID-18023] [11-Oct-2022 18:18:01] INFO --> processing the job ...
[PID-18023] [11-Oct-2022 18:18:01] INFO --> <<< job done, releasing lock "update"
====
[PID-18105] [11-Oct-2022 18:19:01] INFO --> jobs to run: update.php
[PID-18105] [11-Oct-2022 18:19:01] INFO --> >>> trying to run "update"
[PID-18105] [11-Oct-2022 18:19:01] INFO --> lock "update" acquired
[PID-18105] [11-Oct-2022 18:19:01] INFO --> processing the job ...
[PID-18105] [11-Oct-2022 18:19:01] INFO --> <<< job done, releasing lock "update"
====
[PID-18190] [11-Oct-2022 18:20:01] INFO --> jobs to run: update.php
[PID-18190] [11-Oct-2022 18:20:01] INFO --> >>> trying to run "update"
[PID-18190] [11-Oct-2022 18:20:01] INFO --> lock "update" acquired
[PID-18190] [11-Oct-2022 18:20:01] INFO --> processing the job ...
[PID-18190] [11-Oct-2022 18:20:01] INFO --> <<< job done, releasing lock "update"
====
[PID-18285] [11-Oct-2022 18:21:01] INFO --> jobs to run: update.php
[PID-18285] [11-Oct-2022 18:21:01] INFO --> >>> trying to run "update"
[PID-18285] [11-Oct-2022 18:21:01] INFO --> lock "update" acquired
[PID-18285] [11-Oct-2022 18:21:01] INFO --> processing the job ...
[PID-18285] [11-Oct-2022 18:21:01] INFO --> <<< job done, releasing lock "update"
====
[PID-18375] [11-Oct-2022 18:22:02] INFO --> jobs to run: update.php
[PID-18375] [11-Oct-2022 18:22:02] INFO --> >>> trying to run "update"
[PID-18375] [11-Oct-2022 18:22:02] INFO --> lock "update" acquired
[PID-18375] [11-Oct-2022 18:22:02] INFO --> processing the job ...
[PID-18375] [11-Oct-2022 18:22:02] INFO --> <<< job done, releasing lock "update"
====
[PID-18505] [11-Oct-2022 18:23:01] INFO --> jobs to run: update.php
[PID-18505] [11-Oct-2022 18:23:01] INFO --> >>> trying to run "update"
[PID-18505] [11-Oct-2022 18:23:01] INFO --> lock "update" acquired
[PID-18505] [11-Oct-2022 18:23:01] INFO --> processing the job ...
[PID-18505] [11-Oct-2022 18:23:01] INFO --> <<< job done, releasing lock "update"
====
[PID-18640] [11-Oct-2022 18:24:01] INFO --> jobs to run: update.php
[PID-18640] [11-Oct-2022 18:24:01] INFO --> >>> trying to run "update"
[PID-18640] [11-Oct-2022 18:24:01] INFO --> lock "update" acquired
[PID-18640] [11-Oct-2022 18:24:01] INFO --> processing the job ...
[PID-18640] [11-Oct-2022 18:24:01] INFO --> <<< job done, releasing lock "update"
====
[PID-18743] [11-Oct-2022 18:25:01] INFO --> jobs to run: update.php
[PID-18743] [11-Oct-2022 18:25:01] INFO --> >>> trying to run "update"
[PID-18743] [11-Oct-2022 18:25:01] INFO --> lock "update" acquired
[PID-18743] [11-Oct-2022 18:25:01] INFO --> processing the job ...
[PID-18743] [11-Oct-2022 18:25:01] INFO --> <<< job done, releasing lock "update"
====
[PID-18850] [11-Oct-2022 18:26:01] INFO --> jobs to run: update.php
[PID-18850] [11-Oct-2022 18:26:01] INFO --> >>> trying to run "update"
[PID-18850] [11-Oct-2022 18:26:01] INFO --> lock "update" acquired
[PID-18850] [11-Oct-2022 18:26:01] INFO --> processing the job ...
[PID-18850] [11-Oct-2022 18:26:01] INFO --> <<< job done, releasing lock "update"
====
[PID-18970] [11-Oct-2022 18:27:01] INFO --> jobs to run: update.php
[PID-18970] [11-Oct-2022 18:27:01] INFO --> >>> trying to run "update"
[PID-18970] [11-Oct-2022 18:27:01] INFO --> lock "update" acquired
[PID-18970] [11-Oct-2022 18:27:01] INFO --> processing the job ...
[PID-18970] [11-Oct-2022 18:27:01] INFO --> <<< job done, releasing lock "update"
====
[PID-19096] [11-Oct-2022 18:28:01] INFO --> jobs to run: update.php
[PID-19096] [11-Oct-2022 18:28:01] INFO --> >>> trying to run "update"
[PID-19096] [11-Oct-2022 18:28:01] INFO --> lock "update" acquired
[PID-19096] [11-Oct-2022 18:28:01] INFO --> processing the job ...
[PID-19096] [11-Oct-2022 18:28:01] INFO --> <<< job done, releasing lock "update"
====
[PID-19230] [11-Oct-2022 18:29:01] INFO --> jobs to run: update.php
[PID-19230] [11-Oct-2022 18:29:01] INFO --> >>> trying to run "update"
[PID-19230] [11-Oct-2022 18:29:01] INFO --> lock "update" acquired
[PID-19230] [11-Oct-2022 18:29:01] INFO --> processing the job ...
[PID-19230] [11-Oct-2022 18:29:01] INFO --> <<< job done, releasing lock "update"
====
[PID-19332] [11-Oct-2022 18:30:02] INFO --> jobs to run: update.php
[PID-19332] [11-Oct-2022 18:30:02] INFO --> >>> trying to run "update"
[PID-19332] [11-Oct-2022 18:30:02] INFO --> lock "update" acquired
[PID-19332] [11-Oct-2022 18:30:02] INFO --> processing the job ...
[PID-19332] [11-Oct-2022 18:30:02] INFO --> <<< job done, releasing lock "update"
====
[PID-19476] [11-Oct-2022 18:31:01] INFO --> jobs to run: update.php
[PID-19476] [11-Oct-2022 18:31:01] INFO --> >>> trying to run "update"
[PID-19476] [11-Oct-2022 18:31:01] INFO --> lock "update" acquired
[PID-19476] [11-Oct-2022 18:31:01] INFO --> processing the job ...
[PID-19476] [11-Oct-2022 18:31:01] INFO --> <<< job done, releasing lock "update"
====
[PID-19578] [11-Oct-2022 18:32:01] INFO --> jobs to run: update.php
[PID-19578] [11-Oct-2022 18:32:01] INFO --> >>> trying to run "update"
[PID-19578] [11-Oct-2022 18:32:01] INFO --> lock "update" acquired
[PID-19578] [11-Oct-2022 18:32:01] INFO --> processing the job ...
[PID-19578] [11-Oct-2022 18:32:01] INFO --> <<< job done, releasing lock "update"
====
[PID-19696] [11-Oct-2022 18:33:01] INFO --> jobs to run: update.php
[PID-19696] [11-Oct-2022 18:33:01] INFO --> >>> trying to run "update"
[PID-19696] [11-Oct-2022 18:33:01] INFO --> lock "update" acquired
[PID-19696] [11-Oct-2022 18:33:01] INFO --> processing the job ...
[PID-19696] [11-Oct-2022 18:33:01] INFO --> <<< job done, releasing lock "update"
====
[PID-19786] [11-Oct-2022 18:34:01] INFO --> jobs to run: update.php
[PID-19786] [11-Oct-2022 18:34:01] INFO --> >>> trying to run "update"
[PID-19786] [11-Oct-2022 18:34:01] INFO --> lock "update" acquired
[PID-19786] [11-Oct-2022 18:34:01] INFO --> processing the job ...
[PID-19786] [11-Oct-2022 18:34:01] INFO --> <<< job done, releasing lock "update"
====
[PID-19887] [11-Oct-2022 18:35:01] INFO --> jobs to run: update.php
[PID-19887] [11-Oct-2022 18:35:01] INFO --> >>> trying to run "update"
[PID-19887] [11-Oct-2022 18:35:01] INFO --> lock "update" acquired
[PID-19887] [11-Oct-2022 18:35:01] INFO --> processing the job ...
[PID-19887] [11-Oct-2022 18:35:01] INFO --> <<< job done, releasing lock "update"
====
[PID-19981] [11-Oct-2022 18:36:01] INFO --> jobs to run: update.php
[PID-19981] [11-Oct-2022 18:36:01] INFO --> >>> trying to run "update"
[PID-19981] [11-Oct-2022 18:36:01] INFO --> lock "update" acquired
[PID-19981] [11-Oct-2022 18:36:01] INFO --> processing the job ...
[PID-19981] [11-Oct-2022 18:36:01] INFO --> <<< job done, releasing lock "update"
====
[PID-20076] [11-Oct-2022 18:37:02] IN

View File

@ -2,10 +2,10 @@
"openapi": "3.0.2", "openapi": "3.0.2",
"info": { "info": {
"title": "bindAPI", "title": "bindAPI",
"version": "0.0.2", "version": "0.0.1",
"description": "TODO …", "description": "TODO …",
"contact": { "contact": {
"name": "Micha Espey", "name": "micha Espey",
"email": "tracer@24unix.net" "email": "tracer@24unix.net"
} }
}, },
@ -31,9 +31,6 @@
{ {
"name": "Server" "name": "Server"
}, },
{
"name": "DNS"
},
{ {
"name": "Domains" "name": "Domains"
} }
@ -69,48 +66,6 @@
] ]
} }
}, },
"/dyndns/{hostname}": {
"post": {
"tags": [
"DNS"
],
"summary": "Updated a DynDNS host.",
"description": "Updates a predefined custom DNS entry.",
"operationId": "updateDynDNS",
"parameters": [
{
"name": "hostname",
"in": "path",
"required": true,
"schema": {
"type": "string"
}
}
],
"requestBody": {
"$ref": "#/components/requestBodies/dyndns-put"
},
"responses": {
"200": {
"description": "OK"
},
"204": {
"description": "No Content"
},
"401": {
"description": "API key is missing or invalid."
},
"404": {
"description": "Domain not found."
}
},
"security": [
{
"Authorization": []
}
]
}
},
"/domains": { "/domains": {
"get": { "get": {
"tags": [ "tags": [
@ -126,15 +81,7 @@
"401": { "401": {
"$ref": "#/components/responses/401-unauthorized" "$ref": "#/components/responses/401-unauthorized"
} }
}, }
"security": [
{
"Authorization": [
"read"
]
}
]
}, },
"post": { "post": {
"tags": [ "tags": [
@ -303,20 +250,6 @@
} }
}, },
"requestBodies": { "requestBodies": {
"dyndns-put": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/dyndns"
},
"example": {
"a": "1.2.3.4",
"aaaa": "1bad::babe"
}
}
}
},
"domain-post": { "domain-post": {
"required": true, "required": true,
"content": { "content": {
@ -461,20 +394,6 @@
} }
} }
}, },
"dyndns": {
"type": "object",
"properties": {
"a": {
"type": "string",
"example": "1.2.3.4"
},
"aaaa": {
"type": "string",
"example": "1bad::babe"
}
}
},
"domain": { "domain": {
"description": "Representation of a domain.\n", "description": "Representation of a domain.\n",
"type": "object", "type": "object",
@ -534,4 +453,4 @@
} }
} }
} }
} }

View File

@ -1,5 +0,0 @@
<?php
const DEFAULT_NS = 'ns2.24unix.net';
const NAMESERVERS = ['ns1.24unix.net', 'ns2.24unix.net'];

View File

@ -19,8 +19,7 @@
<script> <script>
window.onload = function () { window.onload = function () {
// Begin Swagger UI call region // Begin Swagger UI call region
let ui; const ui = SwaggerUIBundle({
ui = SwaggerUIBundle({
url: "/openapi/bindapi.json", url: "/openapi/bindapi.json",
dom_id: "#swagger-ui", dom_id: "#swagger-ui",
deepLinking: true, deepLinking: true,

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,107 @@
<?php declare(strict_types=1);
namespace App\Controller;
use UnhandledMatchError;
error_reporting(error_level: E_ALL);
/**
*
*/
class ApiController
{
/**
* @param String $requestType
* @param String $serverName
* @param int $versionIP
* @param String $apiKey
* @param String $command
* @param String $serverType
* @param array $body
*
* @return array
*/
function sendCommand(string $requestType, string $serverName, int $versionIP, string $apiKey, string $command, string $serverType, array $body = []): array
{
$error = false;
$curl = curl_init();
try {
match ($serverType) {
'panel' => curl_setopt(handle: $curl, option: CURLOPT_URL, value: "https://$serverName/api/v2/" . $command),
'nameserver' => curl_setopt(handle: $curl, option: CURLOPT_URL, value: "https://$serverName/api/" . $command)
};
} catch (UnhandledMatchError) {
echo 'Unhandled match: ' . $serverType;
}
curl_setopt(handle: $curl, option: CURLOPT_RETURNTRANSFER, value: 1);
curl_setopt(handle: $curl, option: CURLOPT_TIMEOUT_MS, value: 19999);
curl_setopt(handle: $curl, option: CURLOPT_HTTP_VERSION, value: CURL_HTTP_VERSION_2TLS);
if ($versionIP == 4) {
curl_setopt(handle: $curl, option: CURLOPT_IPRESOLVE, value: CURL_IPRESOLVE_V4);
} else {
curl_setopt(handle: $curl, option: CURLOPT_IPRESOLVE, value: CURL_IPRESOLVE_V6);
}
curl_setopt(handle: $curl, option: CURLOPT_HTTPHEADER, value: ["X-API-Key:$apiKey"]);
if ($requestType == "POST") {
curl_setopt(handle: $curl, option: CURLOPT_POST, value: true);
curl_setopt(handle: $curl, option: CURLOPT_POSTFIELDS, value: $body);
}
curl_setopt(handle: $curl, option: CURLOPT_CUSTOMREQUEST, value: $requestType);
if ($resultJSON = curl_exec(handle: $curl)) {
$httpResponse = curl_getinfo(handle: $curl)['http_code'];
switch ($httpResponse) {
case 200:
$apiResult = json_decode(json: $resultJSON);
if ($command == "ping") {
if ($apiResult->response == "pong") {
$result = $apiResult->response;
} else {
$result = $apiResult;
}
} else {
$result = $resultJSON;
}
break;
case 401:
$result = 'Missing or wrong API Key';
break;
case 404:
$result = '404 Not Found';
break;
case 500:
$result = 'server error';
break;
default:
$result = 'Unhandled error: ' . $httpResponse;
}
} else {
$error = true;
$result = curl_error(handle: $curl);
}
$info = curl_getinfo(handle: $curl);
$responseTime = $info['total_time'];
curl_close(handle: $curl);
return [
'responseTime' => $responseTime,
'error' => $error,
'data' => $result,
'header' => $httpResponse ?? ''
];
}
}

View File

@ -0,0 +1,20 @@
<?php declare(strict_types=1);
namespace App\Controller;
error_reporting(error_level: E_ALL);
use Exception;
use PDO;
use PDOException;
/**
*
*/
class ApiKeys
{
public function __construct(private DatabaseConnection $databaseConnection)
{}
}

1350
src/Controller/BindAPI.php Executable file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,68 +0,0 @@
<?php
namespace App\Controller\Commands;
use Closure;
/**
*
*/
class Command
{
public function __construct(
private readonly string $name,
private readonly Closure $callback,
private readonly array $mandatoryParameters = [],
private readonly array $optionalParameters = [],
private readonly string $description = ''
)
{
// no body
}
/**
* @return string
*/
public function getName(): string
{
return $this->name;
}
/**
* @return array
*/
public function getMandatoryParameters(): array
{
return $this->mandatoryParameters;
}
/**
* @return array
*/
public function getOptionalParameters(): array
{
return $this->optionalParameters;
}
/**
* @return string|null
*/
public function getDescription(): ?string
{
return $this->description;
}
/**
* @return Closure
*/
public function getCallback(): Closure
{
return $this->callback;
}
public function exec(): void
{
call_user_func(callback: $this->callback);
}
}

View File

@ -1,84 +0,0 @@
<?php
namespace App\Controller\Commands;
use App\Utilities\Colors;
/**
*
*/
class CommandGroup
{
private array $commands = [];
public function __construct(private readonly string $name, private readonly string $description)
{
// no body
}
public function addCommand(Command $command): ?CommandGroup
{
$this->commands[] = $command;
return $this;
}
public function getName(): string
{
return $this->name;
}
public function printCommands(int $longestCommandLength): void
{
echo Colors::YELLOW . str_pad(string: $this->name, length: $longestCommandLength + 1) . Colors::WHITE . $this->description . Colors::DEFAULT . PHP_EOL;
foreach ($this->commands as $command) {
echo Colors::GREEN . str_pad(string: ' ', length: $longestCommandLength + 1, pad_type: STR_PAD_LEFT) . $this->name . ':' . $command->getName();
foreach ($command->getMandatoryParameters() as $optionals) {
echo ' <' . $optionals . '>';
}
foreach ($command->getOptionalParameters() as $mandatory) {
echo ' {' . $mandatory . '}';
}
echo Colors::WHITE . ' ' . $command->getDescription();
echo Colors::DEFAULT . PHP_EOL;
}
}
public function findCommandByName(string $command): ?Command
{
foreach ($this->commands as $currentCommand) {
if ($command === $currentCommand->getName()) {
return $currentCommand;
}
}
return null;
}
private function findCommandGroupByName(string $command)
{
echo 'in check';
foreach ($this->commands as $currentCommand) {
print_r($currentCommand->getName());
if ($currentCommand instanceof CommandGroup) {
if ($command === $currentCommand->getName()) {
return $currentCommand;
}
}
}
return false;
}
public function exec(string $subcommand): bool
{
if ($command = $this->findCommandByName(command: $subcommand)) {
$command->exec();
return true;
} else {
return false;
}
}
}

View File

@ -1,88 +0,0 @@
<?php
namespace App\Controller\Commands;
use App\Utilities\Colors;
/**
*
*/
class CommandGroupContainer
{
private array $commandGroups = [];
public function addCommandGroup(CommandGroup $commandGroup): CommandGroupContainer
{
$this->commandGroups[] = $commandGroup;
return $this;
}
/**
* @return void
*/
public function printCommands(): void
{
$longestCommandLength = $this->getLongestCommandLength();
foreach ($this->commandGroups as $commandGroup) {
$commandGroup->printCommands($longestCommandLength);
}
}
/**
* @return int
*/
public function getLongestCommandLength(): int
{
$longest = 0;
foreach ($this->commandGroups as $group) {
$len = strlen(string: $group->getName());
if ($len > $longest) {
$longest = $len;
}
}
return $longest;
}
private function findGroupByName(string $command): ?CommandGroup
{
foreach ($this->commandGroups as $group) {
if ($group->getName() === $command) {
return $group;
}
}
return null;
}
public function run(string $command, string $subcommand): void
{
if ($subcommand !== '') {
if ($group = $this->findGroupByName(command: $command)) {
if ($group->exec(subcommand: $subcommand)) {
exit(0);
} else {
echo Colors::DEFAULT . 'Unknown subcommand ' . Colors::YELLOW . $subcommand . Colors::DEFAULT .' for ' . Colors::YELLOW . $command . Colors::DEFAULT . '.' . PHP_EOL;
exit(1);
}
} else {
echo Colors::DEFAULT . 'Unknown command group ' . Colors::YELLOW . $command . Colors::DEFAULT . '.' . PHP_EOL;
exit(1);
}
} else {
// check for command group and print available commands
foreach ($this->commandGroups as $group) {
if ($group->getName() === $command) {
echo 'Available subcommands for: ' . Colors::YELLOW . $group->getName() . Colors::DEFAULT . ':' . PHP_EOL;
$group->printCommands(strlen(string: $group->getName()));
exit(0);
}
}
}
echo Colors::DEFAULT . 'Unknown command ' . Colors::YELLOW . $command . Colors::DEFAULT . '.' . PHP_EOL;
}
}

View File

@ -1,70 +0,0 @@
<?php
namespace App\Controller;
use App\Utilities\Colors;
class ConfigController
{
private array $config;
private static $missingEncryptionShown = false;
public function __construct(private readonly bool $quiet, bool $test = false)
{
if ($test) {
$configFile = dirname(path: __DIR__, levels: 2) . "/config.json.test";
if (!file_exists(filename: $configFile)) {
echo 'No testing (config.json.test) config has benn setup.' . PHP_EOL;
exit(1);
}
} else {
$configFile = dirname(path: __DIR__, levels: 2) . "/config.json.local";
if (!file_exists(filename: $configFile)) {
$configFile = dirname(path: __DIR__, levels: 2) . "/config.json";
}
if (!file_exists(filename: $configFile)) {
echo 'Missing config file' . PHP_EOL;
if (confirm(message: 'Should I create a new config based on config.json.sample?')) {
copy(from: 'config.json.sample', to: 'config.json');
echo 'Config file has been generated. Adjust it to your needs, then proceed to database setup.' . PHP_EOL;
} else {
echo 'You first have to setup the bindAPI. Bye.' . PHP_EOL;
exit(0);
}
exit(1);
}
}
$configJSON = file_get_contents(filename: $configFile);
// 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 $configJSON . PHP_EOL;
exit(1);
}
$this->config = json_decode(json: $configJSON, associative: true);
if (!ConfigController::$missingEncryptionShown) {
if (!isset($this->config['encryptionKey']) || ($this->config['encryptionKey'] === '1bad::babe')) {
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
{
if (isset($this->config[$configKey])) {
return $this->config[$configKey];
} else {
return null;
}
}
}

View File

@ -0,0 +1,125 @@
<?php
namespace App\Controller;
error_reporting(error_level: E_ALL);
use PDO;
use PDOException;
/**
*
*/
class DatabaseConnection
{
private PDO $dbConnection;
const TABLE_PREFIX = '';
const TABLE_DOMAINS = self::TABLE_PREFIX . "domains";
const TABLE_NAMESERVERS = self::TABLE_PREFIX . "nameservers";
const TABLE_PANELS = self::TABLE_PREFIX . "panels";
const TABLE_APIKEYS = self::TABLE_PREFIX . "apikeys";
public function __construct(private array $config)
{
extract(array: $this->config);
try {
$this->dbConnection = new PDO(
dsn: "mysql:host=$dbHost;port=$dbPort;charset=utf8mb4;dbname=$dbDatabase",
username: $dbUser,
password: $dbPassword
);
$sql = "SHOW TABLES";
$statement = $this->dbConnection->prepare(query: $sql);
$statement->execute();
$result = $statement->fetch();
if (empty($result)) {
// ALTER TABLE `domains` ADD `panel_id` INT NULL AFTER `id`;
echo 'Error: Cannot find tables.' . PHP_EOL;
if (confirm(message: 'Should I try to create them?')) {
$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();
echo 'Tables have been created.' . PHP_EOL;
}
exit(1);
}
} catch (PDOException $exception) {
echo $exception->getMessage() . PHP_EOL;
echo 'Did you create the database and adjust the config file?' . PHP_EOL;
echo PHP_EOL . 'You can create database an user via a panel or manually in mysql shell:' . PHP_EOL;
$password = $this->generatePassword();
echo 'Created an initial password: ' . $password . PHP_EOL;
echo 'CREATE DATABASE bindAPI;' . PHP_EOL;
echo "CREATE USER 'bindAPI'@'localhost' IDENTIFIED BY '$password';" . PHP_EOL;
echo "GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, INDEX, DROP, ALTER, CREATE TEMPORARY TABLES, LOCK TABLES ON bindAPI.* TO 'bindAPI'@'localhost';" . PHP_EOL;
echo 'There is no need to run FLUSH PRIVILEGES when using GRANT!' . PHP_EOL;
exit(1);
}
}
/**
* @param int $length
*
* @return string
*/
function generatePassword(int $length = 8): string
{
$chars = '23456789bcdfhkmnprstvzBCDFHJKLMNPRSTVZ';
$shuffled = str_shuffle(string: $chars);
return mb_substr(string: $shuffled, start: 0, length: $length);
}
/**
* @return \PDO
*/
public function getConnection(): PDO
{
return $this->dbConnection;
}
}

View File

@ -6,8 +6,6 @@ use App\Entity\Domain;
use App\Repository\DomainRepository; 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\Utilities\Colors;
use Monolog\Logger; use Monolog\Logger;
error_reporting(error_level: E_ALL); error_reporting(error_level: E_ALL);
@ -19,117 +17,52 @@ error_reporting(error_level: E_ALL);
*/ */
class DomainController class DomainController
{ {
public string $localZoneFile; private string $localZoneFile;
public string $localZonesDir; private string $localZonesDir;
public string $namedConfLocalFile; private string $namedConfLocalFile;
private string $zoneCachePath; private string $zoneCachePath;
private string $keyhelpNamedCond;
public function __construct( public function __construct(private NameserverRepository $nameserverRepository, private ApiController $checkController, private DomainRepository $domainRepository, private PanelRepository $panelRepository, private array $config, private Logger $log)
private readonly NameserverRepository $nameserverRepository,
private readonly ApiClient $checkController,
private readonly DomainRepository $domainRepository,
private readonly PanelRepository $panelRepository,
private readonly ConfigController $configController,
private readonly Logger $logger,
private readonly bool $quiet
)
{ {
if ($this->config['debug']) {
$this->log->debug(message: "__construct()");
}
$this->localZoneFile = '/etc/bind/local.zones'; $this->localZoneFile = '/etc/bind/local.zones';
$this->localZonesDir = '/etc/bind/zones/'; $this->localZonesDir = '/etc/bind/zones/';
$this->namedConfLocalFile = '/etc/bind/named.conf.local'; $this->namedConfLocalFile = '/etc/bind/named.conf.local';
$this->zoneCachePath = '/var/cache/bind/'; $this->zoneCachePath = '/var/cache/bind/';
$this-> keyhelpNamedCond = '/etc/bind/named.conf.keyhelp';
} }
function createIncludeFile(): void
function createIncludeFile()
{ {
$this->logger->debug(message: "createIncludeFile()"); if ($this->config['debug']) {
$this->log->debug(message: "createIncludeFile()");
}
$domains = $this->domainRepository->findAll(); $domains = $this->domainRepository->findAll();
$oFile = fopen(filename: $this->localZoneFile, mode: 'w'); $oFile = fopen(filename: $this->localZoneFile, mode: 'w');
foreach ($domains as $domain) { foreach ($domains as $domain) {
if (!$this->isMasterZone(domain: $domain)) { fputs(stream: $oFile, data: 'include "' . $this->localZonesDir . $domain->getName() . '";' . PHP_EOL);
fputs(stream: $oFile, data: 'include "' . $this->localZonesDir . $domain->getName() . '";' . PHP_EOL);
}
} }
fclose(stream: $oFile); fclose(stream: $oFile);
exec(command: '/usr/bin/named-checkconf', output: $output, result_code: $resultCode);
if ($resultCode != 0) {
echo 'There was an error:' . PHP_EOL;
foreach ($output as $line) {
echo $line . PHP_EOL;
}
echo 'You need to fix the error before the configuration can be activated.' . PHP_EOL;
exit(1);
}
exec(command: '/usr/sbin/rndc reload'); exec(command: '/usr/sbin/rndc reload');
} }
function updateSlaveZones(): void function deleteOnNameservers(Domain $domain)
{ {
$this->logger->debug(message: 'update slave zones'); if ($this->config['debug']) {
$this->log->debug(message: "deleteOnNameserver()");
$existingZones = glob(pattern: $this->localZonesDir . '*');
$domains = $this->domainRepository->findAll();
$longestEntry = $this->domainRepository->getLongestEntry(field: 'name');
$self = $this->panelRepository->getSelf();
foreach ($domains as $domain) {
$zoneFile = $this->localZonesDir . $domain->getName();
if (!$this->quiet) {
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 (!file_exists(filename: $zoneFile)) {
if (!$this->quiet) {
echo Colors::GREEN . ' OK' . Colors::DEFAULT . PHP_EOL;
}
$this->createSlaveZoneFile(domain: $domain);
} else {
if (($key = array_search(needle: $zoneFile, haystack: $existingZones)) !== false) {
if (isset($existingZones[$key])) {
unset($existingZones[$key]);
}
} else {
echo 'missing value: ' . $zoneFile;
}
if (!$this->quiet) {
echo Colors::DEFAULT . 'Zone already exists.' . PHP_EOL;
}
}
} else {
if (!$this->quiet) {
echo Colors::DEFAULT . 'We are master for ' . Colors::YELLOW . $domain->getName() . PHP_EOL;
}
}
} }
// remove stale zones
foreach ($existingZones as $zone) {
if (!$this->quiet) {
echo 'Removing stale zone: ' . Colors::YELLOW . $zone . Colors::DEFAULT . PHP_EOL;
}
echo $zone . PHP_EOL;
unlink(filename: $zone);
}
$semaphore = $this->localZonesDir . 'zones.flag';
if (file_exists(filename: $semaphore)) {
unlink(filename: $semaphore);
$this->createIncludeFile();
}
}
function deleteOnNameservers(Domain $domain): void
{
$this->logger->debug(message: "deleteOnNameserver()");
$nameservers = $this->nameserverRepository->findAll(); $nameservers = $this->nameserverRepository->findAll();
foreach ($nameservers as $nameserver) { foreach ($nameservers as $nameserver) {
@ -137,36 +70,24 @@ class DomainController
'name' => $domain->getName() 'name' => $domain->getName()
]; ];
if (!empty($nameserver->getAaaa())) { if (!empty($nameserver->getAaaa())) {
$this->checkController->sendCommand( $this->checkController->sendCommand(requestType: 'DELETE', serverName: $nameserver->getName(), versionIP: 6, apiKey: $nameserver->getApikey(), command: 'delete', serverType: 'nameserver', body: $body);
requestType: 'DELETE',
serverName: $nameserver->getName(),
versionIP: 6,
apiKey: $nameserver->getApikey(),
command: 'delete',
serverType: 'nameserver',
body: $body);
} else { } else {
$this->checkController->sendCommand( $this->checkController->sendCommand(requestType: 'DELETE', serverName: $nameserver->getName(), versionIP: 4, apiKey: $nameserver->getApikey(), command: 'delete', serverType: 'nameserver', body: $body);
requestType: 'DELETE',
serverName: $nameserver->getName(),
versionIP: 4,
apiKey: $nameserver->getApikey(),
command: 'delete',
serverType: 'nameserver',
body: $body);
} }
} }
} }
/** /**
* @param Domain $domain * @param \App\Entity\Domain $domain
* *
* @return void * @return void
*/ */
function deleteZone(Domain $domain): void function deleteZone(Domain $domain)
{ {
$this->logger->debug(message: "deleteZone()"); if ($this->config['debug']) {
$this->log->debug(message: "deleteZone()");
}
$zoneFile = $this->localZonesDir . $domain->getName(); $zoneFile = $this->localZonesDir . $domain->getName();
if (file_exists(filename: "$zoneFile")) { if (file_exists(filename: "$zoneFile")) {
@ -175,213 +96,146 @@ class DomainController
$this->createIncludeFile(); $this->createIncludeFile();
$this->deleteOnNameservers(domain: $domain); $this->deleteOnNameservers(domain: $domain);
} }
function checkPermissions($impersonatedUserId = null): bool
{
$this->logger->debug(message: "checkPermissions()");
$setupIsValid = true;
if (!$this->quiet) {
echo 'Checking permissions...' . PHP_EOL;
}
if ($impersonatedUserId) {
$uid = $impersonatedUserId;
} else {
$uid = posix_geteuid();
}
if (!$this->quiet) {
echo "UID:\t" . Colors::YELLOW . $uid . PHP_EOL;
}
$pwuid = posix_getpwuid(user_id: $uid);
$name = $pwuid['name'];
if (!$this->quiet) {
echo Colors::DEFAULT . "Name:\t" . Colors::YELLOW . $name . PHP_EOL;
}
if (!$bindGroup = posix_getgrnam(name: 'bind')) {
$bindGroup = [];
}
$members = $bindGroup['members'] ?? [];
if (in_array(needle: $name, haystack: $members)) {
if (!$this->quiet) {
echo "\t$name" . Colors::DEFAULT . ' is in group ' . Colors::YELLOW . 'bind' . PHP_EOL;
}
} else {
$setupIsValid = false;
if (!$this->quiet) {
echo Colors::RED . "\t$name needs to be in group " . Colors::YELLOW . 'bind' . Colors::DEFAULT . '!' . PHP_EOL;
}
}
if (!$this->quiet) {
echo Colors::DEFAULT . 'Checking ' . Colors::YELLOW . $this->localZoneFile . PHP_EOL;
}
$localZoneFilePermissions = @fileperms(filename: $this->localZoneFile);
if ($localZoneFilePermissions & 0x0010) {
if (!$this->quiet) {
echo Colors::DEFAULT . "\t✅ Group has write access." . PHP_EOL;
}
} else {
$setupIsValid = false;
if (!$this->quiet) {
echo Colors::RED . "\t❌Group needs write permission!" . Colors::DEFAULT . PHP_EOL;
}
}
if (!$this->quiet) {
echo 'Checking ' . Colors::YELLOW . $this->namedConfLocalFile . PHP_EOL;
}
if (file_exists(filename: $this->namedConfLocalFile) && $namedConfLocal = file_get_contents(filename: $this->namedConfLocalFile)) {
if (!str_contains(haystack: $namedConfLocal, needle: $this->localZoneFile)) {
$setupIsValid = false;
if (!$this->quiet) {
echo "\t$this->localZoneFile" . Colors::RED . ' needs to be included in ' . Colors::YELLOW . $this->namedConfLocalFile . PHP_EOL;
}
} else {
if (!$this->quiet) {
echo "\t$this->localZoneFile" . Colors::DEFAULT . ' is included in ' . Colors::YELLOW . $this->namedConfLocalFile . PHP_EOL;
}
}
} else {
$setupIsValid = false;
if (!$this->quiet) {
echo "\t❌ No access to '$this->namedConfLocalFile' . Please check permissions" . PHP_EOL;
}
}
if (!$this->quiet) {
echo Colors::DEFAULT . 'Checking directory: ' . Colors::YELLOW . $this->localZonesDir . PHP_EOL;
}
$localZoneDirPermissions = @fileperms(filename: $this->localZonesDir);
if ($localZoneDirPermissions & 0x0010) {
if (!$this->quiet) {
echo "\t✅ Group has write access." . PHP_EOL;
}
} else {
$setupIsValid = false;
if (!$this->quiet) {
echo Colors::RED . "\t❌Group needs write permission!" . PHP_EOL;
}
}
return $setupIsValid;
}
/** /**
* @return void * @return void
*/ */
function checkDomains(): void function checkPermissions(): void
{ {
if (!file_exists(filename: $this->localZoneFile)) { if ($this->config['debug']) {
if (!$this->quiet) { $this->log->debug(message: "checkPermissions()");
echo Colors::DEFAULT . 'Local Zone file ' . Colors::YELLOW . $this->localZoneFile . Colors::DEFAULT . ' does not exist.' . PHP_EOL;
}
exit(1);
} }
$localZones = file_get_contents(filename: $this->localZoneFile);
$maxNameLength = $this->domainRepository->getLongestEntry(field: 'name');
$domains = $this->domainRepository->findAll();
foreach ($domains as $domain) { echo 'Checking permission:' . PHP_EOL . PHP_EOL;
$idString = '(' . $domain->getId() . ') '; $uid = posix_geteuid();
if (!$this->quiet) { print("UID:\t$uid" . PHP_EOL);
echo Colors::YELLOW .
str_pad(string: $domain->getName(), length: $maxNameLength + 1) $pwuid = posix_getpwuid(user_id: $uid);
. Colors::DEFAULT $name = $pwuid['name'];
. str_pad(string: $idString, length: 7, pad_type: STR_PAD_LEFT); print("Name:\t$name" . PHP_EOL);
} $bindGroup = posix_getgrnam(name: 'bind');
$members = $bindGroup['members'];
$hasError = false; if (in_array(needle: $name, haystack: $members)) {
if ($this->isMasterZone(domain: $domain)) { echo "\t$name is in group 'bind" . PHP_EOL;
if (!$this->quiet) { } else {
echo Colors::GREEN . 'Master Zone'; echo "\t$name needs to be in group $bindGroup!" . PHP_EOL;
}
}
echo 'Checking file: ' . $this->localZoneFile . PHP_EOL;
$localZoneFilePermissions = fileperms(filename: $this->localZoneFile);
if ($localZoneFilePermissions & 0x0010) {
echo "\t✅ Group has write access . " . PHP_EOL;
} else {
echo "\t❌Group needs write permission!" . PHP_EOL;
}
echo "Checking $this->namedConfLocalFile" . PHP_EOL;
if ($namedConfLocal = file_get_contents(filename: $this->namedConfLocalFile)) {
if (!str_contains(haystack: $namedConfLocal, needle: $this->localZoneFile)) {
echo "\t$this->localZoneFile needs to be included in $this->namedConfLocalFile . " . PHP_EOL;
} else { } else {
if (!str_contains(haystack: $localZones, needle: $domain->getName())) { echo "\t$this->localZoneFile is included in $this->namedConfLocalFile" . PHP_EOL;
if (!$this->quiet) {
echo Colors::RED . 'is missing in ' . Colors::YELLOW . $this->localZoneFile . Colors::DEFAULT;
}
$hasError = true;
} else {
if (!$this->quiet) {
echo Colors::GREEN . 'OK';
}
}
$zoneFile = $this->localZonesDir . $domain->getName();
if (!file_exists(filename: $zoneFile)) {
echo ' Missing zone file for ' . Colors::YELLOW . $zoneFile . Colors::DEFAULT;
$hasError = true;
}
if ($hasError) {
echo " Update zone (Domain) to create it.";
}
} }
if (!$this->quiet) { } else {
echo Colors::DEFAULT . PHP_EOL; echo "\t❌ No access to '$this->namedConfLocalFile' . Please check permissions" . PHP_EOL;
}
} }
echo 'Checking directory: ' . $this->localZonesDir . PHP_EOL;
$localZoneDirPermissions = fileperms(filename: $this->localZonesDir);
if ($localZoneDirPermissions & 0x0010) {
echo "\t✅ Group has write access . " . PHP_EOL;
} else {
echo "\t❌Group needs write permission!" . PHP_EOL;
}
} }
/** /**
* @param Domain $domain * @return array|bool
*/
function checkDomains(): array|bool
{
return true;
/*
$domains = $this->findAll();
if ($namedConfLocal = file_get_contents(filename: $this->namedConfLocalFile)) {
if (!str_contains(haystack: $namedConfLocal, needle: $this->localZoneFile)) {
return "$this->localZoneFile needs to be included in $this->namedConfLocalFile . ";
}
} else {
return "No access to '$this->namedConfLocalFile' . Please check permissions";
}
if (!fileperms($this->localZoneFile)) {
return "No access to $this->localZoneFile . Please check permissions . ";
}
$localZones = file_get_contents($this->localZoneFile);
foreach($domains as $domain) {
if(!str_contains($localZones, $domain['name'])) {
$errors[] = $domain['name'] . " is missing in '$this->localZoneFile'";
}
$zoneFile = $this->localZonesDir . $domain['name'];
if (!file_exists($zoneFile)) {
$errors[] = "Missing zone file for $zoneFile . Update zone to create it";
}
}
if (empty($errors)) {
return true;
} else {
return $errors;
}
*/
}
/**
* @param \App\Entity\Domain $domain
* *
* @return void * @return void
*/ */
public function createSlaveZoneFile(Domain $domain): bool public function createSlaveZoneFile(Domain $domain): void
{ {
touch(filename: $this->localZonesDir . 'zones.flag'); if ($this->config['debug']) {
$domainName = $domain->getName();
$domainName = $domain->getName(); $this->log->debug(message: "createZoneFile($domainName)");
$this->logger->info(message: "createZoneFile($domainName)"); }
// check if we're a master zone // check if we're a master zone
if ($this->isMasterZone(domain: $domain)) { $keyhelpConf = file_get_contents(filename: $this->keyhelpNamedCond);
//echo 'We are zone master for ' . $domainName . PHP_EOL; if (str_contains(haystack: $keyhelpConf, needle: $domain->getName())) {
return true; echo 'We a zone master for ' . $domain->getName() . PHP_EOL;
exit(1);
} }
if ($zoneFile = fopen(filename: $this->localZonesDir . $domainName, mode: 'w')) { if ($zonefile = fopen(filename: $this->localZonesDir . $domain->getName(), mode: 'w')) {
$panelName = $domain->getPanel(); $panelName = $domain->getPanel();
if (!$panel = $this->panelRepository->findByName(name: $panelName)) { $panel = $this->panelRepository->findByName(name: $panelName);
if (!$this->quiet) {
echo "Error: Panel $panelName doesn't exist." . PHP_EOL;
}
return false;
}
$a = $panel->getA(); $a = $panel->getA();
$aaaa = $panel->getAaaa(); $aaaa = $panel->getAaaa();
fputs(stream: $zoneFile, data: 'zone "' . $domainName . '"' . ' IN {' . PHP_EOL); fputs(stream: $zonefile, data: 'zone "' . $domain->getName() . '"' . ' IN {' . PHP_EOL);
fputs(stream: $zoneFile, data: "\ttype slave;" . PHP_EOL); fputs(stream: $zonefile, data: "\ttype slave;" . PHP_EOL);
fputs(stream: $zoneFile, data: "\tfile \"" . $this->zoneCachePath . $domainName . '.db";' . PHP_EOL); fputs(stream: $zonefile, data: "\tfile \"" . $this->zoneCachePath . $domain->getName() . '.db";' . PHP_EOL);
fputs(stream: $zoneFile, data: "\tmasters {" . PHP_EOL); fputs(stream: $zonefile, data: "\tmasters {" . PHP_EOL);
if (!empty($a)) { if (!empty($a)) {
fputs(stream: $zoneFile, data: "\t\t" . $a . ';' . PHP_EOL); fputs(stream: $zonefile, data: "\t\t" . $a . ';' . PHP_EOL);
} }
if (!empty($aaaa)) { if (!empty($aaaa)) {
fputs(stream: $zoneFile, data: "\t\t" . $aaaa . ';' . PHP_EOL); fputs(stream: $zonefile, data: "\t\t" . $aaaa . ';' . PHP_EOL);
} }
fputs(stream: $zoneFile, data: "\t};" . PHP_EOL); fputs(stream: $zonefile, data: "\t};" . PHP_EOL);
fputs(stream: $zoneFile, data: "};" . PHP_EOL); fputs(stream: $zonefile, data: "};" . PHP_EOL);
return true;
} else {
if (!$this->quiet) {
echo Colors::RED . ' Error: ' . Colors::DEFAULT . 'unable to create ' . Colors::YELLOW . $this->localZonesDir . $domainName . Colors::DEFAULT . PHP_EOL;
}
return false;
}
}
public function isMasterZone(Domain $domain): bool
{
if (file_exists(filename: '/etc/bind/keyhelp_domains/' . $domain->getName())) {
return true;
} else {
return false;
} }
$this->createIncludeFile();
} }
}
}

View File

@ -1,71 +0,0 @@
<?php
namespace App\Controller;
use Exception;
use SodiumException;
/**
*
*/
class EncryptionController
{
/**
* Encrypt a message
*
* @param string $message - message to encrypt
* @param string $key - encryption key
* @return string
*/
function safeEncrypt(string $message, string $key): string
{
try {
$binKey = sodium_hex2bin(string: $key);
$nonce = random_bytes(length: SODIUM_CRYPTO_SECRETBOX_NONCEBYTES);
$cipher = base64_encode(string: $nonce . sodium_crypto_secretbox(message: $message, nonce: $nonce, key: $binKey));
sodium_memzero(string: $message);
sodium_memzero(string: $key);
sodium_memzero(string: $binKey);
return $cipher;
} catch (Exception|SodiumException $e) {
exit($e->getMessage() . PHP_EOL);
}
}
/**
* Decrypt a message
*
* @param string $encrypted - message encrypted with safeEncrypt()
* @param string $key - encryption key
* @return string
*/
function safeDecrypt(string $encrypted, string $key): string
{
try {
$binKey = sodium_hex2bin(string: $key);
$decoded = base64_decode(string: $encrypted);
if ($decoded === false) {
throw new Exception(message: 'Decoding broken. Wrong payload.');
}
if (mb_strlen(string: $decoded, encoding: '8bit') < (SODIUM_CRYPTO_SECRETBOX_NONCEBYTES + SODIUM_CRYPTO_SECRETBOX_MACBYTES)) {
throw new Exception(message: 'Decoding broken. Incomplete message.');
}
$nonce = mb_substr(string: $decoded, start: 0, length: SODIUM_CRYPTO_SECRETBOX_NONCEBYTES, encoding: '8bit');
$ciphertext = mb_substr(string: $decoded, start: SODIUM_CRYPTO_SECRETBOX_NONCEBYTES, length: null, encoding: '8bit');
$plain = sodium_crypto_secretbox_open(ciphertext: $ciphertext, nonce: $nonce, key: $binKey);
if ($plain === false) {
throw new Exception(message: ' Incorrect key.' . PHP_EOL);
}
sodium_memzero(string: $ciphertext);
sodium_memzero(string: $key);
return $plain;
} catch(Exception|SodiumException $e) {
exit($e->getMessage());
}
}
}

View File

@ -0,0 +1,18 @@
<?php declare(strict_types=1);
namespace App\Controller;
error_reporting(error_level: E_ALL);
/**
*
*/
class NameserverController
{
public function __construct(private DatabaseConnection $databaseConnection)
{}
}

View File

@ -0,0 +1,19 @@
<?php declare(strict_types=1);
namespace App\Controller;
error_reporting(error_level: E_ALL);
/**
*
*/
class PanelController
{
public function __construct(private DatabaseConnection $databaseConnection)
{}
}

File diff suppressed because it is too large Load Diff

View File

@ -2,73 +2,89 @@
namespace App\Entity; namespace App\Entity;
use App\Controller\ConfigController; /**
use App\Controller\EncryptionController; *
use Exception; */
class Apikey class Apikey
{ {
public function __construct( private int $id;
private int $id = 0, private string $name;
private string $name = '', private string $apiTokenPrefix;
private string $apikey = '', private string $apiToken;
private string $apikeyPrefix = '',
private readonly string $passphrase = '', public function __construct(string $name, string $apiTokenPrefix, string $apiToken, int $id = 0)
private string $createdAt = '' {
) $this->id = $id;
{ $this->name = $name;
if ($this->passphrase) { $this->apiTokenPrefix = $apiTokenPrefix;
$configController = new ConfigController(quiet: true); $this->apiToken = $apiToken;
$encryptionController = new EncryptionController(); }
$encryptionKey = $configController->getConfig(configKey: 'encryptionKey');
/**
$this->apikey = strtok(string: $this->passphrase, token: '.'); * @return String
*/
try { public function getApiToken(): string
$this->apikey = $encryptionController->safeEncrypt(message: $this->passphrase, key: $encryptionKey); {
} catch (Exception $e) { return $this->apiToken;
exit($e->getMessage() . PHP_EOL); }
}
} /**
} * @return string
*/
public function getCreatedAt(): string public function getApiTokenPrefix(): string
{ {
return $this->createdAt; return $this->apiTokenPrefix;
} }
public function getApikey(): string
{ /**
return $this->apikey; * @return int
} */
public function getId(): int
public function getApikeyPrefix(): string {
{ return $this->id;
return $this->apikeyPrefix; }
}
/**
* @param int $id
public function getId(): int */
{ public function setId(int $id): void
return $this->id; {
} $this->id = $id;
}
public function getName(): string
{ /**
return $this->name; * @return String
} */
public function getName(): string
{
public function setApikey(string $apikey): void return $this->name;
{ }
$this->apikey = $apikey;
} /**
* @param string $apiTokenPrefix
*/
public function setName(string $name): void public function setApiTokenPrefix(string $apiTokenPrefix): void
{ {
$this->name = $name; $this->apiTokenPrefix = $apiTokenPrefix;
} }
/**
* @param String $apiToken
*/
public function setApiToken(string $apiToken): void
{
$this->apiToken = $apiToken;
}
/**
* @param String $name
*/
public function setName(string $name): void
{
$this->name = $name;
}
} }

View File

@ -2,6 +2,10 @@
namespace App\Entity; namespace App\Entity;
use App\Enums\PanelType;
/** /**
* *
*/ */

View File

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

View File

@ -1,44 +0,0 @@
<?php
namespace App\Entity\KeyHelp;
/**
*
*/
class Apache
{
private ?string $httpDirectives;
private ?string $httpsDirectives;
/**
* @return string
*/
public function getHttpDirectives(): string
{
return $this->httpDirectives;
}
/**
* @param string|null $httpDirectives
*/
public function setHttpDirectives(?string $httpDirectives): void
{
$this->httpDirectives = $httpDirectives;
}
/**
* @return string
*/
public function getHttpsDirectives(): string
{
return $this->httpsDirectives;
}
/**
* @param string|null $httpsDirectives
*/
public function setHttpsDirectives(?string $httpsDirectives): void
{
$this->httpsDirectives = $httpsDirectives;
}
}

View File

@ -1,405 +0,0 @@
<?php
namespace App\Entity\KeyHelp;
use DateTime;
/**
*
*/
class KeyHelpDomain
{
private int $id;
private int $idUser;
private int $idParentDomain;
private int $status;
private string $domain;
private string $domainUtf8;
private DateTime $createdAt;
private string $phpVersion;
private bool $isDisabled;
private ?DateTime $deleteOn;
private string $dkimTxtRecord;
private bool $isCustomDns;
private bool $isDnsDisabled;
private bool $isSubdomain;
private bool $isSystemDomain;
private bool $isEmailDomain;
private Target $target;
private Security $security;
private Apache $apache;
private string $dkimSelector;
private string $dkimRecord;
private ?string $dkimTextRecord;
public function __construct()
{
$this->dkimTextRecord = null;
}
private int $traffic;
private bool $isEmailSendingOnly;
public function isEmailSendingOnly(): bool
{
return $this->isEmailSendingOnly;
}
public function setIsEmailSendingOnly(bool $isEmailSendingOnly): void
{
$this->isEmailSendingOnly = $isEmailSendingOnly;
}
public function getTraffic(): int
{
return $this->traffic;
}
public function setTraffic(int $traffic): void
{
$this->traffic = $traffic;
}
public function getDkimTextRecord(): string
{
return $this->dkimTextRecord;
}
public function setDkimTextRecord(string $dkimTextRecord): void
{
$this->dkimTextRecord = $dkimTextRecord;
}
public function getDkimRecord(): string
{
return $this->dkimRecord;
}
public function setDkimRecord(string $dkimRecord): void
{
$this->dkimRecord = $dkimRecord;
}
public function getDkimSelector(): string
{
return $this->dkimSelector;
}
public function setDkimSelector(string $dkimSelector): void
{
$this->dkimSelector = $dkimSelector;
}
/**
* @return Apache
*/
public function getApache(): Apache
{
return $this->apache;
}
/**
* @param Apache $apache
*/
public function setApache(Apache $apache): void
{
$this->apache = $apache;
}
/**
* @return Security
*/
public function getSecurity(): Security
{
return $this->security;
}
/**
* @param Security $security
*/
public function setSecurity(Security $security): void
{
$this->security = $security;
}
/**
* @return Target
*/
public function getTarget(): Target
{
return $this->target;
}
/**
* @param Target $target
*/
public function setTarget(Target $target): void
{
$this->target = $target;
}
/**
* @return bool
*/
public function isEmailDomain(): bool
{
return $this->isEmailDomain;
}
/**
* @param bool $isEmailDomain
*/
public function setIsEmailDomain(bool $isEmailDomain): void
{
$this->isEmailDomain = $isEmailDomain;
}
/**
* @return bool
*/
public function isSystemDomain(): bool
{
return $this->isSystemDomain;
}
/**
* @param bool $isSystemDomain
*/
public function setIsSystemDomain(bool $isSystemDomain): void
{
$this->isSystemDomain = $isSystemDomain;
}
/**
* @return bool
*/
public function isSubdomain(): bool
{
return $this->isSubdomain;
}
/**
* @param bool $isSubdomain
*/
public function setIsSubdomain(bool $isSubdomain): void
{
$this->isSubdomain = $isSubdomain;
}
/**
* @return bool
*/
public function isDnsDisabled(): bool
{
return $this->isDnsDisabled;
}
/**
* @param bool $isDnsDisabled
*/
public function setIsDnsDisabled(bool $isDnsDisabled): void
{
$this->isDnsDisabled = $isDnsDisabled;
}
/**
* @return bool
*/
public function isCustomDns(): bool
{
return $this->isCustomDns;
}
/**
* @param bool $isCustomDns
*/
public function setIsCustomDns(bool $isCustomDns): void
{
$this->isCustomDns = $isCustomDns;
}
/**
* @return string
*/
public function getDkimTxtRecord(): string
{
return $this->dkimTxtRecord;
}
/**
* @param string $dkimTxtRecord
*/
public function setDkimTxtRecord(string $dkimTxtRecord): void
{
$this->dkimTxtRecord = $dkimTxtRecord;
}
/**
* @return DateTime
*/
public function getDeleteOn(): DateTime
{
return $this->deleteOn;
}
/**
* @param DateTime|null $deleteOn
*/
public function setDeleteOn(?DateTime $deleteOn): void
{
$this->deleteOn = $deleteOn;
}
/**
* @return bool
*/
public function isDisabled(): bool
{
return $this->isDisabled;
}
/**
* @param bool $isDisabled
*/
public function setIsDisabled(bool $isDisabled): void
{
$this->isDisabled = $isDisabled;
}
/**
* @return string
*/
public function getPhpVersion(): string
{
return $this->phpVersion;
}
/**
* @param string $phpVersion
*/
public function setPhpVersion(string $phpVersion): void
{
$this->phpVersion = $phpVersion;
}
/**
* @return DateTime
*/
public function getCreatedAt(): DateTime
{
return $this->createdAt;
}
/**
* @param DateTime $createdAt
*/
public function setCreatedAt(DateTime $createdAt): void
{
$this->createdAt = $createdAt;
}
/**
* @return string
*/
public function getDomainUtf8(): string
{
return $this->domainUtf8;
}
/**
* @param string $domainUtf8
*/
public function setDomainUtf8(string $domainUtf8): void
{
$this->domainUtf8 = $domainUtf8;
}
/**
* @return string
*/
public function getDomain(): string
{
return $this->domain;
}
/**
* @param string $domain
*/
public function setDomain(string $domain): void
{
$this->domain = $domain;
}
/**
* @return int
*/
public function getStatus(): int
{
return $this->status;
}
/**
* @param int $status
*/
public function setStatus(int $status): void
{
$this->status = $status;
}
/**
* @return int
*/
public function getIdParentDomain(): int
{
return $this->idParentDomain;
}
/**
* @param int $idParentDomain
*/
public function setIdParentDomain(int $idParentDomain): void
{
$this->idParentDomain = $idParentDomain;
}
/**
* @return int
*/
public function getIdUser(): int
{
return $this->idUser;
}
/**
* @param int $idUser
*/
public function setIdUser(int $idUser): void
{
$this->idUser = $idUser;
}
/**
* @return int
*/
public function getId(): int
{
return $this->id;
}
/**
* @param int $id
*/
public function setId(int $id): void
{
$this->id = $id;
}
}

View File

@ -1,143 +0,0 @@
<?php
namespace App\Entity\KeyHelp;
/**
*
*/
class Security
{
private int $idCertificate;
private bool $letsEncrypt;
private bool $forceHttps;
private bool $isHsts;
private int $hstsMaxAge;
private bool $hstsInclude;
private bool $hstsPreload;
private bool $isPreferHttps;
public function isPreferHttps(): bool
{
return $this->isPreferHttps;
}
public function setIsPreferHttps(bool $isPreferHttps): void
{
$this->isPreferHttps = $isPreferHttps;
}
/**
* @return int
*/
public function getIdCertificate(): int
{
return $this->idCertificate;
}
/**
* @param int $idCertificate
*/
public function setIdCertificate(int $idCertificate): void
{
$this->idCertificate = $idCertificate;
}
/**
* @return bool
*/
public function isLetsEncrypt(): bool
{
return $this->letsEncrypt;
}
/**
* @param bool $letsEncrypt
*/
public function setLetsEncrypt(bool $letsEncrypt): void
{
$this->letsEncrypt = $letsEncrypt;
}
/**
* @return bool
*/
public function isHsts(): bool
{
return $this->isHsts;
}
/**
* @param bool $isHsts
*/
public function setIsHsts(bool $isHsts): void
{
$this->isHsts = $isHsts;
}
/**
* @return int
*/
public function getHstsMaxAge(): int
{
return $this->hstsMaxAge;
}
/**
* @param int $hstsMaxAge
*/
public function setHstsMaxAge(int $hstsMaxAge): void
{
$this->hstsMaxAge = $hstsMaxAge;
}
/**
* @return bool
*/
public function isHstsInclude(): bool
{
return $this->hstsInclude;
}
/**
* @param bool $hstsInclude
*/
public function setHstsInclude(bool $hstsInclude): void
{
$this->hstsInclude = $hstsInclude;
}
/**
* @return bool
*/
public function isHstsPreload(): bool
{
return $this->hstsPreload;
}
/**
* @param bool $hstsPreload
*/
public function setHstsPreload(bool $hstsPreload): void
{
$this->hstsPreload = $hstsPreload;
}
/**
* @return bool
*/
public function isForceHttps(): bool
{
return $this->forceHttps;
}
/**
* @param bool $forceHttps
*/
public function setForceHttps(bool $forceHttps): void
{
$this->forceHttps = $forceHttps;
}
}

View File

@ -1,61 +0,0 @@
<?php
namespace App\Entity\KeyHelp;
/**
*
*/
class Target
{
private string $target;
private bool $isForwarding;
private ?string $forwardingType;
/**
* @return string
*/
public function getForwardingType(): string
{
return $this->forwardingType;
}
/**
* @param string|null $forwardingType
*/
public function setForwardingType(?string $forwardingType): void
{
$this->forwardingType = $forwardingType;
}
/**
* @return bool
*/
public function isForwarding(): bool
{
return $this->isForwarding;
}
/**
* @param bool $isForwarding
*/
public function setIsForwarding(bool $isForwarding): void
{
$this->isForwarding = $isForwarding;
}
/**
* @return string
*/
public function getTarget(): string
{
return $this->target;
}
/**
* @param string $target
*/
public function setTarget(string $target): void
{
$this->target = $target;
}
}

View File

@ -2,173 +2,114 @@
namespace App\Entity; namespace App\Entity;
use App\Controller\ConfigController;
use App\Controller\EncryptionController;
use Exception;
use OpenApi\Attributes as OAT; use OpenApi\Attributes as OAT;
use SodiumException;
/** /**
* *
*/ */
#[OAT\Schema(schema: 'nameserver')] #[OAT\Schema(schema: 'nameserver')]
class Nameserver class Nameserver
{ {
/** private int $id;
* @param string $name private String $name;
* @param int $id private String $a;
* @param string $a private String $aaaa;
* @param string $aaaa private String $apikey;
* @param string $passphrase
* @param string $apikey public function __construct(String $name, int $id = 0, String $a = '', String $aaaa = '', String $apikey = '')
* @param string $apikeyPrefix {
*/ $this->id = $id;
public function __construct( $this->name = $name;
private string $name, $this->a = $a;
private int $id = 0, $this->aaaa = $aaaa;
private string $a = '', $this->apikey = $apikey;
private string $aaaa = '', }
private readonly string $passphrase = '',
private string $apikey = '',
private string $apikeyPrefix = '', /**
private string $self = 'no' * @return String
) */
{ #[OAT\Property(type: 'string')]
if ($this->passphrase) { public function getA(): string
$configController = new ConfigController(quiet: false); {
$encryptionController = new EncryptionController(); return $this->a;
}
$encryptionKey = $configController->getConfig(configKey: 'encryptionKey');
/**
[$this->apikeyPrefix] = explode(separator: '.', string: $this->passphrase); * @param String $a
*/
try { public function setA(string $a): void
$this->apikey = $encryptionController->safeEncrypt(message: $this->passphrase, key: $encryptionKey); {
} catch (Exception|SodiumException $e) { $this->a = $a;
exit($e->getMessage() . PHP_EOL); }
}
} /**
* @return String
} */
#[OAT\Property(type: 'string')]
public function getSelf(): string public function getAaaa(): string
{ {
return $this->self; return $this->aaaa;
} }
public function setSelf(string $self): void /**
{ * @param String $aaaa
$this->self = $self; */
} public function setAaaa(string $aaaa): void
{
/** $this->aaaa = $aaaa;
* @return string }
*/
public function getApikeyPrefix(): string /**
{ * @return String
return $this->apikeyPrefix; */
} #[OAT\Property(type: 'string')]
public function getApikey(): string
/** {
* @param string $apikeyPrefix return $this->apikey;
*/ }
public function setApikeyPrefix(string $apikeyPrefix): void
{ /**
$this->apikeyPrefix = $apikeyPrefix; * @param String $apikey
} */
public function setApikey(string $apikey): void
{
/** $this->apikey = $apikey;
* @return string }
*/
#[OAT\Property(type: 'string')] /**
public function getA(): string * @return int
{ */
return $this->a; #[OAT\Property(type: 'int')]
} public function getId(): int
{
/** return $this->id;
* @param string $a }
*/
public function setA(string $a): void /**
{ * @param int $id
$this->a = $a; */
} public function setId(int $id): void
{
/** $this->id = $id;
* @return string }
*/
#[OAT\Property(type: 'string')] /**
public function getAaaa(): string * @return String
{ */
return $this->aaaa; #[OAT\Property(type: 'string')]
} public function getName(): string
{
/** return $this->name;
* @param string $aaaa }
*/
public function setAaaa(string $aaaa): void /**
{ * @param String $name
$this->aaaa = $aaaa; */
} public function setName(string $name): void
{
/** $this->name = $name;
* @return string }
*/
#[OAT\Property(type: 'string')]
public function getApikey(): string
{
return $this->apikey;
}
/**
* @param string $apikey
*/
public function setApikey(string $apikey): void
{
$this->apikey = $apikey;
}
/**
* @return int
*/
#[OAT\Property(type: 'int')]
public function getId(): int
{
return $this->id;
}
/**
* @param int $id
*/
public function setId(int $id): void
{
$this->id = $id;
}
/**
* @return string
*/
#[OAT\Property(type: 'string')]
public function getName(): string
{
return $this->name;
}
/**
* @param string $name
*/
public function setName(string $name): void
{
$this->name = $name;
}
/**
* @return string
*/
public function getPassphrase(): string
{
return $this->passphrase;
}
} }

View File

@ -2,150 +2,107 @@
namespace App\Entity; namespace App\Entity;
use App\Controller\ConfigController;
use App\Controller\EncryptionController;
use Exception;
use SodiumException;
/** /**
* *
*/ */
class Panel class Panel
{ {
public function __construct( private int $id;
private string $name, private String $name;
private int $id = 0, private String $a;
private string $a = '', private String $aaaa;
private string $aaaa = '', private String $apikey;
private readonly string $passphrase = '',
private string $apikey = '', public function __construct(String $name, int $id = 0, String $a = '', String $aaaa = '', String $apikey = '')
private string $apikeyPrefix = '', {
private string $self = 'no', $this->id = $id;
) $this->name = $name;
{ $this->a = $a;
if ($this->passphrase) { $this->aaaa = $aaaa;
$configController = new ConfigController(quiet: false); $this->apikey = $apikey;
$encryptionController = new EncryptionController(); }
$encryptionKey = $configController->getConfig(configKey: 'encryptionKey');
/**
$this->apikeyPrefix = strtok(string: $this->passphrase, token: '.'); * @return String
*/
try { public function getA(): string
$this->apikey = $encryptionController->safeEncrypt(message: $this->passphrase, key: $encryptionKey); {
} catch (Exception|SodiumException $e) { return $this->a;
exit($e->getMessage() . PHP_EOL); }
}
} /**
} * @return String
*/
/** public function getAaaa(): string
* @return string {
*/ return $this->aaaa;
public function getPassphrase(): string }
{
return $this->passphrase; /**
} * @return String
*/
public function getApikey(): string
/** {
* @return string return $this->apikey;
*/ }
public function getName(): string
{ /**
return $this->name; * @return int
} */
public function getId(): int
/** {
* @param string $name return $this->id;
*/ }
public function setName(string $name): void
{ /**
$this->name = $name; * @param int $id
} */
public function setId(int $id): void
/** {
* @return int $this->id = $id;
*/ }
public function getId(): int
{ /**
return $this->id; * @return String
} */
public function getName(): string
/** {
* @param int $id return $this->name;
*/ }
public function setId(int $id): void
{
$this->id = $id; /**
} * @param String $apikey
*/
/** public function setApikey(string $apikey): void
* @return string {
*/ $this->apikey = $apikey;
public function getA(): string }
{
return $this->a;
} /**
* @param String $name
*/
/** public function setName(string $name): void
* @return string {
*/ $this->name = $name;
public function getSelf(): string }
{
return $this->self; /**
} * @param String $a
*/
/** public function setA(string $a): void
* @param string $self {
*/ $this->a = $a;
public function setSelf(string $self): void }
{
$this->self = $self; /**
} * @param String $aaaa
*/
public function setAaaa(string $aaaa): void
/** {
* @return string $this->aaaa = $aaaa;
*/ }
public function getAaaa(): string
{ }
return $this->aaaa;
}
/**
* @return string
*/
public function getApikey(): string
{
return $this->apikey;
}
/**
* @param string $a
*/
public function setA(string $a): void
{
$this->a = $a;
}
/**
* @param string $aaaa
*/
public function setAaaa(string $aaaa): void
{
$this->aaaa = $aaaa;
}
/**
* @return string
*/
public function getApikeyPrefix(): string
{
return $this->apikeyPrefix;
}
}

1
src/Helpers.php Normal file
View File

@ -0,0 +1 @@
<?php

View File

@ -1,105 +0,0 @@
<?php
namespace App\Provider;
//error_reporting(error_level: E_ALL);
use App\Utilities\Colors;
use PDO;
use PDOException;
use PHPUnit\Exception;
use App\Controller\ConfigController;
/**
*
*/
class DatabaseConnection
{
private PDO $dbConnection;
const TABLE_PREFIX = '';
const TABLE_DOMAINS = self::TABLE_PREFIX . "domains";
const TABLE_NAMESERVERS = self::TABLE_PREFIX . "nameservers";
const TABLE_PANELS = self::TABLE_PREFIX . "panels";
const TABLE_APIKEYS = self::TABLE_PREFIX . "apikeys";
const TABLE_DYNDNS = self::TABLE_PREFIX . "dyndns";
const TABLE_SETTINGS = self::TABLE_PREFIX . 'config';
public function __construct(private readonly ConfigController $configController)
{
$errors = [];
if (!$dbHost = $this->configController->getConfig(configKey: 'dbHost')) {
$errors[] = Colors::RED . 'Error: ' . Colors::DEFAULT . 'Missing config: dbHost' . PHP_EOL;
}
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 {
$this->dbConnection = new PDO(
dsn: "mysql:host=$dbHost;port=$dbPort;charset=utf8mb4;dbname=$dbDatabase",
username: $dbUser,
password: $dbPassword
);
} catch (Exception $e) {
echo $e->getMessage() . PHP_EOL;
echo 'Did you create the database and adjust the config file?' . PHP_EOL;
exit(1);
}
if (!$this->configController->getConfig(configKey: 'test')) {
try {
$sql = "SHOW TABLES";
$statement = $this->dbConnection->prepare(query: $sql);
$statement->execute();
$result = $statement->fetch();
if (empty($result)) {
// ALTER TABLE `domains` ADD `panel_id` INT NULL AFTER `id`;
echo Colors::RED . 'Error: ' . Colors::DEFAULT . 'Cannot find tables.' . PHP_EOL;
echo 'Run the migration: ' . Colors::YELLOW . './bin/console migrations:migrate' . Colors::DEFAULT . PHP_EOL;
}
} catch (PDOException $exception) {
echo $exception->getMessage() . PHP_EOL;
echo 'Did you create the database and adjust the config file?' . PHP_EOL;
echo PHP_EOL . 'You can create database an user via a panel or manually in mysql shell:' . PHP_EOL;
$password = $this->generatePassword();
echo 'Created an initial password: ' . $password . PHP_EOL;
echo 'CREATE DATABASE bindAPI;' . PHP_EOL;
echo "CREATE USER 'bindAPI'@'localhost' IDENTIFIED BY '$password';" . PHP_EOL;
echo "GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, INDEX, DROP, ALTER, CREATE TEMPORARY TABLES, LOCK TABLES ON bindAPI.* TO 'bindAPI'@'localhost';" . PHP_EOL;
echo 'There is no need to run FLUSH PRIVILEGES when using GRANT!' . PHP_EOL;
exit(1);
}
}
}
function generatePassword(int $length = 8): string
{
$chars = '23456789bcdfhkmnprstvzBCDFHJKLMNPRSTVZ';
$shuffled = str_shuffle(string: $chars);
return mb_substr(string: $shuffled, start: 0, length: $length);
}
public function getConnection(): PDO
{
return $this->dbConnection;
}
}

View File

@ -3,9 +3,10 @@ namespace App\Repository;
error_reporting(error_level: E_ALL); error_reporting(error_level: E_ALL);
use App\Provider\DatabaseConnection; use App\Controller\DatabaseConnection;
use App\Controller\EncryptionController; use App\Controller\PanelController;
use App\Entity\Apikey; use App\Entity\Apikey;
use Exception;
use PDO; use PDO;
use PDOException; use PDOException;
@ -14,28 +15,30 @@ use PDOException;
*/ */
class ApikeyRepository class ApikeyRepository
{ {
public function __construct(private readonly DatabaseConnection $databaseConnection, EncryptionController $encryptionController) public function __construct(private DatabaseConnection $databaseConnection, PanelController $panelController)
{} {}
/**
* @return array|false
*/
public function findAll(): bool|array public function findAll(): bool|array
{ {
$sql = " $sql = "
SELECT id, name, apikey_prefix, apikey, created_at SELECT id, name, api_token_prefix, api_token
FROM " . DatabaseConnection::TABLE_APIKEYS; FROM " . DatabaseConnection::TABLE_APIKEYS;
try { try {
$statement = $this->databaseConnection->getConnection()->prepare(query: $sql); $statement = $this->databaseConnection->getConnection()->prepare(query: $sql);
$statement->execute(); $statement->execute();
$apiKeys = []; $apikeys = [];
while ($result = $statement->fetch()) { while ($result = $statement->fetch()) {
$apikey = new Apikey(id: $result['id'], name: $result['name'], apikey: $result['apikey'], apikeyPrefix: $result['apikey_prefix'], createdAt: $result['created_at']); $apikey = new Apikey(name: $result['name'], apiTokenPrefix: $result['api_token_prefix'], apiToken: $result['api_token'], id: $result['id']);
$apiKeys[] = $apikey; $apikeys[] = $apikey;
} }
return $apiKeys; return $apikeys;
} catch (PDOException $e) { } catch (PDOException $e) {
exit($e->getMessage()); exit($e->getMessage());
} }
@ -45,12 +48,12 @@ class ApikeyRepository
/** /**
* @param Int $id * @param Int $id
* *
* @return Apikey|bool * @return \App\Entity\Apikey|bool
*/ */
public function findByID(Int $id): Apikey|bool public function findByID(Int $id): Apikey|bool
{ {
$sql = " $sql = "
SELECT id, name, apikey_prefix, apikey SELECT id, name, api_token_prefix, api_token
FROM " . DatabaseConnection::TABLE_APIKEYS . " FROM " . DatabaseConnection::TABLE_APIKEYS . "
WHERE id = :id; WHERE id = :id;
"; ";
@ -60,7 +63,7 @@ class ApikeyRepository
$statement->bindParam(param: ':id', var: $id); $statement->bindParam(param: ':id', var: $id);
$statement->execute(); $statement->execute();
if ($result = $statement->fetch(mode: PDO::FETCH_ASSOC)) { if ($result = $statement->fetch(mode: PDO::FETCH_ASSOC)) {
return new Apikey(id: $result['id'], name: $result['name'], apikey: $result['apikey'], apikeyPrefix: $result['apikey_prefix']); return new Apikey(name: $result['name'], apiTokenPrefix: $result['api_token_prefix'], apiToken: $result['api_token'], id: $result['id']);
} else { } else {
return false; return false;
} }
@ -73,21 +76,21 @@ class ApikeyRepository
/** /**
* @param String $prefix * @param String $prefix
* *
* @return Apikey|bool * @return \App\Entity\Apikey|bool
*/ */
public function findByPrefix(String $prefix): Apikey|bool public function findByPrefix(String $prefix): Apikey|bool
{ {
$sql = " $sql = "
SELECT id, name, apikey_prefix, apikey SELECT id, name, api_token_prefix, api_token
FROM " . DatabaseConnection::TABLE_APIKEYS . " FROM " . DatabaseConnection::TABLE_APIKEYS . "
WHERE apikey_prefix = :prefix"; WHERE api_token_prefix = :prefix";
try { try {
$statement = $this->databaseConnection->getConnection()->prepare(query: $sql); $statement = $this->databaseConnection->getConnection()->prepare(query: $sql);
$statement->bindParam(param: ':prefix', var: $prefix); $statement->bindParam(param: ':prefix', var: $prefix);
$statement->execute(); $statement->execute();
if ($result = $statement->fetch(mode: PDO::FETCH_ASSOC)) { if ($result = $statement->fetch(mode: PDO::FETCH_ASSOC)) {
return new Apikey(id: $result['id'], name: $result['name'], apikey: $result['apikey'], apikeyPrefix: $result['apikey_prefix']); return new Apikey(name: $result['name'], apiTokenPrefix: $result['api_token_prefix'], apiToken: $result['api_token'], id: $result['id']);
} else { } else {
return false; return false;
} }
@ -95,51 +98,56 @@ class ApikeyRepository
exit($e->getMessage()); exit($e->getMessage());
} }
} }
/** /**
* @param Apikey $apikey * @return array|void
* @return int */
*/ public function create(String $name = '')
public function insert(ApiKey $apikey): int {
{ $tokenPrefix = uniqid();
$result['tokenPrefix'] = $tokenPrefix;
$name = $apikey->getName(); try {
$apikeyPrefix = $apikey->getApikeyPrefix(); $key = bin2hex(string: random_bytes(length: 24));
$apikeyValue = $apikey->getApikey(); $result['key'] = $key;
} catch (Exception $e) {
echo $e->getMessage() . PHP_EOL;
exit(1);
}
$token = password_hash(password: $tokenPrefix . '.' . $key, algo: PASSWORD_ARGON2ID);
$sql = " $sql = "
INSERT INTO " . DatabaseConnection::TABLE_APIKEYS . " (name, apikey_prefix, apikey) INSERT INTO " . DatabaseConnection::TABLE_APIKEYS . " (name, api_token_prefix, api_token)
VALUES (:name, :apikey_prefix, :apikey)"; VALUES (:name, :token_prefix, :token)";
try { try {
$statement = $this->databaseConnection->getConnection()->prepare(query: $sql); $statement = $this->databaseConnection->getConnection()->prepare(query: $sql);
$statement->bindParam(param: ':name', var: $name); $statement->bindParam(param: ':token_prefix', var: $tokenPrefix);
$statement->bindParam(param: ':apikey_prefix', var: $apikeyPrefix); $statement->bindParam(param: ':token', var: $token);
$statement->bindParam(param: ':apikey', var: $apikeyValue); $statement->bindParam(param: ':name', var: $name);
$statement->execute(); $statement->execute();
return intval(value: $this->databaseConnection->getConnection()->lastInsertId()); $result['row'] = $this->databaseConnection->getConnection()->lastInsertId();
return $result;
} catch (PDOException $e) { } catch (PDOException $e) {
exit($e->getMessage()); exit($e->getMessage());
} }
} }
/** /**
* @param Apikey $apikey * @param Int $id
* @return false|int * @param String $name
*/ *
public function update(Apikey $apikey): bool|int * @return false|int
*/
public function update(int $id, string $name): bool|int
{ {
$id = $apikey->getId(); $current = $this->findByID(id: $id);
$name = $apikey->getName();
if (empty($name)) {
$current = $this->findByID(id: $id); $name = $current['name'];
}
if (empty($name)) {
$name = $current->getName();
}
$sql = " $sql = "
UPDATE " . DatabaseConnection::TABLE_APIKEYS . " SET UPDATE " . DatabaseConnection::TABLE_APIKEYS . " SET
name = :name name = :name
@ -153,7 +161,7 @@ class ApikeyRepository
return $statement->rowCount(); return $statement->rowCount();
} catch (PDOException $e) { } catch (PDOException $e) {
echo $e->getMessage(); print($e->getMessage());
return false; return false;
} }
} }
@ -180,4 +188,4 @@ class ApikeyRepository
} }
} }
} }

View File

@ -2,8 +2,7 @@
namespace App\Repository; namespace App\Repository;
use App\Controller\ConfigController; use App\Controller\DatabaseConnection;
use App\Provider\DatabaseConnection;
use App\Entity\Domain; use App\Entity\Domain;
use Monolog\Logger; use Monolog\Logger;
use PDO; use PDO;
@ -12,14 +11,13 @@ use PDOException;
/** /**
* *
*/ */
readonly class DomainRepository class DomainRepository
{ {
public function __construct( public function __construct(private DatabaseConnection $databaseConnection, private array $config, private Logger $log)
private DatabaseConnection $databaseConnection,
private ConfigController $configController,
private Logger $logger)
{ {
$this->logger->debug(message: "DomainRepository::__construct()"); if ($this->config['debug']) {
$this->log->debug(message: "DomainRepository::__construct()");
}
} }
@ -29,7 +27,9 @@ readonly class DomainRepository
*/ */
public function findAll(): array public function findAll(): array
{ {
$this->logger->debug(message: "findAll()"); if ($this->config['debug']) {
$this->log->debug(message: "findAll()");
}
$domains = []; $domains = [];
$sql = " $sql = "
@ -41,6 +41,8 @@ readonly class DomainRepository
$statement = $this->databaseConnection->getConnection()->prepare(query: $sql); $statement = $this->databaseConnection->getConnection()->prepare(query: $sql);
$statement->execute(); $statement->execute();
while ($result = $statement->fetch(mode: PDO::FETCH_ASSOC)) { while ($result = $statement->fetch(mode: PDO::FETCH_ASSOC)) {
//print_r($result);
//die();
$domain = new Domain(name: $result['name'], panel: $result['panel'], id: $result['id']); $domain = new Domain(name: $result['name'], panel: $result['panel'], id: $result['id']);
$domains[] = $domain; $domains[] = $domain;
} }
@ -49,34 +51,18 @@ readonly class DomainRepository
exit($e->getMessage()); exit($e->getMessage());
} }
} }
public function findByPanel(string $name): array
{ /**
$this->logger->debug(message: "findByPanel($name)"); * @param int $id
*
$domains = []; * @return bool|\App\Entity\Domain
$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());
}
}
public function findByID(int $id): bool|Domain public function findByID(int $id): bool|Domain
{ {
$this->logger->debug(message: "findById($id)"); if ($this->config['debug']) {
$this->log->debug(message: "findById($id)");
}
$sql = " $sql = "
SELECT id, name, panel SELECT id, name, panel
@ -99,11 +85,16 @@ readonly 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)"); if ($this->config['debug']) {
$this->log->debug(message: "findByName($name)");
}
$sql = " $sql = "
SELECT id, name, panel SELECT id, name, panel
FROM " . DatabaseConnection::TABLE_DOMAINS . " FROM " . DatabaseConnection::TABLE_DOMAINS . "
@ -123,33 +114,18 @@ readonly class DomainRepository
} }
} }
public function findByHost(string $host): Domain|bool
{
$this->logger->debug(message: "findByHost($host)");
$host = strtolower(string: trim(string: $host));
$count = substr_count(haystack: $host, needle: '.');
if ($count == 2) {
if (strlen(string: explode(separator: '.', string: $host)[1]) > 3) {
$host = explode(separator: '.', string: $host, limit: 2)[1];
}
} elseif ($count > 2) {
$host = $this->findByHost(host: explode(separator: '.', string: $host, limit: 2)[1]);
}
if ($domain = $this->findByName(name: $host)) {
return $domain;
} else {
return false;
}
}
/**
* @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(); if ($this->config['debug']) {
$this->logger->info(message: "insert($domainName)"); $domainName = $domain->getName();
$this->log->debug(message: "insert($domainName)");
}
$sql = " $sql = "
INSERT INTO " . DatabaseConnection::TABLE_DOMAINS . " (name, panel) INSERT INTO " . DatabaseConnection::TABLE_DOMAINS . " (name, panel)
@ -177,8 +153,10 @@ readonly class DomainRepository
*/ */
public function update(Domain $domain): bool|int public function update(Domain $domain): bool|int
{ {
$domainName = $domain->getName(); if ($this->config['debug']) {
$this->logger->debug(message: "update($domainName)"); $domainName = $domain->getName();
$this->log->debug(message: "update($domainName)");
}
$id = $domain->getId(); $id = $domain->getId();
$current = $this->findByID(id: $id); $current = $this->findByID(id: $id);
@ -209,17 +187,24 @@ readonly class DomainRepository
return $statement->rowCount(); return $statement->rowCount();
} catch (PDOException $e) { } catch (PDOException $e) {
echo $e->getMessage(); print($e->getMessage());
return false; return false;
} }
} }
public function delete(Domain $domain): int
/**
* @param \App\Entity\Domain $domain
*
* @return int
*/
public function delete(Domain $domain): int
{ {
$domainName = $domain->getName(); if ($this->config['debug']) {
$this->logger->debug(message: "delete($domainName)"); $domainName = $domain->getName();
$this->log->debug(message: "delete($domainName)");
// FIXME, add force parameter, reject deletion if domains left on panel }
$sql = " $sql = "
DELETE FROM " . DatabaseConnection::TABLE_DOMAINS . " DELETE FROM " . DatabaseConnection::TABLE_DOMAINS . "
WHERE id = :id"; WHERE id = :id";
@ -235,9 +220,14 @@ readonly class DomainRepository
exit($e->getMessage()); exit($e->getMessage());
} }
} }
// FIXME check for master/slave in config generation
public function getLongestEntry(string $field): int /**
* @param String $field
*
* @return int
*/
public function getLongestEntry(String $field): int
{ {
$sql = " $sql = "
SELECT MAX(LENGTH(" . $field . ")) as length FROM " . DatabaseConnection::TABLE_DOMAINS; SELECT MAX(LENGTH(" . $field . ")) as length FROM " . DatabaseConnection::TABLE_DOMAINS;
@ -245,11 +235,10 @@ readonly class DomainRepository
try { try {
$statement = $this->databaseConnection->getConnection()->prepare(query: $sql); $statement = $this->databaseConnection->getConnection()->prepare(query: $sql);
$statement->execute(); $statement->execute();
$result = $statement->fetch(); $result = $statement->fetch();
// if there are not yet any domains, just return 30 return $result['length'];
return $result['length'] ?? 30;
} catch (PDOException $e) { } catch (PDOException $e) {
exit($e->getMessage()); exit($e->getMessage());
} }
} }
} }

View File

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

View File

@ -2,275 +2,228 @@
namespace App\Repository; namespace App\Repository;
use App\Provider\DatabaseConnection; use App\Controller\DatabaseConnection;
use App\Entity\Nameserver; use App\Entity\Nameserver;
use PDO; use PDO;
use PDOException; use PDOException;
use SodiumException;
/** /**
* *
*/ */
class NameserverRepository class NameserverRepository
{ {
public function __construct(private readonly DatabaseConnection $databaseConnection) public function __construct(private DatabaseConnection $databaseConnection)
{ {
// no body }
}
/**
/** * @return array
* @return array|null */
*/ public function findAll(): array
public function findAll(): ?array {
{ $nameservers = [];
$nameservers = []; $sql = "
$sql = " SELECT id, name, a, aaaa, apikey
SELECT id, name, a, aaaa, apikey, apikey_prefix, self
FROM " . DatabaseConnection::TABLE_NAMESERVERS . " FROM " . DatabaseConnection::TABLE_NAMESERVERS . "
ORDER BY name"; ORDER BY name";
try { try {
$statement = $this->databaseConnection->getConnection()->prepare(query: $sql); $statement = $this->databaseConnection->getConnection()->prepare(query: $sql);
$statement->execute(); $statement->execute();
while ($result = $statement->fetch(mode: PDO::FETCH_ASSOC)) { while ($result = $statement->fetch(mode: PDO::FETCH_ASSOC)) {
$nameserver = new Nameserver(name: $result['name'], id: $result['id'], a: $result['a'], aaaa: $result['aaaa'], apikey: $result['apikey'], apikeyPrefix: $result['apikey_prefix'], self: $result['self']); $nameserver = new Nameserver(name: $result['name'], id: $result['id'], a: $result['a'], aaaa: $result['aaaa'], apikey: $result['apikey']);
$nameservers[] = $nameserver; $nameservers[] = $nameserver;
} }
return $nameservers; return $nameservers;
} catch (PDOException $e) { } catch (PDOException $e) {
exit($e->getMessage()); exit($e->getMessage());
} }
} }
/** /**
* @return Nameserver|null * @param int $id
*/ *
public function findFirst(): ?Nameserver * @return \App\Entity\Nameserver
{ */
$sql = " public function findByID(int $id): Nameserver
SELECT id, name, a, aaaa, apikey, apikey_prefix, self {
FROM " . DatabaseConnection::TABLE_NAMESERVERS . " $sql = "
ORDER BY name"; SELECT id, name, a, aaaa, apikey
try {
$statement = $this->databaseConnection->getConnection()->prepare(query: $sql);
$statement->execute();
$result = $statement->fetch(mode: PDO::FETCH_ASSOC);
return new Nameserver(name: $result['name'], id: $result['id'], a: $result['a'], aaaa: $result['aaaa'], apikey: $result['apikey'], apikeyPrefix: $result['apikey_prefix'], self: $result['self']);
} catch (PDOException $e) {
exit($e->getMessage());
}
}
/**
* @param int $id
*
* @return null|Nameserver
*/
public function findByID(int $id): ?Nameserver
{
$sql = "
SELECT id, name, a, aaaa, apikey, apikey_prefix, self
FROM . " . DatabaseConnection::TABLE_NAMESERVERS . " FROM . " . DatabaseConnection::TABLE_NAMESERVERS . "
WHERE id = :id"; WHERE id = :id";
try { try {
$statement = $this->databaseConnection->getConnection()->prepare(query: $sql); $statement = $this->databaseConnection->getConnection()->prepare(query: $sql);
$statement->bindParam(param: ':id', var: $id); $statement->bindParam(param: ':id', var: $id);
$statement->execute(); $statement->execute();
if ($result = $statement->fetch(mode: PDO::FETCH_ASSOC)) { $result = $statement->fetch(mode: PDO::FETCH_ASSOC);
return new Nameserver(name: $result['name'], a: $result['a'], aaaa: $result['aaaa'], apikey: $result['apikey'], apikeyPrefix: $result['apikey_prefix'], self: $result['self']); return new Nameserver(name: $result['name'], a: $result['a'], aaaa: $result['aaaa'], apikey: $result['apikey']);
} else { } catch (PDOException $e) {
return null; exit($e->getMessage());
} }
} catch (PDOException $e) { }
exit($e->getMessage());
}
} /**
* @param String $name
*
/** * @return \App\Entity\Nameserver|bool
* @param String $name */
* public function findByName(string $name): Nameserver|bool
* @return Nameserver|null {
*/ $sql = "
public function findByName(string $name): ?Nameserver SELECT id, name, a, aaaa, apikey
{
$sql = "
SELECT id, name, a, aaaa, apikey, apikey_prefix, self
FROM " . DatabaseConnection::TABLE_NAMESERVERS . " FROM " . DatabaseConnection::TABLE_NAMESERVERS . "
WHERE name = :name"; WHERE name = :name";
try { try {
$statement = $this->databaseConnection->getConnection()->prepare(query: $sql); $statement = $this->databaseConnection->getConnection()->prepare(query: $sql);
$statement->bindParam(param: ':name', var: $name); $statement->bindParam(param: ':name', var: $name);
$statement->execute(); $statement->execute();
if ($result = $statement->fetch(mode: PDO::FETCH_ASSOC)) { if ($result = $statement->fetch(mode: PDO::FETCH_ASSOC)) {
return new Nameserver(name: $result['name'], a: $result['a'], aaaa: $result['aaaa'], apikey: $result['apikey'], apikeyPrefix: $result['apikey_prefix'], self: $result['self']); return new Nameserver(name: $result['name'], a: $result['a'], aaaa: $result['aaaa']);
} else { } else {
return null; return false;
} }
} catch (PDOException $e) { } catch (PDOException $e) {
exit($e->getMessage()); exit($e->getMessage());
} }
} }
/** /**
* @param Nameserver $nameserver * @param \App\Entity\Nameserver $nameserver
* *
* @return int|null * @return string|false
*/ */
public function insert(Nameserver $nameserver): ?int public function insert(Nameserver $nameserver): bool|string
{ {
$name = $nameserver->getName(); $sql = "
$a = $nameserver->getA(); INSERT INTO " . DatabaseConnection::TABLE_NAMESERVERS . " (name, a, aaaa, apikey)
$aaaa = $nameserver->getAaaa(); VALUES (:name, :a, :aaaa, :apikey)";
$apikey = $nameserver->getApikey();
$apikeyPrefix = $nameserver->getApikeyPrefix(); try {
$self = $nameserver->getSelf(); $name = $nameserver->getName();
if ($self === '') { $a = $nameserver->getA();
$selfValue = 'no'; $aaaa = $nameserver->getAaaa();
} else { $apikey = $nameserver->getApikey();
$selfValue = $self; $statement = $this->databaseConnection->getConnection()->prepare(query: $sql);
} $statement->bindParam(param: ':name', var: $name);
$statement->bindParam(param: ':a', var: $a);
$statement->bindParam(param: ':aaaa', var: $aaaa);
$sql = " $statement->bindParam(param: ':apikey', var: $apikey);
INSERT INTO " . DatabaseConnection::TABLE_NAMESERVERS . " (name, a, aaaa, apikey, apikey_prefix, self) $statement->execute();
VALUES (:name, :a, :aaaa, :apikey, :apikey_prefix, :self)";
return $this->databaseConnection->getConnection()->lastInsertId();
try { } catch (PDOException $e) {
$statement = $this->databaseConnection->getConnection()->prepare(query: $sql); exit($e->getMessage());
$statement->bindParam(param: ':name', var: $name); }
$statement->bindParam(param: ':a', var: $a); }
$statement->bindParam(param: ':aaaa', var: $aaaa);
$statement->bindParam(param: ':apikey', var: $apikey);
$statement->bindParam(param: ':apikey_prefix', var: $apikeyPrefix); /**
$statement->bindParam(param: ':self', var: $selfValue); * @param Int $id
$statement->execute(); * @param String $name
* @param String $a
return intval(value: $this->databaseConnection->getConnection()->lastInsertId()); * @param String $aaaa
} catch (PDOException $e) { * @param String $apikey
exit($e->getMessage() . PHP_EOL); *
} * @return false|int
} */
public function update(int $id, string $name, string $a, string $aaaa, string $apikey): bool|int
{
/** $current = $this->findByID(id: $id);
* @param Nameserver $nameserver
* @return false|int /* doesn't work
*/ $statement = "
public function update(Nameserver $nameserver): bool|int INSERT INTO domains(id, name, a, aaaa)
{ VALUES(:id, :name, :a, :aaaa)
$id = $nameserver->getId(); ON DUPLICATE KEY UPDATE
$name = $nameserver->getName(); name=COALESCE(VALUES(name), :name),
$a = $nameserver->getA(); a=COALESCE(:a, a),
$aaaa = $nameserver->getAaaa(); aaaa=COALESCE(:aaaa, aaaa)";
$apikey = $nameserver->getApikey(); */
$apikeyPrefix = $nameserver->getApikeyPrefix();
$passphrase = $nameserver->getPassphrase(); if (empty($name)) {
$self =$nameserver->getSelf(); $name = $current->getName();
}
$current = $this->findByID(id: $id); if (empty($a)) {
$a = $current->getA();
}
if (empty($name)) { if (empty($aaaa)) {
$name = $current->getName(); $aaaa = $current->getAaaa();
} }
if (empty($a)) { if (empty($apikey)) {
$a = $current->getA(); $apikey = $current->getApikey();
} }
if (empty($aaaa)) {
$aaaa = $current->getAaaa(); $sql = "
}
if (empty($passphrase)) {
$apikey = $current->getApikey();
$apikeyPrefix = $current->getApikeyPrefix();
}
if (empty($self)) {
$self = $current->getSelf();
}
$sql = "
UPDATE " . DatabaseConnection::TABLE_NAMESERVERS . " SET UPDATE " . DatabaseConnection::TABLE_NAMESERVERS . " SET
name = :name, name = :name,
a = :a, a = :a,
aaaa = :aaaa, aaaa = :aaaa,
apikey = :apikey, apikey = :apikey
apikey_prefix = :apikey_prefix,
self = :self
WHERE id = :id"; WHERE id = :id";
try { try {
$statement = $this->databaseConnection->getConnection()->prepare(query: $sql); $statement = $this->databaseConnection->getConnection()->prepare(query: $sql);
$statement->bindParam(param: 'id', var: $id); $statement->bindParam(param: 'id', var: $id);
$statement->bindParam(param: 'name', var: $name); $statement->bindParam(param: 'name', var: $name);
$statement->bindParam(param: 'a', var: $a); $statement->bindParam(param: 'a', var: $a);
$statement->bindParam(param: 'aaaa', var: $aaaa); $statement->bindParam(param: 'aaaa', var: $aaaa);
$statement->bindParam(param: 'apikey', var: $apikey); $statement->bindParam(param: 'apikey', var: $apikey);
$statement->bindParam(param: 'apikey_prefix', var: $apikeyPrefix); $statement->execute();
$statement->bindParam(param: 'self', var: $self);
$statement->execute(); return $statement->rowCount();
try { } catch (PDOException $e) {
sodium_memzero(string: $apikey); print($e->getMessage());
} catch(SodiumException $e) { return false;
exit($e->getMessage() . PHP_EOL); }
} }
return intval(value: $statement->rowCount());
} catch (PDOException $e) {
echo $e->getMessage(); /**
return false; * @param $id
} *
} * @return int
*/
public function delete($id): int
/** {
* @param $id $sql = "
*
* @return int|null
*/
public function delete($id): ?int
{
$sql = "
DELETE FROM " . DatabaseConnection::TABLE_NAMESERVERS . " DELETE FROM " . DatabaseConnection::TABLE_NAMESERVERS . "
WHERE id = :id"; WHERE id = :id";
try { try {
$statement = $this->databaseConnection->getConnection()->prepare(query: $sql); $statement = $this->databaseConnection->getConnection()->prepare(query: $sql);
$statement->bindParam(param: 'id', var: $id); $statement->bindParam(param: 'id', var: $id);
$statement->execute(); $statement->execute();
return $statement->rowCount(); return $statement->rowCount();
} catch (PDOException $e) { } catch (PDOException $e) {
exit($e->getMessage()); exit($e->getMessage());
} }
} }
/** /**
* @param String $field * @param String $field
* *
* @return int * @return int
*/ */
public function getLongestEntry(string $field): int public function getLongestEntry(string $field): int
{ {
$sql = " $sql = "
SELECT MAX(LENGTH(" . $field . ")) as length FROM " . DatabaseConnection::TABLE_NAMESERVERS; SELECT MAX(LENGTH(" . $field . ")) as length FROM " . DatabaseConnection::TABLE_NAMESERVERS;
try { try {
$statement = $this->databaseConnection->getConnection()->prepare(query: $sql); $statement = $this->databaseConnection->getConnection()->prepare(query: $sql);
$statement->execute(); $statement->execute();
$result = $statement->fetch(); $result = $statement->fetch();
return $result['length']; return $result['length'];
} catch (PDOException $e) { } catch (PDOException $e) {
exit($e->getMessage()); exit($e->getMessage());
} }
} }
} }

View File

@ -2,7 +2,7 @@
namespace App\Repository; namespace App\Repository;
use App\Provider\DatabaseConnection; use App\Controller\DatabaseConnection;
use App\Entity\Panel; use App\Entity\Panel;
use PDO; use PDO;
use PDOException; use PDOException;
@ -12,262 +12,206 @@ use PDOException;
*/ */
class PanelRepository class PanelRepository
{ {
public function __construct(private readonly DatabaseConnection $databaseConnection) public function __construct(private DatabaseConnection $databaseConnection)
{ {}
// no body
}
/**
/** * @return array
* @return array|null */
*/ public function findAll(): array
public function findSelf(): ?array {
{ $panels = [];
$sql = " $sql = "
SELECT id, name, a, aaaa, apikey, apikey_prefix, self SELECT id, name, a, aaaa, apikey
FROM " . DatabaseConnection::TABLE_PANELS . "
WHERE self = 1";
$panels = [];
$statement = $this->databaseConnection->getConnection()->prepare(query: $sql);
$statement->execute();
while ($result = $statement->fetch(mode: PDO::FETCH_ASSOC)) {
$panel = new Panel(name: $result['name'], id: $result['id'], a: $result['a'], aaaa: $result['aaaa'], apikey: $result['apikey'], apikeyPrefix: $result['apikey_prefix'], self: $result['self']);
$panels[] = $panel;
}
return $panels;
}
public function findAll(): ?array
{
$panels = [];
$sql = "
SELECT id, name, a, aaaa, apikey, apikey_prefix, self
FROM " . DatabaseConnection::TABLE_PANELS . " FROM " . DatabaseConnection::TABLE_PANELS . "
ORDER BY name"; ORDER BY name";
try { try {
$statement = $this->databaseConnection->getConnection()->prepare(query: $sql); $statement = $this->databaseConnection->getConnection()->prepare(query: $sql);
$statement->execute(); $statement->execute();
while ($result = $statement->fetch(mode: PDO::FETCH_ASSOC)) { while ($result = $statement->fetch(mode: PDO::FETCH_ASSOC)) {
$panel = new Panel(name: $result['name'], id: $result['id'], a: $result['a'], aaaa: $result['aaaa'], apikey: $result['apikey'], apikeyPrefix: $result['apikey_prefix'], self: $result['self']); $panel = new Panel(name: $result['name'], id: $result['id'], a: $result['a'], aaaa: $result['aaaa'], apikey: $result['apikey']);
$panels[] = $panel; $panels[] = $panel;
} }
return $panels; return $panels;
} catch (PDOException $e) { } catch (PDOException $e) {
exit($e->getMessage()); exit($e->getMessage());
} }
} }
/** /**
* @param int $id * @param int $id
* *
* @return null|Panel * @return \App\Entity\Panel
*/ */
public function findByID(int $id): ?Panel public function findByID(int $id): Panel
{ {
$sql = " $sql = "
SELECT id, name, a, aaaa, apikey, apikey_prefix, self SELECT id, name, a, aaaa, apikey
FROM . " . DatabaseConnection::TABLE_PANELS . " FROM . " . DatabaseConnection::TABLE_PANELS . "
WHERE id = :id"; WHERE id = :id";
try { try {
$statement = $this->databaseConnection->getConnection()->prepare(query: $sql); $statement = $this->databaseConnection->getConnection()->prepare(query: $sql);
$statement->bindParam(param: ':id', var: $id); $statement->bindParam(param: ':id', var: $id);
$statement->execute(); $statement->execute();
if ($result = $statement->fetch(mode: PDO::FETCH_ASSOC)) { $result = $statement->fetch(mode: PDO::FETCH_ASSOC);
return new Panel(name: $result['name'], a: $result['a'], aaaa: $result['aaaa'], apikey: $result['apikey'], apikeyPrefix: $result['apikey_prefix'], self: $result['self']); return new Panel(name: $result['name'], a: $result['a'], aaaa: $result['aaaa'], apikey: $result['apikey']);
} else { } catch (PDOException $e) {
return null; exit($e->getMessage());
} }
} catch (PDOException $e) { }
exit($e->getMessage());
}
} /**
* @param String $name
*
/** * @return \App\Entity\Panel|bool
* @param String $name */
* public function findByName(string $name): Panel|bool
* @return Panel|null {
*/ $sql = "
public function findByName(string $name): ?Panel SELECT id, name, a, aaaa, apikey
{
$sql = "
SELECT id, name, a, aaaa, apikey, apikey_prefix, self
FROM " . DatabaseConnection::TABLE_PANELS . " FROM " . DatabaseConnection::TABLE_PANELS . "
WHERE name = :name"; WHERE name = :name";
try { try {
$statement = $this->databaseConnection->getConnection()->prepare(query: $sql); $statement = $this->databaseConnection->getConnection()->prepare(query: $sql);
$statement->bindParam(param: ':name', var: $name); $statement->bindParam(param: ':name', var: $name);
$statement->execute(); $statement->execute();
if ($result = $statement->fetch(mode: PDO::FETCH_ASSOC)) { if ($result = $statement->fetch(mode: PDO::FETCH_ASSOC)) {
return new Panel(name: $result['name'], a: $result['a'], aaaa: $result['aaaa'], apikey: $result['apikey'], apikeyPrefix: $result['apikey_prefix'], self: $result['self']); return new Panel(name: $result['name'], a: $result['a'], aaaa: $result['aaaa']);
} else { } else {
return null; return false;
} }
} catch (PDOException $e) { } catch (PDOException $e) {
exit($e->getMessage()); exit($e->getMessage());
} }
} }
/** /**
* @param Panel $panel * @param String $name
* @return int|null * @param String $a
*/ * @param String $aaaa
public function insert(Panel $panel): ?int * @param String $apikey
{ *
$name = $panel->getName(); * @return string|false
$a = $panel->getA(); */
$aaaa = $panel->getAaaa(); public function insert(string $name, string $a, string $aaaa, String $apikey): bool|string
$apikey = $panel->getApikey(); {
$apikeyPrefix = $panel->getApikeyPrefix(); $sql = "
$self = $panel->getSelf(); INSERT INTO " . DatabaseConnection::TABLE_PANELS . " (name, a, aaaa, apikey)
VALUES (:name, :a, :aaaa, :apikey)";
$sql = "
INSERT INTO " . DatabaseConnection::TABLE_PANELS . " (name, a, aaaa, apikey, apikey_prefix, self) try {
VALUES (:name, :a, :aaaa, :apikey, :prefix, :self)"; $statement = $this->databaseConnection->getConnection()->prepare(query: $sql);
$statement->bindParam(param: ':name', var: $name);
try { $statement->bindParam(param: ':a', var: $a);
$statement = $this->databaseConnection->getConnection()->prepare(query: $sql); $statement->bindParam(param: ':aaaa', var: $aaaa);
$statement->bindParam(param: ':name', var: $name); $statement->bindParam(param: ':apikey', var: $apikey);
$statement->bindParam(param: ':a', var: $a); $statement->execute();
$statement->bindParam(param: ':aaaa', var: $aaaa);
$statement->bindParam(param: ':apikey', var: $apikey); return $this->databaseConnection->getConnection()->lastInsertId();
$statement->bindParam(param: ':prefix', var: $apikeyPrefix); } catch (PDOException $e) {
$statement->bindParam(param: ':self', var: $self); exit($e->getMessage());
$statement->execute(); }
}
return intval(value: $this->databaseConnection->getConnection()->lastInsertId());
} catch (PDOException $e) {
exit($e->getMessage()); /**
} * @param Int $id
} * @param String $name
* @param String $a
* @param String $aaaa
/** * @param String $apikey
* @param Panel $panel *
* @return int|null * @return false|int
*/ */
public function update(Panel $panel): ?int public function update(int $id, string $name, string $a, string $aaaa, String $apikey): bool|int
{ {
$id = $panel->getId(); $current = $this->findByID(id: $id);
$name = $panel->getName();
$a = $panel->getA(); if (empty($name)) {
$aaaa = $panel->getAaaa(); $name = $current->getName();
$apikey = $panel->getApikey(); }
$apikeyPrefix = $panel->getApikeyPrefix(); if (empty($a)) {
$passphrase = $panel->getPassphrase(); $a = $current->getA();
$self = $panel->getSelf(); }
echo 'self: ' . $self; if (empty($aaaa)) {
$aaaa = $current->getAaaa();
$current = $this->findByID(id: $id); }
if (empty($apikey)) {
$apikey = $current->getApikey();
if (empty($name)) { }
$name = $current->getName();
} $sql = "
if (empty($a)) {
$a = $current->getA();
}
if (empty($aaaa)) {
$aaaa = $current->getAaaa();
}
if (empty($passphrase)) {
$apikey = $current->getApikey();
$apikeyPrefix = $current->getApikeyPrefix();
}
if (empty($self)) {
$self = $current->getSelf();
}
$sql = "
UPDATE " . DatabaseConnection::TABLE_PANELS . " SET UPDATE " . DatabaseConnection::TABLE_PANELS . " SET
name = :name, name = :name,
a = :a, a = :a,
aaaa = :aaaa, aaaa = :aaaa,
apikey = :apikey, apikey = :apikey
apikey_prefix = :apikey_prefix,
self = :self
WHERE id = :id"; WHERE id = :id";
try { try {
$statement = $this->databaseConnection->getConnection()->prepare(query: $sql); $statement = $this->databaseConnection->getConnection()->prepare(query: $sql);
$statement->bindParam(param: 'id', var: $id); $statement->bindParam(param: 'id', var: $id);
$statement->bindParam(param: 'name', var: $name); $statement->bindParam(param: 'name', var: $name);
$statement->bindParam(param: 'a', var: $a); $statement->bindParam(param: 'a', var: $a);
$statement->bindParam(param: 'aaaa', var: $aaaa); $statement->bindParam(param: 'aaaa', var: $aaaa);
$statement->bindParam(param: 'apikey', var: $apikey); $statement->bindParam(param: 'apikey', var: $apikey);
$statement->bindParam(param: 'apikey_prefix', var: $apikeyPrefix); $statement->execute();
$statement->bindParam(param: 'self', var: $self);
$statement->execute(); return $statement->rowCount();
} catch (PDOException $e) {
return intval(value: $statement->rowCount()); print($e->getMessage());
} catch (PDOException $e) { return false;
echo $e->getMessage(); }
return null; }
}
}
/**
* @param $id
/** *
* @param $id * @return int
* */
* @return int|null public function delete($id): int
*/ {
public function delete($id): ?int $sql = "
{
$sql = "
DELETE FROM " . DatabaseConnection::TABLE_PANELS . " DELETE FROM " . DatabaseConnection::TABLE_PANELS . "
WHERE id = :id"; WHERE id = :id";
try { try {
$statement = $this->databaseConnection->getConnection()->prepare(query: $sql); $statement = $this->databaseConnection->getConnection()->prepare(query: $sql);
$statement->bindParam(param: 'id', var: $id); $statement->bindParam(param: 'id', var: $id);
$statement->execute(); $statement->execute();
return intval(value: $statement->rowCount()); return $statement->rowCount();
} catch (PDOException $e) { } catch (PDOException $e) {
exit($e->getMessage()); exit($e->getMessage());
} }
} }
/** /**
* @param String $field * @param String $field
* *
* @return int|null * @return int
*/ */
public function getLongestEntry(string $field): ?int public function getLongestEntry(String $field): int
{ {
$sql = " $sql = "
SELECT MAX(LENGTH(" . $field . ")) as length FROM " . DatabaseConnection::TABLE_PANELS; SELECT MAX(LENGTH(" . $field . ")) as length FROM " . DatabaseConnection::TABLE_PANELS;
try { try {
$statement = $this->databaseConnection->getConnection()->prepare(query: $sql); $statement = $this->databaseConnection->getConnection()->prepare(query: $sql);
$statement->execute(); $statement->execute();
$result = $statement->fetch(); $result = $statement->fetch();
return $result['length']; return $result['length'];
} catch (PDOException $e) { } catch (PDOException $e) {
exit($e->getMessage()); exit($e->getMessage());
} }
} }
}
public function getSelf(): ?Panel
{
$panels = $this->findAll();
foreach ($panels as $panel) {
if ($panel->getSelf() === 'yes') {
return $panel;
}
}
return null;
}
}

View File

@ -1,69 +0,0 @@
<?php declare(strict_types=1);
namespace App\Repository;
error_reporting(error_level: E_ALL);
use App\Provider\DatabaseConnection;
use App\Controller\EncryptionController;
use PDO;
use PDOException;
/**
*
*/
readonly class SettingsRepository
{
public function __construct(private DatabaseConnection $databaseConnection, EncryptionController $encryptionController)
{}
public function findByName(string $name): string|bool
{
$sql = "
SELECT value
FROM " . DatabaseConnection::TABLE_SETTINGS . "
WHERE name = :name;
";
try {
$statement = $this->databaseConnection->getConnection()->prepare(query: $sql);
$statement->bindParam(param: ':name', var: $name);
$statement->execute();
if ($result = $statement->fetch(mode: PDO::FETCH_ASSOC)) {
return $result['value'];
} else {
return false;
}
} catch (PDOException $e) {
exit($e->getMessage());
}
}
public function set(string $name, string $value): int
{
$currentSetting = $this->findByName($name);
if ($currentSetting !== false) {
$sql = "
UPDATE " . DatabaseConnection::TABLE_SETTINGS . "
SET value = :value
WHERE name = :name
";
} else {
$sql = "
INSERT INTO " . DatabaseConnection::TABLE_SETTINGS . " (id, name, value)
VALUES (UUID(), :name, :value)
";
}
try {
$statement = $this->databaseConnection->getConnection()->prepare(query: $sql);
$statement->bindParam(param: ':name', var: $name);
$statement->bindParam(param: ':value', var: $value);
$statement->execute();
return intval(value: $this->databaseConnection->getConnection()->lastInsertId());
} catch (PDOException $e) {
exit($e->getMessage());
}
}
}

View File

@ -1,136 +0,0 @@
<?php declare(strict_types=1);
namespace App\Service;
use UnhandledMatchError;
error_reporting(error_level: E_ALL);
class ApiClient
{
function sendCommand(string $requestType, string $serverName, int $versionIP, string $apiKey, string $command, string $serverType, array $body = []): array
{
$error = false;
$curl = curl_init();
try {
match ($serverType) {
'panel' => curl_setopt(handle: $curl, option: CURLOPT_URL, value: "https://$serverName/api/v2/" . $command),
'nameserver' => curl_setopt(handle: $curl, option: CURLOPT_URL, value: "https://$serverName/api/" . $command)
};
} catch (UnhandledMatchError) {
exit('Unhandled match: ' . $serverType .' in ' . __FILE__ . ' on line ' . __LINE__ . PHP_EOL);
}
curl_setopt(handle: $curl, option: CURLOPT_RETURNTRANSFER, value: 1);
curl_setopt(handle: $curl, option: CURLOPT_TIMEOUT_MS, value: 19999);
curl_setopt(handle: $curl, option: CURLOPT_HTTP_VERSION, value: CURL_HTTP_VERSION_2TLS);
if ($versionIP == 4) {
curl_setopt(handle: $curl, option: CURLOPT_IPRESOLVE, value: CURL_IPRESOLVE_V4);
} else {
curl_setopt(handle: $curl, option: CURLOPT_IPRESOLVE, value: CURL_IPRESOLVE_V6);
}
curl_setopt(handle: $curl, option: CURLOPT_HTTPHEADER, value: ["X-API-Key:$apiKey"]);
if ($requestType == "POST") {
curl_setopt(handle: $curl, option: CURLOPT_POST, value: true);
curl_setopt(handle: $curl, option: CURLOPT_POSTFIELDS, value: $body);
}
if ($requestType == "PUT") {
curl_setopt(handle: $curl, option: CURLOPT_CUSTOMREQUEST, value: 'PUT');
curl_setopt(handle: $curl, option: CURLOPT_POSTFIELDS, value: json_encode(value: $body));
}
curl_setopt(handle: $curl, option: CURLOPT_CUSTOMREQUEST, value: $requestType);
if ($resultJSON = curl_exec(handle: $curl)) {
$httpResponse = curl_getinfo(handle: $curl)['http_code'];
switch ($httpResponse) {
case 200:
$apiResult = json_decode(json: $resultJSON);
if ($command == "ping") {
if ($apiResult->response == "pong") {
$result = $apiResult->response;
} else {
$result = $apiResult;
}
} else {
$result = $resultJSON;
}
break;
case 400:
$result = $resultJSON;
$error = true;
break;
case 401:
$result = 'Missing or wrong API Key';
$error = true;
break;
case 404:
$result = '404 Not Found';
$error = true;
break;
case 500:
$result = 'server error';
$error = true;
break;
default:
$error = true;
$result = 'Unhandled error: ' . $httpResponse;
}
} else {
$error = true;
$result = curl_error(handle: $curl);
}
$info = curl_getinfo(handle: $curl);
$responseTime = $info['total_time'];
curl_close(handle: $curl);
return [
'responseTime' => $responseTime,
'error' => $error,
'data' => $result,
'header' => $httpResponse ?? ''
];
}
function fileGetContents(string $url, int $versionIP): ?array
{
$curl = curl_init(url: $url);
$options = array(
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_ENCODING => '',
CURLOPT_AUTOREFERER => true,
CURLOPT_CONNECTTIMEOUT => 120,
CURLOPT_TIMEOUT => 120,
CURLOPT_MAXREDIRS => 10,
);
if ($versionIP == 4) {
curl_setopt(handle: $curl, option: CURLOPT_IPRESOLVE, value: CURL_IPRESOLVE_V4);
} else {
curl_setopt(handle: $curl, option: CURLOPT_IPRESOLVE, value: CURL_IPRESOLVE_V6);
}
curl_setopt_array(handle: $curl, options: $options);
$content = curl_exec(handle: $curl);
$error = curl_errno(handle: $curl);
$errorMessage = curl_error(handle: $curl);
$header = curl_getinfo(handle: $curl);
curl_close(handle: $curl);
$header['error'] = $error;
$header['errorMessage'] = $errorMessage;
$header['content'] = $content;
return $header;
}
}

View File

@ -1,94 +0,0 @@
<?php declare(strict_types=1);
namespace App\Service;
error_reporting(error_level: E_ALL);
use App\Controller\ConfigController;
use App\Controller\CLIController;
use App\Controller\DomainController;
use App\Controller\RequestController;
use App\Repository\DomainRepository;
use App\Repository\DynDNSRepository;
use App\Service\ApiClient;
use DI\Container;
use DI\ContainerBuilder;
use DI\DependencyException;
use DI\NotFoundException;
use Exception;
use Monolog\Formatter\LineFormatter;
use Monolog\Handler\StreamHandler;
use Monolog\Level;
use Monolog\Logger;
use function DI\autowire;
class BindAPI
{
private Logger $logger;
private Container $container;
public function __construct(bool $quiet)
{
// init the logger
$dateFormat = "Y:m:d H:i:s";
$output = "%datetime% %channel%.%level_name% %message%\n"; // %context% %extra%
$formatter = new LineFormatter(format: $output, dateFormat: $dateFormat);
$debug = (new ConfigController(quiet: $quiet))->getConfig(configKey: 'debug');
if ($debug) {
$stream = new StreamHandler(stream: dirname(path: __DIR__, levels: 2) . '/var/log/bindAPI.debug', level: Level::Debug);
} else {
$stream = new StreamHandler(stream: dirname(path: __DIR__, levels: 2) . '/var/log/bindAPI.info', level: Level::Info);
}
$stream->setFormatter(formatter: $formatter);
$this->logger = new Logger(name: 'bindAPI');
$this->logger->pushHandler(handler: $stream);
$this->logger->debug(message: 'bindAPI started');
$containerBuilder = new ContainerBuilder();
$containerBuilder->addDefinitions([
ApiClient::class => autowire(),
ConfigController::class => autowire()
->constructorParameter(parameter: 'quiet', value: $quiet),
CLIController::class => autowire()
->constructorParameter(parameter: 'logger', value: $this->logger)
->constructorParameter(parameter: 'quiet', value: $quiet),
DomainController::class => autowire()
->constructorParameter(parameter: 'logger', value: $this->logger)
->constructorParameter(parameter: 'quiet', value: $quiet),
DomainRepository::class => autowire()
->constructorParameter(parameter: 'logger', value: $this->logger),
DynDnsRepository::class => autowire()
->constructorParameter(parameter: 'logger', value: $this->logger),
RequestController::class => autowire()
->constructorParameter(parameter: 'logger', value: $this->logger)
]);
$this->container = $containerBuilder->build();
}
/**
* @throws DependencyException
* @throws NotFoundException
*/
public function runCommand(array $arguments): void
{
$this->logger->debug(message: 'runCommand()');
$cliController = $this->container->get(name: CLIController::class);
$cliController->runCommand(arguments: $arguments);
}
/**
* @throws DependencyException
* @throws NotFoundException
*/
public function handleRequest(string $requestMethod, array $uri): void
{
$this->logger->debug(message: 'handleRequest()');
$requestController = $this->container->get(name: RequestController::class);
$requestController->handleRequest(requestMethod: $requestMethod, uri: $uri);
}
}

View File

@ -1,13 +0,0 @@
<?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,121 +0,0 @@
<?php
use App\Service\BindAPI;
use App\Utilities\Colors;
error_reporting(error_level: E_ALL & ~E_DEPRECATED);
if (!is_file(filename: dirname(path: __DIR__, levels: 2) . '/vendor/autoload.php')) {
echo 'Required runtime components are missing. Try running "' . Colors::YELLOW . 'composer install' . Colors::DEFAULT . '".' . PHP_EOL;
exit(1);
}
require dirname(path: __DIR__, levels: 2) . '/vendor/autoload.php';
$shortOpts = 'v::'; // version
$shortOpts .= 'q::'; // quiet
$shortOpts .= "h::"; // help
$longOpts = [
'version::',
'quiet::',
'help::'
];
$options = getopt(short_options: $shortOpts, long_options: $longOpts, rest_index: $restIndex);
$arguments = array_slice(array: $argv, offset: $restIndex);
if (array_key_exists(key: 'v', array: $options) || array_key_exists(key: 'version', array: $options)) {
$arguments = 'showVersion';
$composerJson = json_decode(json: file_get_contents(filename: dirname(path: __DIR__, levels: 2) . '/composer.json'));
$name = $composerJson->name;
$description = $composerJson->description;
$version = $composerJson->version;
$buildNumber = $composerJson->build_number;
$authors = $composerJson->authors;
// currently only one author, so just handle only first entry
$authorName = $authors[0]->name;
$authorEmail = $authors[0]->email;
echo "Name: $name" . PHP_EOL;
echo "Description: $description" . PHP_EOL;
echo "Version: $version" . PHP_EOL;
echo "Build Number: $buildNumber" . PHP_EOL;
echo "Author: $authorName ($authorEmail)" . PHP_EOL;
exit(0);
}
if (array_key_exists(key: 'h', array: $options) || array_key_exists(key: 'help', array: $options)) {
$arguments = "showUsage";
}
if (array_key_exists(key: 'q', array: $options) || array_key_exists(key: 'quiet', array: $options)) {
$quiet = true;
} else {
$quiet = false;
}
try {
$app = new BindAPI(quiet: $quiet);
} catch (Exception $e) {
echo 'Could not initialize the application: ' . $e->getMessage() . PHP_EOL;
exit(1);
}
try {
$app->runCommand(arguments: $arguments);
} catch (Exception $e) {
$exceptionMessage = $e->getMessage();
preg_match(pattern: '/\[1045]/', subject: $exceptionMessage, matches: $matches);
if (!empty($matches)) {
echo 'Access was denied for a user when trying to access the database.' . PHP_EOL;
} else {
echo 'The error message could not be parsed.';
echo $exceptionMessage . PHP_EOL;
exit(1);
}
}
function confirm(string $message = 'Are you sure? ', array $options = ['y', 'n'], string $default = 'n'): bool
{
// first $options means true, any other false
echo $message, ' (';
$first = true;
foreach ($options as $option) {
// mark default
if ($option === $default) {
$option = strtoupper(string: $option);
}
if ($first) {
echo $option;
$first = false;
} else {
echo '/', $option;
}
}
echo '): ';
$handle = fopen(filename: "php://stdin", mode: 'r');
$line = trim(string: fgetc(stream: $handle));
fclose(stream: $handle);
if ($line == '') {
// enter
$line = $default;
}
if ($line == $options[0]) {
$result = true;
} else {
$result = false;
}
return $result;
}

View File

@ -0,0 +1,42 @@
<?php
namespace App\Controller;
use App\Repository\NameserverRepository;
use DI\Container;
use DI\ContainerBuilder;
use PHPUnit\Framework\TestCase;
use function DI\autowire;
/**
*
*/
class BindApiTestController extends TestCase
{
protected Container $container;
protected NameserverRepository $nameserverRepository;
/**
* @param int|string $dataName
*
* @throws \Exception
* @internal This method is not covered by the backward compatibility promise for PHPUnit
*/
public function __construct(?string $name = null, array $data = [], $dataName = '')
{
parent::__construct(name: $name, data: $data, dataName: $dataName);
// read config TODO use .env file instead?
$configFile = dirname(path: __DIR__) . "/config.json";
$configJSON = file_get_contents(filename: $configFile);
$config = json_decode(json: $configJSON, associative: true);
$containerBuilder = new ContainerBuilder();
$containerBuilder->addDefinitions([
DatabaseConnection::class => autowire()->constructorParameter(parameter: 'config', value: $config),
]);
$this->container = $containerBuilder->build();
$this->nameserverRepository = $this->container->get(name: NameserverRepository::class);
}
}

View File

@ -1,28 +1,28 @@
<?php <?php
namespace Unit\Controller; namespace App\Controller;
use PHPUnit\Framework\TestCase; use PHPUnit\Framework\TestCase;
/** /**
* *
*/ */
class NameserverControllerTest extends BindApiControllerTest class NameserverControllerTest extends TestCase
{ {
public function setUp(): void public function setUp(): void
{ {
//$this->fixture = //$this->fixture =
} }
public function tearDown(): void public function tearDown(): void
{ {
} }
public function testUpdate() public function testUpdate()
{ {
self::assertEquals(expected: true, actual: true);
} }
} }

View File

@ -1,6 +1,6 @@
<?php <?php
namespace Unit\Controller; namespace App\Controller;
use PHPUnit\Framework\TestCase; use PHPUnit\Framework\TestCase;
@ -8,7 +8,7 @@ use PHPUnit\Framework\TestCase;
/** /**
* *
*/ */
class RequestControllerTest extends BindApiControllerTest class RequestControllerTest extends TestCase
{ {
public function setUp(): void public function setUp(): void

View File

@ -0,0 +1,161 @@
<?php
namespace App\Repository;
use App\Controller\DatabaseConnection;
use App\Controller\DomainController;
use App\Entity\Domain;
use DI\Container;
use DI\ContainerBuilder;
use Monolog\Formatter\LineFormatter;
use Monolog\Handler\StreamHandler;
use Monolog\Logger;
use PHPUnit\Framework\TestCase;
use function DI\autowire;
/**
*
*/
class DomainRepositoryTest extends TestCase
{
private Container $container;
private DomainRepository $domainRepository;
private DomainController $domainController;
private string $localZoneFile;
private string $localZonesDir;
private string $namedConfLocalFile;
private Logger $log;
/**
* @param int|string $dataName
*
* @throws \Exception
* @internal This method is not covered by the backward compatibility promise for PHPUnit
*/
public function __construct(?string $name = null, array $data = [], $dataName = '')
{
parent::__construct(name: $name, data: $data, dataName: $dataName);
$dateFormat = "Y-m-d H:i:s";
$output = "%datetime% %channel%.%level_name% %message%\n"; // %context% %extra%
$formatter = new LineFormatter(format: $output, dateFormat: $dateFormat);
$stream = new StreamHandler(stream: dirname(path: __DIR__, levels: 3) . '/bindAPI.test.log');
$stream->setFormatter(formatter: $formatter);
$this->log = new Logger(name: 'bindAPI');
$this->log->pushHandler(handler: $stream);
$this->localZoneFile = '/etc/bind/local.zones';
$this->localZonesDir = '/etc/bind/zones/';
$this->namedConfLocalFile = '/etc/bind/named.conf.local';
//$this->zoneCachePath = '/var/cache/bind/';
// read config TODO use .env file instead?
$configFile = dirname(path: __DIR__, levels: 3) . "/config.json";
$configJSON = file_get_contents(filename: $configFile);
$config = json_decode(json: $configJSON, associative: true);
$containerBuilder = new ContainerBuilder();
$containerBuilder->addDefinitions([
DatabaseConnection::class => autowire()->constructorParameter(parameter: 'config', value: $config),
DomainController::class => autowire()
->constructorParameter(parameter: 'config', value: $config)
->constructorParameter(parameter: 'log', value: $this->log),
DomainRepository::class => autowire()
->constructorParameter(parameter: 'config', value: $config)
->constructorParameter(parameter: 'log', value: $this->log),
]);
$this->container = $containerBuilder->build();
$this->domainRepository = $this->container->get(name: DomainRepository::class);
$this->domainController = $this->container->get(name: DomainController::class);
}
public function setUp(): void
{
$this->log->info(message: 'Started DomainRepositoryTest');
}
public function tearDown(): void
{
$this->log->info(message: 'Finished DomainRepositoryTest');
}
/**
* @throws \DI\NotFoundException
* @throws \DI\DependencyException
*/
public function testInsert()
{
$domain = new Domain(name: 'inserttest.org', a: '1.2.3.4', aaaa: '1bad::babe');
$this->domainRepository->insert(domain: $domain);
$this->domainController->createZoneFile(domain: $domain);
// now get the persisted domain with id
$domainTest = $this->domainRepository->findByName(name: 'inserttest.org');
$this->assertIsNotBool(actual: $domainTest);
$this->assertEquals(expected: 'inserttest.org', actual: $domainTest->getName());
if ($namedConfLocal = file_get_contents(filename: $this->namedConfLocalFile)) {
$this->assertStringContainsString(needle: $this->localZoneFile, haystack: $namedConfLocal);
} else {
$this->fail(message: 'No permissions: ' . $this->namedConfLocalFile);
}
$this->assertNotFalse(condition: fileperms(filename: $this->localZoneFile));
$localZones = file_get_contents(filename: $this->localZoneFile);
$this->assertStringContainsString(needle: $domainTest->getName(), haystack: $localZones);
$zoneFile = $this->localZonesDir . $domain->getName();
$this->assertFileExists(filename: $zoneFile);
// clean up
$this->domainRepository->delete(domain: $domainTest);
}
/**
* @throws \DI\NotFoundException
* @throws \DI\DependencyException
*/
public function testDelete()
{
$domain = new Domain(name: 'inserttest.org', a: '1.2.3.4', aaaa: '1bad::babe');
$this->domainRepository->insert(domain: $domain);
$this->domainController->createZoneFile(domain: $domain);
$domainTest = $this->domainRepository->findByName(name: 'inserttest.org');
$this->assertIsNotBool(actual: $domainTest);
$this->assertEquals(expected: 'inserttest.org', actual: $domainTest->getName());
// domain is valid and created
// now delete and check for cleanup
$this->domainRepository->delete(domain: $domainTest);
$this->domainController->deleteZone(domain: $domainTest);
// check zone is removed
$this->assertNotFalse(condition: fileperms(filename: $this->localZoneFile));
$localZones = file_get_contents(filename: $this->localZoneFile);
$this->assertStringNotContainsString(needle: $domainTest->getName(), haystack: $localZones);
$zoneFile = $this->localZonesDir . $domain->getName();
$this->assertFileDoesNotExist(filename: $zoneFile);
}
}

View File

@ -0,0 +1,61 @@
<?php
namespace App\Repository;
use App\Controller\DatabaseConnection;
use App\Entity\Nameserver;
use DI\Container;
use DI\ContainerBuilder;
use PHPUnit\Framework\TestCase;
use function DI\autowire;
/**
*
*/
class NameserverRepositoryTest extends TestCase
{
private Container $container;
private NameserverRepository $nameserverRepository;
/**
* @param int|string $dataName
*
* @throws \Exception
* @internal This method is not covered by the backward compatibility promise for PHPUnit
*/
public function __construct(?string $name = null, array $data = [], $dataName = '')
{
parent::__construct(name: $name, data: $data, dataName: $dataName);
// read config TODO use .env file instead?
$configFile = dirname(path: __DIR__, levels: 3) . "/config.json";
$configJSON = file_get_contents(filename: $configFile);
$config = json_decode(json: $configJSON, associative: true);
$containerBuilder = new ContainerBuilder();
$containerBuilder->addDefinitions([
DatabaseConnection::class => autowire()->constructorParameter(parameter: 'config', value: $config),
]);
$this->container = $containerBuilder->build();
$this->nameserverRepository = $this->container->get(name: NameserverRepository::class);
}
/**
* @throws \DI\NotFoundException
* @throws \DI\DependencyException
*/
public function testInsert()
{
$nameserver = new Nameserver(name: 'inserttest.org', a: '1.2.3.4', aaaa: '1bad::babe');
$this->nameserverRepository->insert(nameserver: $nameserver);
$nameservertest = $this->nameserverRepository->findByName(name: 'inserttest.org');
$this->assertIsNotBool(actual: $nameserver);
$this->assertEquals(expected: 'inserttest.org', actual: $nameservertest->getName());
// clean up
$this->nameserverRepository->delete(id: $nameservertest->getId());
}
}

View File

@ -1,15 +1,11 @@
<?php <?php
namespace Unit\Repository; namespace App\Repository;
use App\Controller\BindApiTestController; use App\Controller\BindApiTestController;
use PHPUnit\Framework\TestCase; use PHPUnit\Framework\TestCase;
use Unit\Controller\BindApiControllerTest;
/** class PanelRepositoryTest extends BindApiTestController
*
*/
class PanelRepositoryTest extends BindApiControllerTest
{ {
@ -24,7 +20,6 @@ class PanelRepositoryTest extends BindApiControllerTest
public function testInsert() public function testInsert()
{ {
self::assertEquals(expected: true, actual: true);
}
}
} }

View File

@ -0,0 +1,17 @@
<?php
namespace App\Controller;
use PHPUnit\Framework\TestCase;
/**
*
*/
class DatabaseConnectionTest extends TestCase
{
public function testGetConnection()
{
}
}

View File

@ -1,83 +0,0 @@
<?php
namespace Unit\Controller;
use App\Controller\ConfigController;
use App\Controller\DatabaseConnection;
use App\Controller\DomainController;
use App\Repository\DomainRepository;
use App\Repository\NameserverRepository;
use DI\Container;
use DI\ContainerBuilder;
use Exception;
use Monolog\Formatter\LineFormatter;
use Monolog\Handler\StreamHandler;
use Monolog\Level;
use Monolog\Logger;
use PHPUnit\Framework\TestCase;
use function DI\autowire;
/**
*
*/
class BindApiControllerTest extends TestCase
{
protected Container $container;
protected NameserverRepository $nameserverRepository;
protected DomainRepository $domainRepository;
protected DomainController $domainController;
protected Logger $logger;
/**
* @param int|string $dataName
*
* @throws Exception
* @internal This method is not covered by the backward compatibility promise for PHPUnit
*/
public function __construct(?string $name = null, array $data = [], $dataName = '')
{
parent::__construct(name: $name, data: $data, dataName: $dataName);
// init the logger
$dateFormat = "Y:m:d H:i:s";
$output = "%datetime% %channel%.%level_name% %message%\n"; // %context% %extra%
$formatter = new LineFormatter(format: $output, dateFormat: $dateFormat);
$debug = (new ConfigController)->getConfig(configKey: 'debug');
if ($debug) {
$stream = new StreamHandler(stream: dirname(path: __DIR__, levels: 3) . '/bindAPI.test.log', level: Level::Debug);
} else {
$stream = new StreamHandler(stream: dirname(path: __DIR__, levels: 3) . '/bindAPI.test.log', level: Level::Info);
}
$stream->setFormatter(formatter: $formatter);
$this->logger = new Logger(name: 'bindAPI');
$this->logger->pushHandler(handler: $stream);
$this->logger->debug(message: 'bindAPI started');
$containerBuilder = new ContainerBuilder();
$containerBuilder->addDefinitions([
//DatabaseConnection::class => autowire()->constructorParameter(parameter: 'config', value: $config),
DomainController::class => autowire()
->constructorParameter(parameter: 'logger', value: $this->logger),
DomainRepository::class => autowire()
->constructorParameter(parameter: 'logger', value: $this->logger),
]);
$this->container = $containerBuilder->build();
$this->nameserverRepository = $this->container->get(name: NameserverRepository::class);
$this->domainRepository = $this->container->get(name: DomainRepository::class);
$this->domainController = $this->container->get(name: DomainController::class);
}
public function testFoo(): void
{
self::assertEquals(expected: true, actual: true);
}
}

View File

@ -1,42 +0,0 @@
<?php
namespace Unit\Controller;
use App\Controller\ConfigController;
use App\Controller\DatabaseConnection;
use PDO;
use PDOException;
/**
* @covers \App\Controller\DatabaseConnection
* @covers \App\Controller\ConfigController
*/
class DatabaseConnectionTest extends BindApiControllerTest
{
private PDO $dbConnection;
public function testGetConnection()
{
$configController = new ConfigController(test: true);
$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');
try {
$this->dbConnection = new PDO(
dsn: "mysql:host=$dbHost;port=$dbPort;charset=utf8mb4;dbname=$dbDatabase",
username: $dbUser,
password: $dbPassword
);
} catch (PDOException $e) {
$this->fail(message: $e->getMessage());
}
$databaseConnection = new DatabaseConnection(configController: $configController);
self::assertEquals(expected: $databaseConnection->getConnection(), actual: $this->dbConnection);
}
}

View File

@ -1,124 +0,0 @@
<?php
namespace Unit\Repository;
use App\Controller\ConfigController;
use App\Controller\DomainController;
use App\Entity\Domain;
use App\Repository\DomainRepository;
use DI\Container;
use DI\ContainerBuilder;
use Exception;
use Monolog\Formatter\LineFormatter;
use Monolog\Handler\StreamHandler;
use Monolog\Logger;
use PHPUnit\Framework\TestCase;
use Unit\Controller\BindApiControllerTest;
use function DI\autowire;
/**
*
*/
class DomainRepositoryTest extends BindApiControllerTest
{
private string $localZoneFile;
private string $localZonesDir;
private string $namedConfLocalFile;
/**
* @param int|string $dataName
*
* @throws Exception
* @internal This method is not covered by the backward compatibility promise for PHPUnit
*/
public function __construct(?string $name = null, array $data = [], $dataName = '')
{
parent::__construct(name: $name, data: $data, dataName: $dataName);
}
public function setUp(): void
{
$this->logger->info(message: 'Started DomainRepositoryTest');
}
public function tearDown(): void
{
$this->logger->info(message: 'Finished DomainRepositoryTest');
}
/**
*/
public function testInsert()
{
self::assertEquals(expected: true, actual: true);
/*
$domain = new Domain(name: 'inserttest.org', panel: 'keyhelp.lab.24unix.net');
$this->domainRepository->insert(domain: $domain);
$this->domainController->createSlaveZoneFile(domain: $domain);
// now get the persisted domain with id
$domainTest = $this->domainRepository->findByName(name: 'inserttest.org');
$this->assertIsNotBool(actual: $domainTest);
$this->assertEquals(expected: 'inserttest.org', actual: $domainTest->getName());
if ($namedConfLocal = file_get_contents(filename: $this->namedConfLocalFile)) {
$this->assertStringContainsString(needle: $this->localZoneFile, haystack: $namedConfLocal);
} else {
$this->fail(message: 'No permissions: ' . $this->namedConfLocalFile);
}
$this->assertNotFalse(condition: fileperms(filename: $this->localZoneFile));
$localZones = file_get_contents(filename: $this->localZoneFile);
$this->assertStringContainsString(needle: $domainTest->getName(), haystack: $localZones);
$zoneFile = $this->localZonesDir . $domain->getName();
$this->assertFileExists(filename: $zoneFile);
// clean up
$this->domainRepository->delete(domain: $domainTest);
*/
}
/**
*/
public function testDelete()
{
self::assertEquals(expected: true, actual: true);
/*
$domain = new Domain(name: 'inserttest.org', panel: 'keyhelp.lab.24unix.net');
$this->domainRepository->insert(domain: $domain);
$this->domainController->createSlaveZoneFile(domain: $domain);
$domainTest = $this->domainRepository->findByName(name: 'inserttest.org');
$this->assertIsNotBool(actual: $domainTest);
$this->assertEquals(expected: 'inserttest.org', actual: $domainTest->getName());
// domain is valid and created
// now delete and check for cleanup
$this->domainRepository->delete(domain: $domainTest);
$this->domainController->deleteZone(domain: $domainTest);
// check zone is removed
$this->assertNotFalse(condition: fileperms(filename: $this->localZoneFile));
$localZones = file_get_contents(filename: $this->localZoneFile);
$this->assertStringNotContainsString(needle: $domainTest->getName(), haystack: $localZones);
$zoneFile = $this->localZonesDir . $domain->getName();
$this->assertFileDoesNotExist(filename: $zoneFile);
*/
}
}

View File

@ -1,27 +0,0 @@
<?php
namespace Unit\Repository;
use App\Entity\Nameserver;
use Unit\Controller\BindApiControllerTest;
/**
*
*/
class NameserverRepositoryTest extends BindApiControllerTest
{
/**
*/
public function testInsert()
{
$nameserver = new Nameserver(name: 'inserttest.org', a: '1.2.3.4', aaaa: '1bad::babe');
$this->nameserverRepository->insert(nameserver: $nameserver);
$nameserverTest = $this->nameserverRepository->findByName(name: 'inserttest.org');
$this->assertIsNotBool(actual: $nameserver);
$this->assertEquals(expected: 'inserttest.org', actual: $nameserverTest->getName());
// clean up
$this->nameserverRepository->delete(id: $nameserverTest->getId());
}
}