Compare commits

..

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

89 changed files with 2722 additions and 8341 deletions

7
.gitignore vendored
View File

@ -9,11 +9,4 @@
/reports/ /reports/
/bindAPI.test.log /bindAPI.test.log
/.phpunit.result.cache /.phpunit.result.cache
/config.json.dev
/config.json.test /config.json.test
/config.json.prod
keys.txt
/.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

108
.idea/bindAPI.iml Normal file
View File

@ -0,0 +1,108 @@
<?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$/spec" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/tests" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" packagePrefix="App\" />
<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" />
<excludeFolder url="file://$MODULE_DIR$/vendor/nikic/php-parser" />
<excludeFolder url="file://$MODULE_DIR$/vendor/php-di/php-di" />
<excludeFolder url="file://$MODULE_DIR$/vendor/php-di/phpdoc-reader" />
<excludeFolder url="file://$MODULE_DIR$/vendor/php-di/invoker" />
<excludeFolder url="file://$MODULE_DIR$/vendor/monolog/monolog" />
<excludeFolder url="file://$MODULE_DIR$/vendor/myclabs/deep-copy" />
<excludeFolder url="file://$MODULE_DIR$/vendor/phar-io/version" />
<excludeFolder url="file://$MODULE_DIR$/vendor/phar-io/manifest" />
<excludeFolder url="file://$MODULE_DIR$/vendor/phpspec/prophecy" />
<excludeFolder url="file://$MODULE_DIR$/vendor/phpunit/php-invoker" />
<excludeFolder url="file://$MODULE_DIR$/vendor/phpunit/php-code-coverage" />
<excludeFolder url="file://$MODULE_DIR$/vendor/phpunit/php-file-iterator" />
<excludeFolder url="file://$MODULE_DIR$/vendor/phpunit/phpunit" />
<excludeFolder url="file://$MODULE_DIR$/vendor/phpunit/php-timer" />
<excludeFolder url="file://$MODULE_DIR$/vendor/phpunit/php-text-template" />
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/polyfill-ctype" />
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/finder" />
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/yaml" />
<excludeFolder url="file://$MODULE_DIR$/vendor/theseer/tokenizer" />
<excludeFolder url="file://$MODULE_DIR$/vendor/zircote/swagger-php" />
<excludeFolder url="file://$MODULE_DIR$/vendor/arubacao/tld-checker" />
<excludeFolder url="file://$MODULE_DIR$/vendor/doctrine/instantiator" />
<excludeFolder url="file://$MODULE_DIR$/vendor/doctrine/annotations" />
<excludeFolder url="file://$MODULE_DIR$/vendor/doctrine/lexer" />
<excludeFolder url="file://$MODULE_DIR$/vendor/sebastian/diff" />
<excludeFolder url="file://$MODULE_DIR$/vendor/sebastian/exporter" />
<excludeFolder url="file://$MODULE_DIR$/vendor/sebastian/code-unit-reverse-lookup" />
<excludeFolder url="file://$MODULE_DIR$/vendor/sebastian/object-reflector" />
<excludeFolder url="file://$MODULE_DIR$/vendor/sebastian/global-state" />
<excludeFolder url="file://$MODULE_DIR$/vendor/sebastian/recursion-context" />
<excludeFolder url="file://$MODULE_DIR$/vendor/sebastian/type" />
<excludeFolder url="file://$MODULE_DIR$/vendor/sebastian/comparator" />
<excludeFolder url="file://$MODULE_DIR$/vendor/sebastian/object-enumerator" />
<excludeFolder url="file://$MODULE_DIR$/vendor/sebastian/code-unit" />
<excludeFolder url="file://$MODULE_DIR$/vendor/sebastian/complexity" />
<excludeFolder url="file://$MODULE_DIR$/vendor/sebastian/resource-operations" />
<excludeFolder url="file://$MODULE_DIR$/vendor/sebastian/cli-parser" />
<excludeFolder url="file://$MODULE_DIR$/vendor/sebastian/lines-of-code" />
<excludeFolder url="file://$MODULE_DIR$/vendor/sebastian/version" />
<excludeFolder url="file://$MODULE_DIR$/vendor/sebastian/environment" />
<excludeFolder url="file://$MODULE_DIR$/vendor/squizlabs/php_codesniffer" />
<excludeFolder url="file://$MODULE_DIR$/vendor/webmozart/assert" />
<excludeFolder url="file://$MODULE_DIR$/vendor/escapestudios/symfony2-coding-standard" />
<excludeFolder url="file://$MODULE_DIR$/vendor/phpdocumentor/type-resolver" />
<excludeFolder url="file://$MODULE_DIR$/vendor/phpdocumentor/reflection-common" />
<excludeFolder url="file://$MODULE_DIR$/vendor/phpdocumentor/reflection-docblock" />
<excludeFolder url="file://$MODULE_DIR$/vendor/phplucidframe/console-table" />
<excludeFolder url="file://$MODULE_DIR$/vendor/composer" />
<excludeFolder url="file://$MODULE_DIR$/vendor/psr/log" />
<excludeFolder url="file://$MODULE_DIR$/vendor/psr/cache" />
<excludeFolder url="file://$MODULE_DIR$/vendor/psr/container" />
<excludeFolder url="file://$MODULE_DIR$/vendor/laravel/serializable-closure" />
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/serializer" />
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/string" />
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/property-access" />
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/polyfill-intl-normalizer" />
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/polyfill-mbstring" />
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/polyfill-intl-grapheme" />
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/property-info" />
<excludeFolder url="file://$MODULE_DIR$/vendor/netresearch/jsonmapper" />
</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>

6
.idea/deployment.xml Normal file
View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="PublishConfigData" autoUpload="On explicit save action" promptOnRemoteOverwrite="CHECK_TIMESTAMP" serverName="keyhelp.lab.24unix.net" preserveFilePermissions="true" autoUploadExternalChanges="true" notifyRemoteChanges="true">
<option name="myAutoUpload" value="ON_EXPLICIT_SAVE" />
</component>
</project>

View File

@ -0,0 +1,109 @@
<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="116" 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="PhpNamedArgumentsWithChangedOrderInspection" enabled="true" level="WARNING" enabled_by_default="true" editorAttributes="WARNING_ATTRIBUTES" />
<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="PhpUnnecessaryFullyQualifiedNameInspection" enabled="true" level="WARNING" enabled_by_default="true" editorAttributes="WARNING_ATTRIBUTES" />
<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>

80
.idea/php.xml Normal file
View File

@ -0,0 +1,80 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="PhpCodeSniffer">
<phpcs_settings>
<PhpCSConfiguration tool_path="$PROJECT_DIR$/vendor/bin/phpcs" />
</phpcs_settings>
</component>
<component name="PhpIncludePathManager">
<include_path>
<path value="$PROJECT_DIR$/vendor/nikic/php-parser" />
<path value="$PROJECT_DIR$/vendor/php-di/php-di" />
<path value="$PROJECT_DIR$/vendor/php-di/phpdoc-reader" />
<path value="$PROJECT_DIR$/vendor/php-di/invoker" />
<path value="$PROJECT_DIR$/vendor/monolog/monolog" />
<path value="$PROJECT_DIR$/vendor/myclabs/deep-copy" />
<path value="$PROJECT_DIR$/vendor/phar-io/version" />
<path value="$PROJECT_DIR$/vendor/phar-io/manifest" />
<path value="$PROJECT_DIR$/vendor/phpspec/prophecy" />
<path value="$PROJECT_DIR$/vendor/phpunit/php-invoker" />
<path value="$PROJECT_DIR$/vendor/phpunit/php-code-coverage" />
<path value="$PROJECT_DIR$/vendor/phpunit/php-file-iterator" />
<path value="$PROJECT_DIR$/vendor/phpunit/phpunit" />
<path value="$PROJECT_DIR$/vendor/phpunit/php-timer" />
<path value="$PROJECT_DIR$/vendor/phpunit/php-text-template" />
<path value="$PROJECT_DIR$/vendor/symfony/polyfill-ctype" />
<path value="$PROJECT_DIR$/vendor/symfony/finder" />
<path value="$PROJECT_DIR$/vendor/symfony/yaml" />
<path value="$PROJECT_DIR$/vendor/theseer/tokenizer" />
<path value="$PROJECT_DIR$/vendor/zircote/swagger-php" />
<path value="$PROJECT_DIR$/vendor/arubacao/tld-checker" />
<path value="$PROJECT_DIR$/vendor/doctrine/instantiator" />
<path value="$PROJECT_DIR$/vendor/doctrine/annotations" />
<path value="$PROJECT_DIR$/vendor/doctrine/lexer" />
<path value="$PROJECT_DIR$/vendor/sebastian/diff" />
<path value="$PROJECT_DIR$/vendor/sebastian/exporter" />
<path value="$PROJECT_DIR$/vendor/sebastian/code-unit-reverse-lookup" />
<path value="$PROJECT_DIR$/vendor/sebastian/object-reflector" />
<path value="$PROJECT_DIR$/vendor/sebastian/global-state" />
<path value="$PROJECT_DIR$/vendor/sebastian/recursion-context" />
<path value="$PROJECT_DIR$/vendor/sebastian/type" />
<path value="$PROJECT_DIR$/vendor/sebastian/comparator" />
<path value="$PROJECT_DIR$/vendor/sebastian/object-enumerator" />
<path value="$PROJECT_DIR$/vendor/sebastian/code-unit" />
<path value="$PROJECT_DIR$/vendor/sebastian/complexity" />
<path value="$PROJECT_DIR$/vendor/sebastian/resource-operations" />
<path value="$PROJECT_DIR$/vendor/sebastian/cli-parser" />
<path value="$PROJECT_DIR$/vendor/sebastian/lines-of-code" />
<path value="$PROJECT_DIR$/vendor/sebastian/version" />
<path value="$PROJECT_DIR$/vendor/sebastian/environment" />
<path value="$PROJECT_DIR$/vendor/squizlabs/php_codesniffer" />
<path value="$PROJECT_DIR$/vendor/webmozart/assert" />
<path value="$PROJECT_DIR$/vendor/escapestudios/symfony2-coding-standard" />
<path value="$PROJECT_DIR$/vendor/phpdocumentor/type-resolver" />
<path value="$PROJECT_DIR$/vendor/phpdocumentor/reflection-common" />
<path value="$PROJECT_DIR$/vendor/phpdocumentor/reflection-docblock" />
<path value="$PROJECT_DIR$/vendor/phplucidframe/console-table" />
<path value="$PROJECT_DIR$/vendor/composer" />
<path value="$PROJECT_DIR$/vendor/psr/log" />
<path value="$PROJECT_DIR$/vendor/psr/cache" />
<path value="$PROJECT_DIR$/vendor/psr/container" />
<path value="$PROJECT_DIR$/vendor/laravel/serializable-closure" />
<path value="$PROJECT_DIR$/vendor/symfony/serializer" />
<path value="$PROJECT_DIR$/vendor/symfony/string" />
<path value="$PROJECT_DIR$/vendor/symfony/property-access" />
<path value="$PROJECT_DIR$/vendor/symfony/polyfill-intl-normalizer" />
<path value="$PROJECT_DIR$/vendor/symfony/polyfill-mbstring" />
<path value="$PROJECT_DIR$/vendor/symfony/polyfill-intl-grapheme" />
<path value="$PROJECT_DIR$/vendor/symfony/property-info" />
<path value="$PROJECT_DIR$/vendor/netresearch/jsonmapper" />
</include_path>
</component>
<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>

6
.idea/vcs.xml Normal file
View File

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

View File

@ -0,0 +1 @@
a:6:{s:9:"classesIn";a:1:{s:25:"App\Entity\KeyHelp\Apache";a:6:{s:4:"name";s:6:"Apache";s:14:"namespacedName";s:25:"App\Entity\KeyHelp\Apache";s:9:"namespace";s:18:"App\Entity\KeyHelp";s:9:"startLine";i:8;s:7:"endLine";i:44;s:7:"methods";a:4:{s:17:"getHttpDirectives";a:6:{s:10:"methodName";s:17:"getHttpDirectives";s:9:"signature";s:27:"getHttpDirectives(): string";s:10:"visibility";s:6:"public";s:9:"startLine";i:16;s:7:"endLine";i:19;s:3:"ccn";i:1;}s:17:"setHttpDirectives";a:6:{s:10:"methodName";s:17:"setHttpDirectives";s:9:"signature";s:48:"setHttpDirectives(?string $httpDirectives): void";s:10:"visibility";s:6:"public";s:9:"startLine";i:24;s:7:"endLine";i:27;s:3:"ccn";i:1;}s:18:"getHttpsDirectives";a:6:{s:10:"methodName";s:18:"getHttpsDirectives";s:9:"signature";s:28:"getHttpsDirectives(): string";s:10:"visibility";s:6:"public";s:9:"startLine";i:32;s:7:"endLine";i:35;s:3:"ccn";i:1;}s:18:"setHttpsDirectives";a:6:{s:10:"methodName";s:18:"setHttpsDirectives";s:9:"signature";s:50:"setHttpsDirectives(?string $httpsDirectives): void";s:10:"visibility";s:6:"public";s:9:"startLine";i:40;s:7:"endLine";i:43;s:3:"ccn";i:1;}}}}s:8:"traitsIn";a:0:{}s:11:"functionsIn";a:0:{}s:14:"linesOfCodeFor";a:3:{s:11:"linesOfCode";i:44;s:18:"commentLinesOfCode";i:15;s:21:"nonCommentLinesOfCode";i:29;}s:15:"ignoredLinesFor";a:1:{i:0;i:8;}s:17:"executableLinesIn";a:4:{i:0;i:18;i:1;i:26;i:2;i:34;i:3;i:42;}}

View File

@ -0,0 +1 @@
a:6:{s:9:"classesIn";a:1:{s:21:"App\Entity\Nameserver";a:6:{s:4:"name";s:10:"Nameserver";s:14:"namespacedName";s:21:"App\Entity\Nameserver";s:9:"namespace";s:10:"App\Entity";s:9:"startLine";i:14;s:7:"endLine";i:163;s:7:"methods";a:14:{s:11:"__construct";a:6:{s:10:"methodName";s:11:"__construct";s:9:"signature";s:117:"__construct(string $name, int $id, string $a, string $aaaa, string $passphrase, string $apikey, string $apikeyPrefix)";s:10:"visibility";s:6:"public";s:9:"startLine";i:27;s:7:"endLine";i:51;s:3:"ccn";i:3;}s:15:"getApikeyPrefix";a:6:{s:10:"methodName";s:15:"getApikeyPrefix";s:9:"signature";s:25:"getApikeyPrefix(): string";s:10:"visibility";s:6:"public";s:9:"startLine";i:56;s:7:"endLine";i:59;s:3:"ccn";i:1;}s:15:"setApikeyPrefix";a:6:{s:10:"methodName";s:15:"setApikeyPrefix";s:9:"signature";s:43:"setApikeyPrefix(string $apikeyPrefix): void";s:10:"visibility";s:6:"public";s:9:"startLine";i:64;s:7:"endLine";i:67;s:3:"ccn";i:1;}s:4:"getA";a:6:{s:10:"methodName";s:4:"getA";s:9:"signature";s:14:"getA(): string";s:10:"visibility";s:6:"public";s:9:"startLine";i:73;s:7:"endLine";i:77;s:3:"ccn";i:1;}s:4:"setA";a:6:{s:10:"methodName";s:4:"setA";s:9:"signature";s:21:"setA(string $a): void";s:10:"visibility";s:6:"public";s:9:"startLine";i:82;s:7:"endLine";i:85;s:3:"ccn";i:1;}s:7:"getAaaa";a:6:{s:10:"methodName";s:7:"getAaaa";s:9:"signature";s:17:"getAaaa(): string";s:10:"visibility";s:6:"public";s:9:"startLine";i:90;s:7:"endLine";i:94;s:3:"ccn";i:1;}s:7:"setAaaa";a:6:{s:10:"methodName";s:7:"setAaaa";s:9:"signature";s:27:"setAaaa(string $aaaa): void";s:10:"visibility";s:6:"public";s:9:"startLine";i:99;s:7:"endLine";i:102;s:3:"ccn";i:1;}s:9:"getApikey";a:6:{s:10:"methodName";s:9:"getApikey";s:9:"signature";s:19:"getApikey(): string";s:10:"visibility";s:6:"public";s:9:"startLine";i:107;s:7:"endLine";i:111;s:3:"ccn";i:1;}s:9:"setApikey";a:6:{s:10:"methodName";s:9:"setApikey";s:9:"signature";s:31:"setApikey(string $apikey): void";s:10:"visibility";s:6:"public";s:9:"startLine";i:116;s:7:"endLine";i:119;s:3:"ccn";i:1;}s:5:"getId";a:6:{s:10:"methodName";s:5:"getId";s:9:"signature";s:12:"getId(): int";s:10:"visibility";s:6:"public";s:9:"startLine";i:124;s:7:"endLine";i:128;s:3:"ccn";i:1;}s:5:"setId";a:6:{s:10:"methodName";s:5:"setId";s:9:"signature";s:20:"setId(int $id): void";s:10:"visibility";s:6:"public";s:9:"startLine";i:133;s:7:"endLine";i:136;s:3:"ccn";i:1;}s:7:"getName";a:6:{s:10:"methodName";s:7:"getName";s:9:"signature";s:17:"getName(): string";s:10:"visibility";s:6:"public";s:9:"startLine";i:141;s:7:"endLine";i:145;s:3:"ccn";i:1;}s:7:"setName";a:6:{s:10:"methodName";s:7:"setName";s:9:"signature";s:27:"setName(string $name): void";s:10:"visibility";s:6:"public";s:9:"startLine";i:150;s:7:"endLine";i:153;s:3:"ccn";i:1;}s:13:"getPassphrase";a:6:{s:10:"methodName";s:13:"getPassphrase";s:9:"signature";s:23:"getPassphrase(): string";s:10:"visibility";s:6:"public";s:9:"startLine";i:158;s:7:"endLine";i:161;s:3:"ccn";i:1;}}}}s:8:"traitsIn";a:0:{}s:11:"functionsIn";a:0:{}s:14:"linesOfCodeFor";a:3:{s:11:"linesOfCode";i:163;s:18:"commentLinesOfCode";i:51;s:21:"nonCommentLinesOfCode";i:112;}s:15:"ignoredLinesFor";a:1:{i:0;i:14;}s:17:"executableLinesIn";a:23:{i:0;i:27;i:1;i:36;i:2;i:37;i:3;i:38;i:4;i:40;i:5;i:42;i:6;i:44;i:7;i:45;i:8;i:46;i:9;i:47;i:10;i:58;i:11;i:66;i:12;i:76;i:13;i:84;i:14;i:93;i:15;i:101;i:16;i:110;i:17;i:118;i:18;i:127;i:19;i:135;i:20;i:144;i:21;i:152;i:22;i:160;}}

View File

@ -0,0 +1 @@
a:6:{s:9:"classesIn";a:1:{s:17:"App\Entity\Apikey";a:6:{s:4:"name";s:6:"Apikey";s:14:"namespacedName";s:17:"App\Entity\Apikey";s:9:"namespace";s:10:"App\Entity";s:9:"startLine";i:13;s:7:"endLine";i:115;s:7:"methods";a:10:{s:11:"__construct";a:6:{s:10:"methodName";s:11:"__construct";s:9:"signature";s:92:"__construct(int $id, string $name, string $apikey, string $apikeyPrefix, string $passphrase)";s:10:"visibility";s:6:"public";s:9:"startLine";i:16;s:7:"endLine";i:38;s:3:"ccn";i:3;}s:13:"getPassphrase";a:6:{s:10:"methodName";s:13:"getPassphrase";s:9:"signature";s:23:"getPassphrase(): string";s:10:"visibility";s:6:"public";s:9:"startLine";i:43;s:7:"endLine";i:46;s:3:"ccn";i:1;}s:9:"getApikey";a:6:{s:10:"methodName";s:9:"getApikey";s:9:"signature";s:19:"getApikey(): string";s:10:"visibility";s:6:"public";s:9:"startLine";i:52;s:7:"endLine";i:55;s:3:"ccn";i:1;}s:15:"getApikeyPrefix";a:6:{s:10:"methodName";s:15:"getApikeyPrefix";s:9:"signature";s:25:"getApikeyPrefix(): string";s:10:"visibility";s:6:"public";s:9:"startLine";i:60;s:7:"endLine";i:63;s:3:"ccn";i:1;}s:5:"getId";a:6:{s:10:"methodName";s:5:"getId";s:9:"signature";s:12:"getId(): int";s:10:"visibility";s:6:"public";s:9:"startLine";i:69;s:7:"endLine";i:72;s:3:"ccn";i:1;}s:5:"setId";a:6:{s:10:"methodName";s:5:"setId";s:9:"signature";s:20:"setId(int $id): void";s:10:"visibility";s:6:"public";s:9:"startLine";i:77;s:7:"endLine";i:80;s:3:"ccn";i:1;}s:7:"getName";a:6:{s:10:"methodName";s:7:"getName";s:9:"signature";s:17:"getName(): string";s:10:"visibility";s:6:"public";s:9:"startLine";i:85;s:7:"endLine";i:88;s:3:"ccn";i:1;}s:15:"setApikeyPrefix";a:6:{s:10:"methodName";s:15:"setApikeyPrefix";s:9:"signature";s:43:"setApikeyPrefix(string $apikeyPrefix): void";s:10:"visibility";s:6:"public";s:9:"startLine";i:93;s:7:"endLine";i:96;s:3:"ccn";i:1;}s:9:"setApikey";a:6:{s:10:"methodName";s:9:"setApikey";s:9:"signature";s:31:"setApikey(string $apikey): void";s:10:"visibility";s:6:"public";s:9:"startLine";i:101;s:7:"endLine";i:104;s:3:"ccn";i:1;}s:7:"setName";a:6:{s:10:"methodName";s:7:"setName";s:9:"signature";s:27:"setName(string $name): void";s:10:"visibility";s:6:"public";s:9:"startLine";i:110;s:7:"endLine";i:113;s:3:"ccn";i:1;}}}}s:8:"traitsIn";a:0:{}s:11:"functionsIn";a:0:{}s:14:"linesOfCodeFor";a:3:{s:11:"linesOfCode";i:115;s:18:"commentLinesOfCode";i:30;s:21:"nonCommentLinesOfCode";i:85;}s:15:"ignoredLinesFor";a:1:{i:0;i:13;}s:17:"executableLinesIn";a:19:{i:0;i:16;i:1;i:24;i:2;i:25;i:3;i:26;i:4;i:28;i:5;i:30;i:6;i:32;i:7;i:33;i:8;i:34;i:9;i:35;i:10;i:45;i:11;i:54;i:12;i:62;i:13;i:71;i:14;i:79;i:15;i:87;i:16;i:95;i:17;i:103;i:18;i:112;}}

View File

@ -0,0 +1 @@
a:6:{s:9:"classesIn";a:1:{s:31:"App\Repository\DynDNSRepository";a:6:{s:4:"name";s:16:"DynDNSRepository";s:14:"namespacedName";s:31:"App\Repository\DynDNSRepository";s:9:"namespace";s:14:"App\Repository";s:9:"startLine";i:14;s:7:"endLine";i:233;s:7:"methods";a:8:{s:11:"__construct";a:6:{s:10:"methodName";s:11:"__construct";s:9:"signature";s:90:"__construct(App\Controller\DatabaseConnection $databaseConnection, Monolog\Logger $logger)";s:10:"visibility";s:6:"public";s:9:"startLine";i:16;s:7:"endLine";i:21;s:3:"ccn";i:1;}s:6:"delete";a:6:{s:10:"methodName";s:6:"delete";s:9:"signature";s:38:"delete(App\Entity\DynDNS $dynDNS): int";s:10:"visibility";s:6:"public";s:9:"startLine";i:28;s:7:"endLine";i:47;s:3:"ccn";i:2;}s:7:"findAll";a:6:{s:10:"methodName";s:7:"findAll";s:9:"signature";s:16:"findAll(): array";s:10:"visibility";s:6:"public";s:9:"startLine";i:52;s:7:"endLine";i:73;s:3:"ccn";i:3;}s:10:"findByName";a:6:{s:10:"methodName";s:10:"findByName";s:9:"signature";s:49:"findByName(string $name): \App\Entity\DynDNS|bool";s:10:"visibility";s:6:"public";s:9:"startLine";i:80;s:7:"endLine";i:101;s:3:"ccn";i:3;}s:15:"getLongestEntry";a:6:{s:10:"methodName";s:15:"getLongestEntry";s:9:"signature";s:35:"getLongestEntry(string $field): int";s:10:"visibility";s:6:"public";s:9:"startLine";i:108;s:7:"endLine";i:121;s:3:"ccn";i:2;}s:6:"insert";a:6:{s:10:"methodName";s:6:"insert";s:9:"signature";s:46:"insert(App\Entity\DynDNS $dynDNS): bool|string";s:10:"visibility";s:6:"public";s:9:"startLine";i:128;s:7:"endLine";i:151;s:3:"ccn";i:2;}s:6:"update";a:6:{s:10:"methodName";s:6:"update";s:9:"signature";s:43:"update(App\Entity\DynDNS $dynDNS): bool|int";s:10:"visibility";s:6:"public";s:9:"startLine";i:158;s:7:"endLine";i:204;s:3:"ccn";i:5;}s:8:"findByID";a:6:{s:10:"methodName";s:8:"findByID";s:9:"signature";s:42:"findByID(int $id): bool|\App\Entity\DynDNS";s:10:"visibility";s:6:"public";s:9:"startLine";i:211;s:7:"endLine";i:232;s:3:"ccn";i:3;}}}}s:8:"traitsIn";a:0:{}s:11:"functionsIn";a:0:{}s:14:"linesOfCodeFor";a:3:{s:11:"linesOfCode";i:234;s:18:"commentLinesOfCode";i:36;s:21:"nonCommentLinesOfCode";i:198;}s:15:"ignoredLinesFor";a:1:{i:0;i:14;}s:17:"executableLinesIn";a:99:{i:0;i:16;i:1;i:20;i:2;i:30;i:3;i:31;i:4;i:33;i:5;i:37;i:6;i:38;i:7;i:39;i:8;i:40;i:9;i:41;i:10;i:43;i:11;i:44;i:12;i:45;i:13;i:54;i:14;i:56;i:15;i:57;i:16;i:62;i:17;i:63;i:18;i:64;i:19;i:65;i:20;i:66;i:21;i:67;i:22;i:69;i:23;i:70;i:24;i:71;i:25;i:82;i:26;i:84;i:27;i:89;i:28;i:90;i:29;i:91;i:30;i:92;i:31;i:93;i:32;i:94;i:33;i:95;i:34;i:96;i:35;i:98;i:36;i:99;i:37;i:110;i:38;i:113;i:39;i:114;i:40;i:115;i:41;i:116;i:42;i:117;i:43;i:118;i:44;i:119;i:45;i:130;i:46;i:131;i:47;i:133;i:48;i:137;i:49;i:138;i:50;i:139;i:51;i:141;i:52;i:142;i:53;i:143;i:54;i:144;i:55;i:145;i:56;i:147;i:57;i:148;i:58;i:149;i:59;i:160;i:60;i:162;i:61;i:164;i:62;i:165;i:63;i:167;i:64;i:168;i:65;i:169;i:66;i:170;i:67;i:172;i:68;i:173;i:69;i:174;i:70;i:175;i:71;i:177;i:72;i:178;i:73;i:179;i:74;i:180;i:75;i:184;i:76;i:191;i:77;i:192;i:78;i:193;i:79;i:194;i:80;i:195;i:81;i:196;i:82;i:197;i:83;i:199;i:84;i:200;i:85;i:201;i:86;i:202;i:87;i:213;i:88;i:215;i:89;i:220;i:90;i:221;i:91;i:222;i:92;i:223;i:93;i:224;i:94;i:225;i:95;i:226;i:96;i:227;i:97;i:229;i:98;i:230;}}

View File

@ -0,0 +1 @@
a:6:{s:9:"classesIn";a:1:{s:22:"App\Controller\BindAPI";a:6:{s:4:"name";s:7:"BindAPI";s:14:"namespacedName";s:22:"App\Controller\BindAPI";s:9:"namespace";s:14:"App\Controller";s:9:"startLine";i:23;s:7:"endLine";i:93;s:7:"methods";a:3:{s:11:"__construct";a:6:{s:10:"methodName";s:11:"__construct";s:9:"signature";s:29:"__construct($verbose, $quiet)";s:10:"visibility";s:6:"public";s:9:"startLine";i:31;s:7:"endLine";i:68;s:3:"ccn";i:2;}s:10:"runCommand";a:6:{s:10:"methodName";s:10:"runCommand";s:9:"signature";s:34:"runCommand(array $arguments): void";s:10:"visibility";s:6:"public";s:9:"startLine";i:75;s:7:"endLine";i:80;s:3:"ccn";i:1;}s:13:"handleRequest";a:6:{s:10:"methodName";s:13:"handleRequest";s:9:"signature";s:54:"handleRequest(string $requestMethod, array $uri): void";s:10:"visibility";s:6:"public";s:9:"startLine";i:87;s:7:"endLine";i:92;s:3:"ccn";i:1;}}}}s:8:"traitsIn";a:0:{}s:11:"functionsIn";a:0:{}s:14:"linesOfCodeFor";a:3:{s:11:"linesOfCode";i:94;s:18:"commentLinesOfCode";i:16;s:21:"nonCommentLinesOfCode";i:78;}s:15:"ignoredLinesFor";a:1:{i:0;i:23;}s:17:"executableLinesIn";a:35:{i:0;i:5;i:1;i:34;i:2;i:35;i:3;i:36;i:4;i:38;i:5;i:39;i:6;i:40;i:7;i:41;i:8;i:42;i:9;i:44;i:10;i:46;i:11;i:47;i:12;i:48;i:13;i:51;i:14;i:52;i:15;i:53;i:16;i:54;i:17;i:55;i:18;i:56;i:19;i:57;i:20;i:58;i:21;i:59;i:22;i:60;i:23;i:61;i:24;i:62;i:25;i:63;i:26;i:64;i:27;i:65;i:28;i:67;i:29;i:77;i:30;i:78;i:31;i:79;i:32;i:89;i:33;i:90;i:34;i:91;}}

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1 @@
a:6:{s:9:"classesIn";a:1:{s:35:"App\Repository\NameserverRepository";a:6:{s:4:"name";s:20:"NameserverRepository";s:14:"namespacedName";s:35:"App\Repository\NameserverRepository";s:9:"namespace";s:14:"App\Repository";s:9:"startLine";i:14;s:7:"endLine";i:262;s:7:"methods";a:9:{s:11:"__construct";a:6:{s:10:"methodName";s:11:"__construct";s:9:"signature";s:66:"__construct(App\Controller\DatabaseConnection $databaseConnection)";s:10:"visibility";s:6:"public";s:9:"startLine";i:16;s:7:"endLine";i:19;s:3:"ccn";i:1;}s:7:"findAll";a:6:{s:10:"methodName";s:7:"findAll";s:9:"signature";s:17:"findAll(): ?array";s:10:"visibility";s:6:"public";s:9:"startLine";i:25;s:7:"endLine";i:44;s:3:"ccn";i:3;}s:9:"findFirst";a:6:{s:10:"methodName";s:9:"findFirst";s:9:"signature";s:35:"findFirst(): ?App\Entity\Nameserver";s:10:"visibility";s:6:"public";s:9:"startLine";i:50;s:7:"endLine";i:65;s:3:"ccn";i:2;}s:8:"findByID";a:6:{s:10:"methodName";s:8:"findByID";s:9:"signature";s:41:"findByID(int $id): ?App\Entity\Nameserver";s:10:"visibility";s:6:"public";s:9:"startLine";i:73;s:7:"endLine";i:92;s:3:"ccn";i:3;}s:10:"findByName";a:6:{s:10:"methodName";s:10:"findByName";s:9:"signature";s:48:"findByName(string $name): ?App\Entity\Nameserver";s:10:"visibility";s:6:"public";s:9:"startLine";i:100;s:7:"endLine";i:119;s:3:"ccn";i:3;}s:6:"insert";a:6:{s:10:"methodName";s:6:"insert";s:9:"signature";s:47:"insert(App\Entity\Nameserver $nameserver): ?int";s:10:"visibility";s:6:"public";s:9:"startLine";i:127;s:7:"endLine";i:153;s:3:"ccn";i:2;}s:6:"update";a:6:{s:10:"methodName";s:6:"update";s:9:"signature";s:51:"update(App\Entity\Nameserver $nameserver): bool|int";s:10:"visibility";s:6:"public";s:9:"startLine";i:160;s:7:"endLine";i:217;s:3:"ccn";i:7;}s:6:"delete";a:6:{s:10:"methodName";s:6:"delete";s:9:"signature";s:17:"delete($id): ?int";s:10:"visibility";s:6:"public";s:9:"startLine";i:225;s:7:"endLine";i:240;s:3:"ccn";i:2;}s:15:"getLongestEntry";a:6:{s:10:"methodName";s:15:"getLongestEntry";s:9:"signature";s:35:"getLongestEntry(string $field): int";s:10:"visibility";s:6:"public";s:9:"startLine";i:248;s:7:"endLine";i:261;s:3:"ccn";i:2;}}}}s:8:"traitsIn";a:0:{}s:11:"functionsIn";a:0:{}s:14:"linesOfCodeFor";a:3:{s:11:"linesOfCode";i:263;s:18:"commentLinesOfCode";i:39;s:21:"nonCommentLinesOfCode";i:224;}s:15:"ignoredLinesFor";a:1:{i:0;i:14;}s:17:"executableLinesIn";a:110:{i:0;i:16;i:1;i:27;i:2;i:28;i:3;i:33;i:4;i:34;i:5;i:35;i:6;i:36;i:7;i:37;i:8;i:38;i:9;i:40;i:10;i:41;i:11;i:42;i:12;i:52;i:13;i:57;i:14;i:58;i:15;i:59;i:16;i:60;i:17;i:61;i:18;i:62;i:19;i:63;i:20;i:75;i:21;i:80;i:22;i:81;i:23;i:82;i:24;i:83;i:25;i:84;i:26;i:85;i:27;i:86;i:28;i:87;i:29;i:89;i:30;i:90;i:31;i:102;i:32;i:107;i:33;i:108;i:34;i:109;i:35;i:110;i:36;i:111;i:37;i:112;i:38;i:113;i:39;i:114;i:40;i:116;i:41;i:117;i:42;i:129;i:43;i:130;i:44;i:131;i:45;i:132;i:46;i:133;i:47;i:136;i:48;i:140;i:49;i:141;i:50;i:142;i:51;i:143;i:52;i:144;i:53;i:145;i:54;i:146;i:55;i:147;i:56;i:149;i:57;i:150;i:58;i:151;i:59;i:162;i:60;i:163;i:61;i:164;i:62;i:165;i:63;i:166;i:64;i:167;i:65;i:168;i:66;i:170;i:67;i:173;i:68;i:174;i:69;i:176;i:70;i:177;i:71;i:179;i:72;i:180;i:73;i:183;i:74;i:184;i:75;i:185;i:76;i:189;i:77;i:198;i:78;i:199;i:79;i:200;i:80;i:201;i:81;i:202;i:82;i:203;i:83;i:204;i:84;i:205;i:85;i:206;i:86;i:207;i:87;i:208;i:88;i:209;i:89;i:210;i:90;i:212;i:91;i:213;i:92;i:214;i:93;i:215;i:94;i:227;i:95;i:231;i:96;i:232;i:97;i:233;i:98;i:234;i:99;i:236;i:100;i:237;i:101;i:238;i:102;i:250;i:103;i:253;i:104;i:254;i:105;i:255;i:106;i:256;i:107;i:257;i:108;i:258;i:109;i:259;}}

View File

@ -0,0 +1 @@
a:6:{s:9:"classesIn";a:1:{s:31:"App\Controller\ConfigController";a:6:{s:4:"name";s:16:"ConfigController";s:14:"namespacedName";s:31:"App\Controller\ConfigController";s:9:"namespace";s:14:"App\Controller";s:9:"startLine";i:8;s:7:"endLine";i:63;s:7:"methods";a:2:{s:11:"__construct";a:6:{s:10:"methodName";s:11:"__construct";s:9:"signature";s:51:"__construct(bool $verbose, bool $quiet, bool $test)";s:10:"visibility";s:6:"public";s:9:"startLine";i:17;s:7:"endLine";i:57;s:3:"ccn";i:7;}s:9:"getConfig";a:6:{s:10:"methodName";s:9:"getConfig";s:9:"signature";s:36:"getConfig(string $configKey): string";s:10:"visibility";s:6:"public";s:9:"startLine";i:59;s:7:"endLine";i:62;s:3:"ccn";i:1;}}}}s:8:"traitsIn";a:0:{}s:11:"functionsIn";a:0:{}s:14:"linesOfCodeFor";a:3:{s:11:"linesOfCode";i:65;s:18:"commentLinesOfCode";i:8;s:21:"nonCommentLinesOfCode";i:57;}s:15:"ignoredLinesFor";a:1:{i:0;i:8;}s:17:"executableLinesIn";a:28:{i:0;i:20;i:1;i:21;i:2;i:22;i:3;i:23;i:4;i:24;i:5;i:26;i:6;i:27;i:7;i:28;i:8;i:29;i:9;i:32;i:10;i:33;i:11;i:34;i:12;i:35;i:13;i:36;i:14;i:37;i:15;i:38;i:16;i:39;i:17;i:41;i:18;i:44;i:19;i:46;i:20;i:47;i:21;i:48;i:22;i:49;i:23;i:52;i:24;i:54;i:25;i:55;i:26;i:56;i:27;i:61;}}

View File

@ -0,0 +1 @@
a:6:{s:9:"classesIn";a:1:{s:36:"App\Controller\Commands\CommandGroup";a:6:{s:4:"name";s:12:"CommandGroup";s:14:"namespacedName";s:36:"App\Controller\Commands\CommandGroup";s:9:"namespace";s:23:"App\Controller\Commands";s:9:"startLine";i:8;s:7:"endLine";i:68;s:7:"methods";a:6:{s:11:"__construct";a:6:{s:10:"methodName";s:11:"__construct";s:9:"signature";s:46:"__construct(string $name, string $description)";s:10:"visibility";s:6:"public";s:9:"startLine";i:12;s:7:"endLine";i:15;s:3:"ccn";i:1;}s:10:"addCommand";a:6:{s:10:"methodName";s:10:"addCommand";s:9:"signature";s:91:"addCommand(App\Controller\Commands\Command $command): ?App\Controller\Commands\CommandGroup";s:10:"visibility";s:6:"public";s:9:"startLine";i:18;s:7:"endLine";i:23;s:3:"ccn";i:1;}s:7:"getName";a:6:{s:10:"methodName";s:7:"getName";s:9:"signature";s:17:"getName(): string";s:10:"visibility";s:6:"public";s:9:"startLine";i:26;s:7:"endLine";i:29;s:3:"ccn";i:1;}s:13:"printCommands";a:6:{s:10:"methodName";s:13:"printCommands";s:9:"signature";s:46:"printCommands(int $longestCommandLength): void";s:10:"visibility";s:6:"public";s:9:"startLine";i:32;s:7:"endLine";i:46;s:3:"ccn";i:4;}s:17:"findCommandByName";a:6:{s:10:"methodName";s:17:"findCommandByName";s:9:"signature";s:68:"findCommandByName(string $command): ?App\Controller\Commands\Command";s:10:"visibility";s:6:"public";s:9:"startLine";i:48;s:7:"endLine";i:56;s:3:"ccn";i:3;}s:4:"exec";a:6:{s:10:"methodName";s:4:"exec";s:9:"signature";s:30:"exec(string $subcommand): void";s:10:"visibility";s:6:"public";s:9:"startLine";i:59;s:7:"endLine";i:67;s:3:"ccn";i:2;}}}}s:8:"traitsIn";a:0:{}s:11:"functionsIn";a:0:{}s:14:"linesOfCodeFor";a:3:{s:11:"linesOfCode";i:68;s:18:"commentLinesOfCode";i:4;s:21:"nonCommentLinesOfCode";i:64;}s:15:"ignoredLinesFor";a:1:{i:0;i:8;}s:17:"executableLinesIn";a:22:{i:0;i:12;i:1;i:20;i:2;i:22;i:3;i:28;i:4;i:34;i:5;i:35;i:6;i:36;i:7;i:37;i:8;i:38;i:9;i:40;i:10;i:41;i:11;i:43;i:12;i:44;i:13;i:50;i:14;i:51;i:15;i:52;i:16;i:55;i:17;i:61;i:18;i:62;i:19;i:63;i:20;i:64;i:21;i:65;}}

View File

@ -0,0 +1 @@
a:6:{s:9:"classesIn";a:1:{s:31:"App\Repository\ApikeyRepository";a:6:{s:4:"name";s:16:"ApikeyRepository";s:14:"namespacedName";s:31:"App\Repository\ApikeyRepository";s:9:"namespace";s:14:"App\Repository";s:9:"startLine";i:15;s:7:"endLine";i:186;s:7:"methods";a:7:{s:11:"__construct";a:6:{s:10:"methodName";s:11:"__construct";s:9:"signature";s:125:"__construct(App\Controller\DatabaseConnection $databaseConnection, App\Controller\EncryptionController $encryptionController)";s:10:"visibility";s:6:"public";s:9:"startLine";i:17;s:7:"endLine";i:18;s:3:"ccn";i:1;}s:7:"findAll";a:6:{s:10:"methodName";s:7:"findAll";s:9:"signature";s:21:"findAll(): bool|array";s:10:"visibility";s:6:"public";s:9:"startLine";i:24;s:7:"endLine";i:45;s:3:"ccn";i:3;}s:8:"findByID";a:6:{s:10:"methodName";s:8:"findByID";s:9:"signature";s:42:"findByID(int $id): \App\Entity\Apikey|bool";s:10:"visibility";s:6:"public";s:9:"startLine";i:53;s:7:"endLine";i:73;s:3:"ccn";i:3;}s:12:"findByPrefix";a:6:{s:10:"methodName";s:12:"findByPrefix";s:9:"signature";s:53:"findByPrefix(string $prefix): \App\Entity\Apikey|bool";s:10:"visibility";s:6:"public";s:9:"startLine";i:81;s:7:"endLine";i:100;s:3:"ccn";i:3;}s:6:"insert";a:6:{s:10:"methodName";s:6:"insert";s:9:"signature";s:38:"insert(App\Entity\Apikey $apikey): int";s:10:"visibility";s:6:"public";s:9:"startLine";i:107;s:7:"endLine";i:129;s:3:"ccn";i:2;}s:6:"update";a:6:{s:10:"methodName";s:6:"update";s:9:"signature";s:43:"update(App\Entity\Apikey $apikey): bool|int";s:10:"visibility";s:6:"public";s:9:"startLine";i:135;s:7:"endLine";i:162;s:3:"ccn";i:3;}s:6:"delete";a:6:{s:10:"methodName";s:6:"delete";s:9:"signature";s:16:"delete($id): int";s:10:"visibility";s:6:"public";s:9:"startLine";i:170;s:7:"endLine";i:184;s:3:"ccn";i:2;}}}}s:8:"traitsIn";a:0:{}s:11:"functionsIn";a:0:{}s:14:"linesOfCodeFor";a:3:{s:11:"linesOfCode";i:187;s:18:"commentLinesOfCode";i:29;s:21:"nonCommentLinesOfCode";i:158;}s:15:"ignoredLinesFor";a:1:{i:0;i:15;}s:17:"executableLinesIn";a:71:{i:0;i:4;i:1;i:17;i:2;i:27;i:3;i:31;i:4;i:32;i:5;i:33;i:6;i:35;i:7;i:37;i:8;i:38;i:9;i:39;i:10;i:41;i:11;i:42;i:12;i:43;i:13;i:55;i:14;i:61;i:15;i:62;i:16;i:63;i:17;i:64;i:18;i:65;i:19;i:66;i:20;i:67;i:21;i:68;i:22;i:70;i:23;i:71;i:24;i:83;i:25;i:88;i:26;i:89;i:27;i:90;i:28;i:91;i:29;i:92;i:30;i:93;i:31;i:94;i:32;i:95;i:33;i:97;i:34;i:98;i:35;i:110;i:36;i:111;i:37;i:112;i:38;i:114;i:39;i:118;i:40;i:119;i:41;i:120;i:42;i:121;i:43;i:122;i:44;i:124;i:45;i:125;i:46;i:126;i:47;i:127;i:48;i:137;i:49;i:138;i:50;i:140;i:51;i:142;i:52;i:143;i:53;i:146;i:54;i:151;i:55;i:152;i:56;i:153;i:57;i:154;i:58;i:155;i:59;i:157;i:60;i:158;i:61;i:159;i:62;i:160;i:63;i:172;i:64;i:176;i:65;i:177;i:66;i:178;i:67;i:179;i:68;i:180;i:69;i:181;i:70;i:182;}}

View File

@ -0,0 +1 @@
a:6:{s:9:"classesIn";a:1:{s:28:"App\Controller\ApiController";a:6:{s:4:"name";s:13:"ApiController";s:14:"namespacedName";s:28:"App\Controller\ApiController";s:9:"namespace";s:14:"App\Controller";s:9:"startLine";i:13;s:7:"endLine";i:146;s:7:"methods";a:2:{s:11:"sendCommand";a:6:{s:10:"methodName";s:11:"sendCommand";s:9:"signature";s:141:"sendCommand(string $requestType, string $serverName, int $versionIP, string $apiKey, string $command, string $serverType, array $body): array";s:10:"visibility";s:6:"public";s:9:"startLine";i:27;s:7:"endLine";i:111;s:3:"ccn";i:14;}s:15:"fileGetContents";a:6:{s:10:"methodName";s:15:"fileGetContents";s:9:"signature";s:52:"fileGetContents(string $url, int $versionIP): ?array";s:10:"visibility";s:6:"public";s:9:"startLine";i:113;s:7:"endLine";i:145;s:3:"ccn";i:2;}}}}s:8:"traitsIn";a:0:{}s:11:"functionsIn";a:0:{}s:14:"linesOfCodeFor";a:3:{s:11:"linesOfCode";i:147;s:18:"commentLinesOfCode";i:14;s:21:"nonCommentLinesOfCode";i:133;}s:15:"ignoredLinesFor";a:1:{i:0;i:13;}s:17:"executableLinesIn";a:77:{i:0;i:7;i:1;i:27;i:2;i:29;i:3;i:30;i:4;i:32;i:5;i:33;i:6;i:34;i:7;i:35;i:8;i:37;i:9;i:38;i:10;i:41;i:11;i:42;i:12;i:43;i:13;i:45;i:14;i:46;i:15;i:47;i:16;i:48;i:17;i:51;i:18;i:53;i:19;i:54;i:20;i:55;i:21;i:57;i:22;i:58;i:23;i:59;i:24;i:62;i:25;i:64;i:26;i:65;i:27;i:67;i:28;i:68;i:29;i:69;i:30;i:70;i:31;i:71;i:32;i:72;i:33;i:73;i:34;i:74;i:35;i:76;i:36;i:77;i:37;i:79;i:38;i:80;i:39;i:81;i:40;i:82;i:41;i:83;i:42;i:84;i:43;i:85;i:44;i:86;i:45;i:87;i:46;i:88;i:47;i:89;i:48;i:90;i:49;i:91;i:50;i:92;i:51;i:93;i:52;i:94;i:53;i:96;i:54;i:97;i:55;i:98;i:56;i:101;i:57;i:102;i:58;i:104;i:59;i:106;i:60;i:109;i:61;i:115;i:62;i:117;i:63;i:127;i:64;i:128;i:65;i:129;i:66;i:130;i:67;i:133;i:68;i:134;i:69;i:135;i:70;i:136;i:71;i:137;i:72;i:138;i:73;i:140;i:74;i:141;i:75;i:142;i:76;i:144;}}

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1 @@
a:6:{s:9:"classesIn";a:1:{s:33:"App\Controller\DatabaseConnection";a:6:{s:4:"name";s:18:"DatabaseConnection";s:14:"namespacedName";s:33:"App\Controller\DatabaseConnection";s:9:"namespace";s:14:"App\Controller";s:9:"startLine";i:14;s:7:"endLine";i:149;s:7:"methods";a:3:{s:11:"__construct";a:6:{s:10:"methodName";s:11:"__construct";s:9:"signature";s:62:"__construct(App\Controller\ConfigController $configController)";s:10:"visibility";s:6:"public";s:9:"startLine";i:25;s:7:"endLine";i:127;s:3:"ccn";i:5;}s:16:"generatePassword";a:6:{s:10:"methodName";s:16:"generatePassword";s:9:"signature";s:37:"generatePassword(int $length): string";s:10:"visibility";s:6:"public";s:9:"startLine";i:135;s:7:"endLine";i:140;s:3:"ccn";i:1;}s:13:"getConnection";a:6:{s:10:"methodName";s:13:"getConnection";s:9:"signature";s:20:"getConnection(): PDO";s:10:"visibility";s:6:"public";s:9:"startLine";i:145;s:7:"endLine";i:148;s:3:"ccn";i:1;}}}}s:8:"traitsIn";a:0:{}s:11:"functionsIn";a:0:{}s:14:"linesOfCodeFor";a:3:{s:11:"linesOfCode";i:150;s:18:"commentLinesOfCode";i:13;s:21:"nonCommentLinesOfCode";i:137;}s:15:"ignoredLinesFor";a:1:{i:0;i:14;}s:17:"executableLinesIn";a:50:{i:0;i:5;i:1;i:25;i:2;i:27;i:3;i:28;i:4;i:29;i:5;i:30;i:6;i:31;i:7;i:33;i:8;i:34;i:9;i:39;i:10;i:41;i:11;i:42;i:12;i:44;i:13;i:45;i:14;i:46;i:15;i:47;i:16;i:49;i:17;i:50;i:18;i:51;i:19;i:59;i:20;i:60;i:21;i:62;i:22;i:69;i:23;i:70;i:24;i:72;i:25;i:81;i:26;i:82;i:27;i:84;i:28;i:93;i:29;i:94;i:30;i:96;i:31;i:106;i:32;i:107;i:33;i:109;i:34;i:111;i:35;i:114;i:36;i:115;i:37;i:116;i:38;i:117;i:39;i:118;i:40;i:119;i:41;i:120;i:42;i:121;i:43;i:122;i:44;i:123;i:45;i:124;i:46;i:137;i:47;i:138;i:48;i:139;i:49;i:147;}}

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1 @@
a:6:{s:9:"classesIn";a:1:{s:35:"App\Controller\EncryptionController";a:6:{s:4:"name";s:20:"EncryptionController";s:14:"namespacedName";s:35:"App\Controller\EncryptionController";s:9:"namespace";s:14:"App\Controller";s:9:"startLine";i:10;s:7:"endLine";i:71;s:7:"methods";a:2:{s:11:"safeEncrypt";a:6:{s:10:"methodName";s:11:"safeEncrypt";s:9:"signature";s:49:"safeEncrypt(string $message, string $key): string";s:10:"visibility";s:6:"public";s:9:"startLine";i:19;s:7:"endLine";i:33;s:3:"ccn";i:2;}s:11:"safeDecrypt";a:6:{s:10:"methodName";s:11:"safeDecrypt";s:9:"signature";s:51:"safeDecrypt(string $encrypted, string $key): string";s:10:"visibility";s:6:"public";s:9:"startLine";i:42;s:7:"endLine";i:69;s:3:"ccn";i:5;}}}}s:8:"traitsIn";a:0:{}s:11:"functionsIn";a:0:{}s:14:"linesOfCodeFor";a:3:{s:11:"linesOfCode";i:71;s:18:"commentLinesOfCode";i:17;s:21:"nonCommentLinesOfCode";i:54;}s:15:"ignoredLinesFor";a:1:{i:0;i:10;}s:17:"executableLinesIn";a:27:{i:0;i:21;i:1;i:22;i:2;i:23;i:3;i:25;i:4;i:26;i:5;i:27;i:6;i:28;i:7;i:29;i:8;i:30;i:9;i:31;i:10;i:44;i:11;i:45;i:12;i:47;i:13;i:48;i:14;i:49;i:15;i:52;i:16;i:53;i:17;i:56;i:18;i:57;i:19;i:59;i:20;i:60;i:21;i:61;i:22;i:63;i:23;i:64;i:24;i:65;i:25;i:66;i:26;i:67;}}

View File

@ -0,0 +1 @@
a:6:{s:9:"classesIn";a:1:{s:45:"App\Controller\Commands\CommandGroupContainer";a:6:{s:4:"name";s:21:"CommandGroupContainer";s:14:"namespacedName";s:45:"App\Controller\Commands\CommandGroupContainer";s:9:"namespace";s:23:"App\Controller\Commands";s:9:"startLine";i:8;s:7:"endLine";i:73;s:7:"methods";a:5:{s:15:"addCommandGroup";a:6:{s:10:"methodName";s:15:"addCommandGroup";s:9:"signature";s:114:"addCommandGroup(App\Controller\Commands\CommandGroup $commandGroup): App\Controller\Commands\CommandGroupContainer";s:10:"visibility";s:6:"public";s:9:"startLine";i:12;s:7:"endLine";i:17;s:3:"ccn";i:1;}s:13:"printCommands";a:6:{s:10:"methodName";s:13:"printCommands";s:9:"signature";s:21:"printCommands(): void";s:10:"visibility";s:6:"public";s:9:"startLine";i:22;s:7:"endLine";i:28;s:3:"ccn";i:2;}s:23:"getLongestCommandLength";a:6:{s:10:"methodName";s:23:"getLongestCommandLength";s:9:"signature";s:30:"getLongestCommandLength(): int";s:10:"visibility";s:6:"public";s:9:"startLine";i:34;s:7:"endLine";i:46;s:3:"ccn";i:3;}s:15:"findGroupByName";a:6:{s:10:"methodName";s:15:"findGroupByName";s:9:"signature";s:71:"findGroupByName(string $command): ?App\Controller\Commands\CommandGroup";s:10:"visibility";s:7:"private";s:9:"startLine";i:53;s:7:"endLine";i:61;s:3:"ccn";i:3;}s:3:"run";a:6:{s:10:"methodName";s:3:"run";s:9:"signature";s:46:"run(string $command, string $subcommand): void";s:10:"visibility";s:6:"public";s:9:"startLine";i:64;s:7:"endLine";i:72;s:3:"ccn";i:2;}}}}s:8:"traitsIn";a:0:{}s:11:"functionsIn";a:0:{}s:14:"linesOfCodeFor";a:3:{s:11:"linesOfCode";i:73;s:18:"commentLinesOfCode";i:13;s:21:"nonCommentLinesOfCode";i:60;}s:15:"ignoredLinesFor";a:1:{i:0;i:8;}s:17:"executableLinesIn";a:20:{i:0;i:14;i:1;i:16;i:2;i:24;i:3;i:25;i:4;i:26;i:5;i:36;i:6;i:38;i:7;i:39;i:8;i:40;i:9;i:41;i:10;i:45;i:11;i:55;i:12;i:56;i:13;i:57;i:14;i:60;i:15;i:66;i:16;i:67;i:17;i:68;i:18;i:69;i:19;i:70;}}

View File

@ -0,0 +1 @@
a:6:{s:9:"classesIn";a:1:{s:30:"App\Repository\PanelRepository";a:6:{s:4:"name";s:15:"PanelRepository";s:14:"namespacedName";s:30:"App\Repository\PanelRepository";s:9:"namespace";s:14:"App\Repository";s:9:"startLine";i:13;s:7:"endLine";i:272;s:7:"methods";a:10:{s:11:"__construct";a:6:{s:10:"methodName";s:11:"__construct";s:9:"signature";s:66:"__construct(App\Controller\DatabaseConnection $databaseConnection)";s:10:"visibility";s:6:"public";s:9:"startLine";i:15;s:7:"endLine";i:18;s:3:"ccn";i:1;}s:8:"findSelf";a:6:{s:10:"methodName";s:8:"findSelf";s:9:"signature";s:18:"findSelf(): ?array";s:10:"visibility";s:6:"public";s:9:"startLine";i:23;s:7:"endLine";i:39;s:3:"ccn";i:2;}s:7:"findAll";a:6:{s:10:"methodName";s:7:"findAll";s:9:"signature";s:17:"findAll(): ?array";s:10:"visibility";s:6:"public";s:9:"startLine";i:42;s:7:"endLine";i:61;s:3:"ccn";i:3;}s:8:"findByID";a:6:{s:10:"methodName";s:8:"findByID";s:9:"signature";s:36:"findByID(int $id): ?App\Entity\Panel";s:10:"visibility";s:6:"public";s:9:"startLine";i:69;s:7:"endLine";i:88;s:3:"ccn";i:3;}s:10:"findByName";a:6:{s:10:"methodName";s:10:"findByName";s:9:"signature";s:43:"findByName(string $name): ?App\Entity\Panel";s:10:"visibility";s:6:"public";s:9:"startLine";i:96;s:7:"endLine";i:115;s:3:"ccn";i:3;}s:6:"insert";a:6:{s:10:"methodName";s:6:"insert";s:9:"signature";s:37:"insert(App\Entity\Panel $panel): ?int";s:10:"visibility";s:6:"public";s:9:"startLine";i:122;s:7:"endLine";i:149;s:3:"ccn";i:2;}s:6:"update";a:6:{s:10:"methodName";s:6:"update";s:9:"signature";s:37:"update(App\Entity\Panel $panel): ?int";s:10:"visibility";s:6:"public";s:9:"startLine";i:156;s:7:"endLine";i:215;s:3:"ccn";i:7;}s:6:"delete";a:6:{s:10:"methodName";s:6:"delete";s:9:"signature";s:17:"delete($id): ?int";s:10:"visibility";s:6:"public";s:9:"startLine";i:223;s:7:"endLine";i:238;s:3:"ccn";i:2;}s:15:"getLongestEntry";a:6:{s:10:"methodName";s:15:"getLongestEntry";s:9:"signature";s:36:"getLongestEntry(string $field): ?int";s:10:"visibility";s:6:"public";s:9:"startLine";i:246;s:7:"endLine";i:259;s:3:"ccn";i:2;}s:7:"getSelf";a:6:{s:10:"methodName";s:7:"getSelf";s:9:"signature";s:28:"getSelf(): ?App\Entity\Panel";s:10:"visibility";s:6:"public";s:9:"startLine";i:262;s:7:"endLine";i:271;s:3:"ccn";i:3;}}}}s:8:"traitsIn";a:0:{}s:11:"functionsIn";a:0:{}s:14:"linesOfCodeFor";a:3:{s:11:"linesOfCode";i:273;s:18:"commentLinesOfCode";i:35;s:21:"nonCommentLinesOfCode";i:238;}s:15:"ignoredLinesFor";a:1:{i:0;i:13;}s:17:"executableLinesIn";a:116:{i:0;i:15;i:1;i:25;i:2;i:30;i:3;i:32;i:4;i:33;i:5;i:34;i:6;i:35;i:7;i:36;i:8;i:38;i:9;i:44;i:10;i:45;i:11;i:50;i:12;i:51;i:13;i:52;i:14;i:53;i:15;i:54;i:16;i:55;i:17;i:57;i:18;i:58;i:19;i:59;i:20;i:71;i:21;i:76;i:22;i:77;i:23;i:78;i:24;i:79;i:25;i:80;i:26;i:81;i:27;i:82;i:28;i:83;i:29;i:85;i:30;i:86;i:31;i:98;i:32;i:103;i:33;i:104;i:34;i:105;i:35;i:106;i:36;i:107;i:37;i:108;i:38;i:109;i:39;i:110;i:40;i:112;i:41;i:113;i:42;i:124;i:43;i:125;i:44;i:126;i:45;i:127;i:46;i:128;i:47;i:129;i:48;i:131;i:49;i:135;i:50;i:136;i:51;i:137;i:52;i:138;i:53;i:139;i:54;i:140;i:55;i:141;i:56;i:142;i:57;i:143;i:58;i:145;i:59;i:146;i:60;i:147;i:61;i:158;i:62;i:159;i:63;i:160;i:64;i:161;i:65;i:162;i:66;i:163;i:67;i:164;i:68;i:166;i:69;i:169;i:70;i:170;i:71;i:172;i:72;i:173;i:73;i:175;i:74;i:176;i:75;i:179;i:76;i:180;i:77;i:181;i:78;i:184;i:79;i:185;i:80;i:189;i:81;i:199;i:82;i:200;i:83;i:201;i:84;i:202;i:85;i:203;i:86;i:204;i:87;i:205;i:88;i:206;i:89;i:207;i:90;i:208;i:91;i:210;i:92;i:211;i:93;i:212;i:94;i:213;i:95;i:225;i:96;i:229;i:97;i:230;i:98;i:231;i:99;i:232;i:100;i:234;i:101;i:235;i:102;i:236;i:103;i:248;i:104;i:251;i:105;i:252;i:106;i:253;i:107;i:254;i:108;i:255;i:109;i:256;i:110;i:257;i:111;i:264;i:112;i:265;i:113;i:266;i:114;i:267;i:115;i:270;}}

View File

@ -0,0 +1 @@
a:6:{s:9:"classesIn";a:1:{s:17:"App\Entity\Domain";a:6:{s:4:"name";s:6:"Domain";s:14:"namespacedName";s:17:"App\Entity\Domain";s:9:"namespace";s:10:"App\Entity";s:9:"startLine";i:8;s:7:"endLine";i:66;s:7:"methods";a:7:{s:11:"__construct";a:6:{s:10:"methodName";s:11:"__construct";s:9:"signature";s:49:"__construct(string $name, string $panel, int $id)";s:10:"visibility";s:6:"public";s:9:"startLine";i:13;s:7:"endLine";i:14;s:3:"ccn";i:1;}s:8:"getPanel";a:6:{s:10:"methodName";s:8:"getPanel";s:9:"signature";s:18:"getPanel(): string";s:10:"visibility";s:6:"public";s:9:"startLine";i:19;s:7:"endLine";i:22;s:3:"ccn";i:1;}s:8:"setPanel";a:6:{s:10:"methodName";s:8:"setPanel";s:9:"signature";s:29:"setPanel(string $panel): void";s:10:"visibility";s:6:"public";s:9:"startLine";i:27;s:7:"endLine";i:30;s:3:"ccn";i:1;}s:7:"getName";a:6:{s:10:"methodName";s:7:"getName";s:9:"signature";s:17:"getName(): string";s:10:"visibility";s:6:"public";s:9:"startLine";i:36;s:7:"endLine";i:39;s:3:"ccn";i:1;}s:7:"setName";a:6:{s:10:"methodName";s:7:"setName";s:9:"signature";s:27:"setName(string $name): void";s:10:"visibility";s:6:"public";s:9:"startLine";i:44;s:7:"endLine";i:47;s:3:"ccn";i:1;}s:5:"getId";a:6:{s:10:"methodName";s:5:"getId";s:9:"signature";s:12:"getId(): int";s:10:"visibility";s:6:"public";s:9:"startLine";i:53;s:7:"endLine";i:56;s:3:"ccn";i:1;}s:5:"setId";a:6:{s:10:"methodName";s:5:"setId";s:9:"signature";s:20:"setId(int $id): void";s:10:"visibility";s:6:"public";s:9:"startLine";i:61;s:7:"endLine";i:64;s:3:"ccn";i:1;}}}}s:8:"traitsIn";a:0:{}s:11:"functionsIn";a:0:{}s:14:"linesOfCodeFor";a:3:{s:11:"linesOfCode";i:66;s:18:"commentLinesOfCode";i:23;s:21:"nonCommentLinesOfCode";i:43;}s:15:"ignoredLinesFor";a:1:{i:0;i:8;}s:17:"executableLinesIn";a:7:{i:0;i:13;i:1;i:21;i:2;i:29;i:3;i:38;i:4;i:46;i:5;i:55;i:6;i:63;}}

View File

@ -0,0 +1 @@
a:6:{s:9:"classesIn";a:1:{s:33:"App\Controller\DatabaseConnection";a:6:{s:4:"name";s:18:"DatabaseConnection";s:14:"namespacedName";s:33:"App\Controller\DatabaseConnection";s:9:"namespace";s:14:"App\Controller";s:9:"startLine";i:14;s:7:"endLine";i:149;s:7:"methods";a:3:{s:11:"__construct";a:6:{s:10:"methodName";s:11:"__construct";s:9:"signature";s:62:"__construct(App\Controller\ConfigController $configController)";s:10:"visibility";s:6:"public";s:9:"startLine";i:25;s:7:"endLine";i:127;s:3:"ccn";i:5;}s:16:"generatePassword";a:6:{s:10:"methodName";s:16:"generatePassword";s:9:"signature";s:37:"generatePassword(int $length): string";s:10:"visibility";s:6:"public";s:9:"startLine";i:135;s:7:"endLine";i:140;s:3:"ccn";i:1;}s:13:"getConnection";a:6:{s:10:"methodName";s:13:"getConnection";s:9:"signature";s:20:"getConnection(): PDO";s:10:"visibility";s:6:"public";s:9:"startLine";i:145;s:7:"endLine";i:148;s:3:"ccn";i:1;}}}}s:8:"traitsIn";a:0:{}s:11:"functionsIn";a:0:{}s:14:"linesOfCodeFor";a:3:{s:11:"linesOfCode";i:150;s:18:"commentLinesOfCode";i:14;s:21:"nonCommentLinesOfCode";i:136;}s:15:"ignoredLinesFor";a:1:{i:0;i:14;}s:17:"executableLinesIn";a:49:{i:0;i:25;i:1;i:27;i:2;i:28;i:3;i:29;i:4;i:30;i:5;i:31;i:6;i:33;i:7;i:34;i:8;i:39;i:9;i:41;i:10;i:42;i:11;i:44;i:12;i:45;i:13;i:46;i:14;i:47;i:15;i:49;i:16;i:50;i:17;i:51;i:18;i:59;i:19;i:60;i:20;i:62;i:21;i:69;i:22;i:70;i:23;i:72;i:24;i:81;i:25;i:82;i:26;i:84;i:27;i:93;i:28;i:94;i:29;i:96;i:30;i:106;i:31;i:107;i:32;i:109;i:33;i:111;i:34;i:114;i:35;i:115;i:36;i:116;i:37;i:117;i:38;i:118;i:39;i:119;i:40;i:120;i:41;i:121;i:42;i:122;i:43;i:123;i:44;i:124;i:45;i:137;i:46;i:138;i:47;i:139;i:48;i:147;}}

View File

@ -0,0 +1 @@
a:6:{s:9:"classesIn";a:1:{s:31:"App\Controller\DomainController";a:6:{s:4:"name";s:16:"DomainController";s:14:"namespacedName";s:31:"App\Controller\DomainController";s:9:"namespace";s:14:"App\Controller";s:9:"startLine";i:18;s:7:"endLine";i:330;s:7:"methods";a:9:{s:11:"__construct";a:6:{s:10:"methodName";s:11:"__construct";s:9:"signature";s:292:"__construct(App\Repository\NameserverRepository $nameserverRepository, App\Controller\ApiController $checkController, App\Repository\DomainRepository $domainRepository, App\Repository\PanelRepository $panelRepository, App\Controller\ConfigController $configController, Monolog\Logger $logger)";s:10:"visibility";s:6:"public";s:9:"startLine";i:26;s:7:"endLine";i:38;s:3:"ccn";i:1;}s:17:"createIncludeFile";a:6:{s:10:"methodName";s:17:"createIncludeFile";s:9:"signature";s:25:"createIncludeFile(): void";s:10:"visibility";s:6:"public";s:9:"startLine";i:41;s:7:"endLine";i:66;s:3:"ccn";i:5;}s:16:"updateSlaveZones";a:6:{s:10:"methodName";s:16:"updateSlaveZones";s:9:"signature";s:24:"updateSlaveZones(): void";s:10:"visibility";s:6:"public";s:9:"startLine";i:69;s:7:"endLine";i:88;s:3:"ccn";i:4;}s:19:"deleteOnNameservers";a:6:{s:10:"methodName";s:19:"deleteOnNameservers";s:9:"signature";s:52:"deleteOnNameservers(App\Entity\Domain $domain): void";s:10:"visibility";s:6:"public";s:9:"startLine";i:91;s:7:"endLine";i:120;s:3:"ccn";i:3;}s:10:"deleteZone";a:6:{s:10:"methodName";s:10:"deleteZone";s:9:"signature";s:43:"deleteZone(App\Entity\Domain $domain): void";s:10:"visibility";s:6:"public";s:9:"startLine";i:128;s:7:"endLine";i:138;s:3:"ccn";i:2;}s:16:"checkPermissions";a:6:{s:10:"methodName";s:16:"checkPermissions";s:9:"signature";s:44:"checkPermissions(bool $disableVerbose): bool";s:10:"visibility";s:6:"public";s:9:"startLine";i:144;s:7:"endLine";i:230;s:3:"ccn";i:22;}s:12:"checkDomains";a:6:{s:10:"methodName";s:12:"checkDomains";s:9:"signature";s:20:"checkDomains(): void";s:10:"visibility";s:6:"public";s:9:"startLine";i:236;s:7:"endLine";i:278;s:3:"ccn";i:7;}s:19:"createSlaveZoneFile";a:6:{s:10:"methodName";s:19:"createSlaveZoneFile";s:9:"signature";s:52:"createSlaveZoneFile(App\Entity\Domain $domain): void";s:10:"visibility";s:6:"public";s:9:"startLine";i:286;s:7:"endLine";i:318;s:3:"ccn";i:6;}s:12:"isMasterZone";a:6:{s:10:"methodName";s:12:"isMasterZone";s:9:"signature";s:45:"isMasterZone(App\Entity\Domain $domain): bool";s:10:"visibility";s:6:"public";s:9:"startLine";i:321;s:7:"endLine";i:328;s:3:"ccn";i:2;}}}}s:8:"traitsIn";a:0:{}s:11:"functionsIn";a:0:{}s:14:"linesOfCodeFor";a:3:{s:11:"linesOfCode";i:331;s:18:"commentLinesOfCode";i:22;s:21:"nonCommentLinesOfCode";i:309;}s:15:"ignoredLinesFor";a:1:{i:0;i:18;}s:17:"executableLinesIn";a:161:{i:0;i:11;i:1;i:26;i:2;i:34;i:3;i:35;i:4;i:36;i:5;i:37;i:6;i:43;i:7;i:45;i:8;i:47;i:9;i:48;i:10;i:49;i:11;i:50;i:12;i:53;i:13;i:55;i:14;i:56;i:15;i:57;i:16;i:58;i:17;i:59;i:18;i:61;i:19;i:62;i:20;i:65;i:21;i:71;i:22;i:73;i:23;i:74;i:24;i:75;i:25;i:78;i:26;i:80;i:27;i:81;i:28;i:82;i:29;i:84;i:30;i:87;i:31;i:93;i:32;i:95;i:33;i:96;i:34;i:97;i:35;i:98;i:36;i:100;i:37;i:101;i:38;i:103;i:39;i:105;i:40;i:109;i:41;i:110;i:42;i:112;i:43;i:114;i:44;i:130;i:45;i:132;i:46;i:133;i:47;i:134;i:48;i:136;i:49;i:137;i:50;i:146;i:51;i:148;i:52;i:149;i:53;i:150;i:54;i:151;i:55;i:154;i:56;i:156;i:57;i:157;i:58;i:159;i:59;i:160;i:60;i:161;i:61;i:163;i:62;i:164;i:63;i:165;i:64;i:166;i:65;i:168;i:66;i:169;i:67;i:170;i:68;i:171;i:69;i:172;i:70;i:174;i:71;i:175;i:72;i:176;i:73;i:177;i:74;i:180;i:75;i:181;i:76;i:183;i:77;i:184;i:78;i:185;i:79;i:186;i:80;i:188;i:81;i:189;i:82;i:190;i:83;i:191;i:84;i:194;i:85;i:195;i:86;i:197;i:87;i:198;i:88;i:199;i:89;i:200;i:90;i:201;i:91;i:203;i:92;i:204;i:93;i:205;i:94;i:208;i:95;i:209;i:96;i:210;i:97;i:211;i:98;i:214;i:99;i:215;i:100;i:217;i:101;i:218;i:102;i:219;i:103;i:220;i:104;i:222;i:105;i:223;i:106;i:224;i:107;i:225;i:108;i:229;i:109;i:238;i:110;i:239;i:111;i:240;i:112;i:242;i:113;i:243;i:114;i:244;i:115;i:246;i:116;i:247;i:117;i:248;i:118;i:249;i:119;i:251;i:120;i:253;i:121;i:254;i:122;i:255;i:123;i:256;i:124;i:257;i:125;i:258;i:126;i:259;i:127;i:260;i:128;i:261;i:129;i:264;i:130;i:266;i:131;i:267;i:132;i:268;i:133;i:271;i:134;i:272;i:135;i:275;i:136;i:288;i:137;i:289;i:138;i:292;i:139;i:294;i:140;i:297;i:141;i:298;i:142;i:299;i:143;i:300;i:144;i:301;i:145;i:303;i:146;i:304;i:147;i:305;i:148;i:306;i:149;i:307;i:150;i:308;i:151;i:309;i:152;i:310;i:153;i:312;i:154;i:313;i:155;i:315;i:156;i:316;i:157;i:323;i:158;i:324;i:159;i:325;i:160;i:326;}}

View File

@ -0,0 +1 @@
a:6:{s:9:"classesIn";a:0:{}s:8:"traitsIn";a:0:{}s:11:"functionsIn";a:0:{}s:14:"linesOfCodeFor";a:3:{s:11:"linesOfCode";i:2;s:18:"commentLinesOfCode";i:0;s:21:"nonCommentLinesOfCode";i:2;}s:15:"ignoredLinesFor";a:0:{}s:17:"executableLinesIn";a:0:{}}

View File

@ -0,0 +1 @@
a:6:{s:9:"classesIn";a:1:{s:31:"App\Controller\Commands\Command";a:6:{s:4:"name";s:7:"Command";s:14:"namespacedName";s:31:"App\Controller\Commands\Command";s:9:"namespace";s:23:"App\Controller\Commands";s:9:"startLine";i:10;s:7:"endLine";i:68;s:7:"methods";a:7:{s:11:"__construct";a:6:{s:10:"methodName";s:11:"__construct";s:9:"signature";s:120:"__construct(string $name, Closure $callback, array $mandatoryParameters, array $optionalParameters, string $description)";s:10:"visibility";s:6:"public";s:9:"startLine";i:12;s:7:"endLine";i:21;s:3:"ccn";i:1;}s:7:"getName";a:6:{s:10:"methodName";s:7:"getName";s:9:"signature";s:17:"getName(): string";s:10:"visibility";s:6:"public";s:9:"startLine";i:27;s:7:"endLine";i:30;s:3:"ccn";i:1;}s:22:"getMandatoryParameters";a:6:{s:10:"methodName";s:22:"getMandatoryParameters";s:9:"signature";s:31:"getMandatoryParameters(): array";s:10:"visibility";s:6:"public";s:9:"startLine";i:35;s:7:"endLine";i:38;s:3:"ccn";i:1;}s:21:"getOptionalParameters";a:6:{s:10:"methodName";s:21:"getOptionalParameters";s:9:"signature";s:30:"getOptionalParameters(): array";s:10:"visibility";s:6:"public";s:9:"startLine";i:43;s:7:"endLine";i:46;s:3:"ccn";i:1;}s:14:"getDescription";a:6:{s:10:"methodName";s:14:"getDescription";s:9:"signature";s:25:"getDescription(): ?string";s:10:"visibility";s:6:"public";s:9:"startLine";i:51;s:7:"endLine";i:54;s:3:"ccn";i:1;}s:11:"getCallback";a:6:{s:10:"methodName";s:11:"getCallback";s:9:"signature";s:22:"getCallback(): Closure";s:10:"visibility";s:6:"public";s:9:"startLine";i:59;s:7:"endLine";i:62;s:3:"ccn";i:1;}s:4:"exec";a:6:{s:10:"methodName";s:4:"exec";s:9:"signature";s:12:"exec(): void";s:10:"visibility";s:6:"public";s:9:"startLine";i:64;s:7:"endLine";i:67;s:3:"ccn";i:1;}}}}s:8:"traitsIn";a:0:{}s:11:"functionsIn";a:0:{}s:14:"linesOfCodeFor";a:3:{s:11:"linesOfCode";i:68;s:18:"commentLinesOfCode";i:19;s:21:"nonCommentLinesOfCode";i:49;}s:15:"ignoredLinesFor";a:1:{i:0;i:10;}s:17:"executableLinesIn";a:9:{i:0;i:12;i:1;i:15;i:2;i:16;i:3;i:29;i:4;i:37;i:5;i:45;i:6;i:53;i:7;i:61;i:8;i:66;}}

View File

@ -0,0 +1 @@
a:6:{s:9:"classesIn";a:1:{s:31:"App\Repository\DomainRepository";a:6:{s:4:"name";s:16:"DomainRepository";s:14:"namespacedName";s:31:"App\Repository\DomainRepository";s:9:"namespace";s:14:"App\Repository";s:9:"startLine";i:15;s:7:"endLine";i:260;s:7:"methods";a:9:{s:11:"__construct";a:6:{s:10:"methodName";s:11:"__construct";s:9:"signature";s:141:"__construct(App\Controller\DatabaseConnection $databaseConnection, App\Controller\ConfigController $configController, Monolog\Logger $logger)";s:10:"visibility";s:6:"public";s:9:"startLine";i:17;s:7:"endLine";i:24;s:3:"ccn";i:1;}s:7:"findAll";a:6:{s:10:"methodName";s:7:"findAll";s:9:"signature";s:16:"findAll(): array";s:10:"visibility";s:6:"public";s:9:"startLine";i:30;s:7:"endLine";i:51;s:3:"ccn";i:3;}s:8:"findByID";a:6:{s:10:"methodName";s:8:"findByID";s:9:"signature";s:42:"findByID(int $id): bool|\App\Entity\Domain";s:10:"visibility";s:6:"public";s:9:"startLine";i:59;s:7:"endLine";i:81;s:3:"ccn";i:3;}s:10:"findByName";a:6:{s:10:"methodName";s:10:"findByName";s:9:"signature";s:49:"findByName(string $name): \App\Entity\Domain|bool";s:10:"visibility";s:6:"public";s:9:"startLine";i:89;s:7:"endLine";i:110;s:3:"ccn";i:3;}s:10:"findByHost";a:6:{s:10:"methodName";s:10:"findByHost";s:9:"signature";s:49:"findByHost(string $host): \App\Entity\Domain|bool";s:10:"visibility";s:6:"public";s:9:"startLine";i:118;s:7:"endLine";i:137;s:3:"ccn";i:5;}s:6:"insert";a:6:{s:10:"methodName";s:6:"insert";s:9:"signature";s:46:"insert(App\Entity\Domain $domain): bool|string";s:10:"visibility";s:6:"public";s:9:"startLine";i:145;s:7:"endLine";i:166;s:3:"ccn";i:2;}s:6:"update";a:6:{s:10:"methodName";s:6:"update";s:9:"signature";s:43:"update(App\Entity\Domain $domain): bool|int";s:10:"visibility";s:6:"public";s:9:"startLine";i:174;s:7:"endLine";i:211;s:3:"ccn";i:4;}s:6:"delete";a:6:{s:10:"methodName";s:6:"delete";s:9:"signature";s:38:"delete(App\Entity\Domain $domain): int";s:10:"visibility";s:6:"public";s:9:"startLine";i:219;s:7:"endLine";i:238;s:3:"ccn";i:2;}s:15:"getLongestEntry";a:6:{s:10:"methodName";s:15:"getLongestEntry";s:9:"signature";s:35:"getLongestEntry(string $field): int";s:10:"visibility";s:6:"public";s:9:"startLine";i:246;s:7:"endLine";i:259;s:3:"ccn";i:2;}}}}s:8:"traitsIn";a:0:{}s:11:"functionsIn";a:0:{}s:14:"linesOfCodeFor";a:3:{s:11:"linesOfCode";i:261;s:18:"commentLinesOfCode";i:41;s:21:"nonCommentLinesOfCode";i:220;}s:15:"ignoredLinesFor";a:1:{i:0;i:15;}s:17:"executableLinesIn";a:105:{i:0;i:17;i:1;i:22;i:2;i:32;i:3;i:34;i:4;i:35;i:5;i:40;i:6;i:41;i:7;i:42;i:8;i:43;i:9;i:44;i:10;i:45;i:11;i:47;i:12;i:48;i:13;i:49;i:14;i:61;i:15;i:63;i:16;i:68;i:17;i:69;i:18;i:70;i:19;i:71;i:20;i:72;i:21;i:74;i:22;i:75;i:23;i:76;i:24;i:78;i:25;i:79;i:26;i:91;i:27;i:93;i:28;i:98;i:29;i:99;i:30;i:100;i:31;i:101;i:32;i:102;i:33;i:103;i:34;i:104;i:35;i:105;i:36;i:107;i:37;i:108;i:38;i:120;i:39;i:122;i:40;i:123;i:41;i:124;i:42;i:125;i:43;i:126;i:44;i:128;i:45;i:129;i:46;i:132;i:47;i:133;i:48;i:134;i:49;i:135;i:50;i:147;i:51;i:148;i:52;i:150;i:53;i:154;i:54;i:155;i:55;i:156;i:56;i:157;i:57;i:158;i:58;i:159;i:59;i:160;i:60;i:162;i:61;i:163;i:62;i:164;i:63;i:176;i:64;i:177;i:65;i:179;i:66;i:180;i:67;i:182;i:68;i:183;i:69;i:184;i:70;i:185;i:71;i:187;i:72;i:188;i:73;i:189;i:74;i:190;i:75;i:193;i:76;i:199;i:77;i:200;i:78;i:201;i:79;i:202;i:80;i:203;i:81;i:204;i:82;i:206;i:83;i:207;i:84;i:208;i:85;i:209;i:86;i:221;i:87;i:222;i:88;i:224;i:89;i:228;i:90;i:229;i:91;i:230;i:92;i:231;i:93;i:232;i:94;i:234;i:95;i:235;i:96;i:236;i:97;i:248;i:98;i:251;i:99;i:252;i:100;i:253;i:101;i:254;i:102;i:255;i:103;i:256;i:104;i:257;}}

View File

@ -0,0 +1 @@
a:6:{s:9:"classesIn";a:1:{s:16:"App\Entity\Panel";a:6:{s:4:"name";s:5:"Panel";s:14:"namespacedName";s:16:"App\Entity\Panel";s:9:"namespace";s:10:"App\Entity";s:9:"startLine";i:13;s:7:"endLine";i:161;s:7:"methods";a:14:{s:11:"__construct";a:6:{s:10:"methodName";s:11:"__construct";s:9:"signature";s:131:"__construct(string $name, int $id, string $a, string $aaaa, string $passphrase, string $apikey, string $apikeyPrefix, string $self)";s:10:"visibility";s:6:"public";s:9:"startLine";i:25;s:7:"endLine";i:50;s:3:"ccn";i:3;}s:13:"getPassphrase";a:6:{s:10:"methodName";s:13:"getPassphrase";s:9:"signature";s:23:"getPassphrase(): string";s:10:"visibility";s:6:"public";s:9:"startLine";i:55;s:7:"endLine";i:58;s:3:"ccn";i:1;}s:7:"getName";a:6:{s:10:"methodName";s:7:"getName";s:9:"signature";s:17:"getName(): string";s:10:"visibility";s:6:"public";s:9:"startLine";i:64;s:7:"endLine";i:67;s:3:"ccn";i:1;}s:7:"setName";a:6:{s:10:"methodName";s:7:"setName";s:9:"signature";s:27:"setName(string $name): void";s:10:"visibility";s:6:"public";s:9:"startLine";i:72;s:7:"endLine";i:75;s:3:"ccn";i:1;}s:5:"getId";a:6:{s:10:"methodName";s:5:"getId";s:9:"signature";s:12:"getId(): int";s:10:"visibility";s:6:"public";s:9:"startLine";i:80;s:7:"endLine";i:83;s:3:"ccn";i:1;}s:5:"setId";a:6:{s:10:"methodName";s:5:"setId";s:9:"signature";s:20:"setId(int $id): void";s:10:"visibility";s:6:"public";s:9:"startLine";i:88;s:7:"endLine";i:91;s:3:"ccn";i:1;}s:4:"getA";a:6:{s:10:"methodName";s:4:"getA";s:9:"signature";s:14:"getA(): string";s:10:"visibility";s:6:"public";s:9:"startLine";i:96;s:7:"endLine";i:99;s:3:"ccn";i:1;}s:7:"getSelf";a:6:{s:10:"methodName";s:7:"getSelf";s:9:"signature";s:17:"getSelf(): string";s:10:"visibility";s:6:"public";s:9:"startLine";i:105;s:7:"endLine";i:108;s:3:"ccn";i:1;}s:7:"setSelf";a:6:{s:10:"methodName";s:7:"setSelf";s:9:"signature";s:27:"setSelf(string $self): void";s:10:"visibility";s:6:"public";s:9:"startLine";i:113;s:7:"endLine";i:116;s:3:"ccn";i:1;}s:7:"getAaaa";a:6:{s:10:"methodName";s:7:"getAaaa";s:9:"signature";s:17:"getAaaa(): string";s:10:"visibility";s:6:"public";s:9:"startLine";i:122;s:7:"endLine";i:125;s:3:"ccn";i:1;}s:9:"getApikey";a:6:{s:10:"methodName";s:9:"getApikey";s:9:"signature";s:19:"getApikey(): string";s:10:"visibility";s:6:"public";s:9:"startLine";i:130;s:7:"endLine";i:133;s:3:"ccn";i:1;}s:4:"setA";a:6:{s:10:"methodName";s:4:"setA";s:9:"signature";s:21:"setA(string $a): void";s:10:"visibility";s:6:"public";s:9:"startLine";i:139;s:7:"endLine";i:142;s:3:"ccn";i:1;}s:7:"setAaaa";a:6:{s:10:"methodName";s:7:"setAaaa";s:9:"signature";s:27:"setAaaa(string $aaaa): void";s:10:"visibility";s:6:"public";s:9:"startLine";i:147;s:7:"endLine";i:150;s:3:"ccn";i:1;}s:15:"getApikeyPrefix";a:6:{s:10:"methodName";s:15:"getApikeyPrefix";s:9:"signature";s:25:"getApikeyPrefix(): string";s:10:"visibility";s:6:"public";s:9:"startLine";i:156;s:7:"endLine";i:159;s:3:"ccn";i:1;}}}}s:8:"traitsIn";a:0:{}s:11:"functionsIn";a:0:{}s:14:"linesOfCodeFor";a:3:{s:11:"linesOfCode";i:162;s:18:"commentLinesOfCode";i:52;s:21:"nonCommentLinesOfCode";i:110;}s:15:"ignoredLinesFor";a:1:{i:0;i:13;}s:17:"executableLinesIn";a:23:{i:0;i:25;i:1;i:36;i:2;i:37;i:3;i:38;i:4;i:40;i:5;i:42;i:6;i:44;i:7;i:45;i:8;i:46;i:9;i:47;i:10;i:57;i:11;i:66;i:12;i:74;i:13;i:82;i:14;i:90;i:15;i:98;i:16;i:107;i:17;i:115;i:18;i:124;i:19;i:132;i:20;i:141;i:21;i:149;i:22;i:158;}}

View File

@ -0,0 +1 @@
a:6:{s:9:"classesIn";a:1:{s:25:"App\Entity\KeyHelp\Target";a:6:{s:4:"name";s:6:"Target";s:14:"namespacedName";s:25:"App\Entity\KeyHelp\Target";s:9:"namespace";s:18:"App\Entity\KeyHelp";s:9:"startLine";i:8;s:7:"endLine";i:61;s:7:"methods";a:6:{s:17:"getForwardingType";a:6:{s:10:"methodName";s:17:"getForwardingType";s:9:"signature";s:27:"getForwardingType(): string";s:10:"visibility";s:6:"public";s:9:"startLine";i:17;s:7:"endLine";i:20;s:3:"ccn";i:1;}s:17:"setForwardingType";a:6:{s:10:"methodName";s:17:"setForwardingType";s:9:"signature";s:48:"setForwardingType(?string $forwardingType): void";s:10:"visibility";s:6:"public";s:9:"startLine";i:25;s:7:"endLine";i:28;s:3:"ccn";i:1;}s:12:"isForwarding";a:6:{s:10:"methodName";s:12:"isForwarding";s:9:"signature";s:20:"isForwarding(): bool";s:10:"visibility";s:6:"public";s:9:"startLine";i:33;s:7:"endLine";i:36;s:3:"ccn";i:1;}s:15:"setIsForwarding";a:6:{s:10:"methodName";s:15:"setIsForwarding";s:9:"signature";s:41:"setIsForwarding(bool $isForwarding): void";s:10:"visibility";s:6:"public";s:9:"startLine";i:41;s:7:"endLine";i:44;s:3:"ccn";i:1;}s:9:"getTarget";a:6:{s:10:"methodName";s:9:"getTarget";s:9:"signature";s:19:"getTarget(): string";s:10:"visibility";s:6:"public";s:9:"startLine";i:49;s:7:"endLine";i:52;s:3:"ccn";i:1;}s:9:"setTarget";a:6:{s:10:"methodName";s:9:"setTarget";s:9:"signature";s:31:"setTarget(string $target): void";s:10:"visibility";s:6:"public";s:9:"startLine";i:57;s:7:"endLine";i:60;s:3:"ccn";i:1;}}}}s:8:"traitsIn";a:0:{}s:11:"functionsIn";a:0:{}s:14:"linesOfCodeFor";a:3:{s:11:"linesOfCode";i:61;s:18:"commentLinesOfCode";i:21;s:21:"nonCommentLinesOfCode";i:40;}s:15:"ignoredLinesFor";a:1:{i:0;i:8;}s:17:"executableLinesIn";a:6:{i:0;i:19;i:1;i:27;i:2;i:35;i:3;i:43;i:4;i:51;i:5;i:59;}}

View File

@ -0,0 +1 @@
a:6:{s:9:"classesIn";a:1:{s:17:"App\Entity\DynDNS";a:6:{s:4:"name";s:6:"DynDNS";s:14:"namespacedName";s:17:"App\Entity\DynDNS";s:9:"namespace";s:10:"App\Entity";s:9:"startLine";i:9;s:7:"endLine";i:98;s:7:"methods";a:11:{s:11:"__construct";a:6:{s:10:"methodName";s:11:"__construct";s:9:"signature";s:70:"__construct(string $name, string $a, string $aaaa, $password, int $id)";s:10:"visibility";s:6:"public";s:9:"startLine";i:14;s:7:"endLine";i:16;s:3:"ccn";i:1;}s:11:"getPassword";a:6:{s:10:"methodName";s:11:"getPassword";s:9:"signature";s:21:"getPassword(): string";s:10:"visibility";s:6:"public";s:9:"startLine";i:21;s:7:"endLine";i:24;s:3:"ccn";i:1;}s:11:"setPassword";a:6:{s:10:"methodName";s:11:"setPassword";s:9:"signature";s:35:"setPassword(string $password): void";s:10:"visibility";s:6:"public";s:9:"startLine";i:29;s:7:"endLine";i:32;s:3:"ccn";i:1;}s:4:"getA";a:6:{s:10:"methodName";s:4:"getA";s:9:"signature";s:14:"getA(): string";s:10:"visibility";s:6:"public";s:9:"startLine";i:37;s:7:"endLine";i:40;s:3:"ccn";i:1;}s:7:"getAaaa";a:6:{s:10:"methodName";s:7:"getAaaa";s:9:"signature";s:17:"getAaaa(): string";s:10:"visibility";s:6:"public";s:9:"startLine";i:45;s:7:"endLine";i:48;s:3:"ccn";i:1;}s:5:"getId";a:6:{s:10:"methodName";s:5:"getId";s:9:"signature";s:12:"getId(): int";s:10:"visibility";s:6:"public";s:9:"startLine";i:53;s:7:"endLine";i:56;s:3:"ccn";i:1;}s:7:"getName";a:6:{s:10:"methodName";s:7:"getName";s:9:"signature";s:17:"getName(): string";s:10:"visibility";s:6:"public";s:9:"startLine";i:61;s:7:"endLine";i:64;s:3:"ccn";i:1;}s:4:"setA";a:6:{s:10:"methodName";s:4:"setA";s:9:"signature";s:21:"setA(string $a): void";s:10:"visibility";s:6:"public";s:9:"startLine";i:69;s:7:"endLine";i:72;s:3:"ccn";i:1;}s:7:"setAaaa";a:6:{s:10:"methodName";s:7:"setAaaa";s:9:"signature";s:27:"setAaaa(string $aaaa): void";s:10:"visibility";s:6:"public";s:9:"startLine";i:77;s:7:"endLine";i:80;s:3:"ccn";i:1;}s:5:"setId";a:6:{s:10:"methodName";s:5:"setId";s:9:"signature";s:20:"setId(int $id): void";s:10:"visibility";s:6:"public";s:9:"startLine";i:85;s:7:"endLine";i:88;s:3:"ccn";i:1;}s:7:"setName";a:6:{s:10:"methodName";s:7:"setName";s:9:"signature";s:27:"setName(string $name): void";s:10:"visibility";s:6:"public";s:9:"startLine";i:93;s:7:"endLine";i:96;s:3:"ccn";i:1;}}}}s:8:"traitsIn";a:0:{}s:11:"functionsIn";a:0:{}s:14:"linesOfCodeFor";a:3:{s:11:"linesOfCode";i:99;s:18:"commentLinesOfCode";i:35;s:21:"nonCommentLinesOfCode";i:64;}s:15:"ignoredLinesFor";a:1:{i:0;i:9;}s:17:"executableLinesIn";a:11:{i:0;i:14;i:1;i:23;i:2;i:31;i:3;i:39;i:4;i:47;i:5;i:55;i:6;i:63;i:7;i:71;i:8;i:79;i:9;i:87;i:10;i:95;}}

View File

@ -0,0 +1 @@
a:6:{s:9:"classesIn";a:1:{s:27:"App\Entity\KeyHelp\Security";a:6:{s:4:"name";s:8:"Security";s:14:"namespacedName";s:27:"App\Entity\KeyHelp\Security";s:9:"namespace";s:18:"App\Entity\KeyHelp";s:9:"startLine";i:8;s:7:"endLine";i:130;s:7:"methods";a:14:{s:16:"getIdCertificate";a:6:{s:10:"methodName";s:16:"getIdCertificate";s:9:"signature";s:23:"getIdCertificate(): int";s:10:"visibility";s:6:"public";s:9:"startLine";i:21;s:7:"endLine";i:24;s:3:"ccn";i:1;}s:16:"setIdCertificate";a:6:{s:10:"methodName";s:16:"setIdCertificate";s:9:"signature";s:42:"setIdCertificate(int $idCertificate): void";s:10:"visibility";s:6:"public";s:9:"startLine";i:29;s:7:"endLine";i:32;s:3:"ccn";i:1;}s:13:"isLetsEncrypt";a:6:{s:10:"methodName";s:13:"isLetsEncrypt";s:9:"signature";s:21:"isLetsEncrypt(): bool";s:10:"visibility";s:6:"public";s:9:"startLine";i:37;s:7:"endLine";i:40;s:3:"ccn";i:1;}s:14:"setLetsEncrypt";a:6:{s:10:"methodName";s:14:"setLetsEncrypt";s:9:"signature";s:39:"setLetsEncrypt(bool $letsEncrypt): void";s:10:"visibility";s:6:"public";s:9:"startLine";i:45;s:7:"endLine";i:48;s:3:"ccn";i:1;}s:6:"isHsts";a:6:{s:10:"methodName";s:6:"isHsts";s:9:"signature";s:14:"isHsts(): bool";s:10:"visibility";s:6:"public";s:9:"startLine";i:53;s:7:"endLine";i:56;s:3:"ccn";i:1;}s:9:"setIsHsts";a:6:{s:10:"methodName";s:9:"setIsHsts";s:9:"signature";s:29:"setIsHsts(bool $isHsts): void";s:10:"visibility";s:6:"public";s:9:"startLine";i:61;s:7:"endLine";i:64;s:3:"ccn";i:1;}s:13:"getHstsMaxAge";a:6:{s:10:"methodName";s:13:"getHstsMaxAge";s:9:"signature";s:20:"getHstsMaxAge(): int";s:10:"visibility";s:6:"public";s:9:"startLine";i:69;s:7:"endLine";i:72;s:3:"ccn";i:1;}s:13:"setHstsMaxAge";a:6:{s:10:"methodName";s:13:"setHstsMaxAge";s:9:"signature";s:36:"setHstsMaxAge(int $hstsMaxAge): void";s:10:"visibility";s:6:"public";s:9:"startLine";i:77;s:7:"endLine";i:80;s:3:"ccn";i:1;}s:13:"isHstsInclude";a:6:{s:10:"methodName";s:13:"isHstsInclude";s:9:"signature";s:21:"isHstsInclude(): bool";s:10:"visibility";s:6:"public";s:9:"startLine";i:85;s:7:"endLine";i:88;s:3:"ccn";i:1;}s:14:"setHstsInclude";a:6:{s:10:"methodName";s:14:"setHstsInclude";s:9:"signature";s:39:"setHstsInclude(bool $hstsInclude): void";s:10:"visibility";s:6:"public";s:9:"startLine";i:93;s:7:"endLine";i:96;s:3:"ccn";i:1;}s:13:"isHstsPreload";a:6:{s:10:"methodName";s:13:"isHstsPreload";s:9:"signature";s:21:"isHstsPreload(): bool";s:10:"visibility";s:6:"public";s:9:"startLine";i:101;s:7:"endLine";i:104;s:3:"ccn";i:1;}s:14:"setHstsPreload";a:6:{s:10:"methodName";s:14:"setHstsPreload";s:9:"signature";s:39:"setHstsPreload(bool $hstsPreload): void";s:10:"visibility";s:6:"public";s:9:"startLine";i:109;s:7:"endLine";i:112;s:3:"ccn";i:1;}s:12:"isForceHttps";a:6:{s:10:"methodName";s:12:"isForceHttps";s:9:"signature";s:20:"isForceHttps(): bool";s:10:"visibility";s:6:"public";s:9:"startLine";i:118;s:7:"endLine";i:121;s:3:"ccn";i:1;}s:13:"setForceHttps";a:6:{s:10:"methodName";s:13:"setForceHttps";s:9:"signature";s:37:"setForceHttps(bool $forceHttps): void";s:10:"visibility";s:6:"public";s:9:"startLine";i:126;s:7:"endLine";i:129;s:3:"ccn";i:1;}}}}s:8:"traitsIn";a:0:{}s:11:"functionsIn";a:0:{}s:14:"linesOfCodeFor";a:3:{s:11:"linesOfCode";i:130;s:18:"commentLinesOfCode";i:45;s:21:"nonCommentLinesOfCode";i:85;}s:15:"ignoredLinesFor";a:1:{i:0;i:8;}s:17:"executableLinesIn";a:14:{i:0;i:23;i:1;i:31;i:2;i:39;i:3;i:47;i:4;i:55;i:5;i:63;i:6;i:71;i:7;i:79;i:8;i:87;i:9;i:95;i:10;i:103;i:11;i:111;i:12;i:120;i:13;i:128;}}

View File

@ -0,0 +1 @@
{"version":1,"defects":{"Unit\\Controller\\DatabaseConnectionTest::testGetConnection":5,"Warning":6,"App\\Controller\\NameserverControllerTest::testUpdate":5,"Unit\\Controller\\NameserverControllerTest::testUpdate":5,"Unit\\Repository\\DomainRepositoryTest::testInsert":5,"Unit\\Repository\\DomainRepositoryTest::testDelete":5,"Unit\\Repository\\DomainRepositoryTest::testFoo":4,"Unit\\Repository\\PanelRepositoryTest::testInsert":5},"times":{"Unit\\Controller\\DatabaseConnectionTest::testGetConnection":0.002,"Warning":0,"Unit\\Controller\\DatabaseConnectionTest::testFoo":0,"Unit\\Controller\\BindApiControllerTest::testFoo":0,"App\\Controller\\NameserverControllerTest::testUpdate":0,"Unit\\Controller\\NameserverControllerTest::testUpdate":0,"Unit\\Repository\\DomainRepositoryTest::testInsert":0,"Unit\\Repository\\DomainRepositoryTest::testDelete":0,"Unit\\Repository\\DomainRepositoryTest::testFoo":0.002,"Unit\\Controller\\NameserverControllerTest::testFoo":0,"Unit\\Controller\\RequestControllerTest::testFoo":0,"Unit\\Repository\\NameserverRepositoryTest::testInsert":0.027,"Unit\\Repository\\NameserverRepositoryTest::testFoo":0,"Unit\\Repository\\PanelRepositoryTest::testInsert":0,"Unit\\Repository\\PanelRepositoryTest::testFoo":0}}

11
Jenkinsfile vendored Normal file
View File

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

View File

@ -6,6 +6,9 @@
6. [DynDNS](#6-dyndns) 6. [DynDNS](#6-dyndns)
7. [Conclusion](#7-conclusion) 7. [Conclusion](#7-conclusion)
Don't use this code right now.
Use the latest release instead.
NOTICE: This documentation is not current as of September 2022. NOTICE: This documentation is not current as of September 2022.
After I finished the refactoring I'll upgrade it. After I finished the refactoring I'll upgrade it.

6
TODO
View File

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

View File

@ -3,18 +3,118 @@
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)
/** @noinspection PhpArgumentWithoutNamedIdentifierInspection */ // version, store that somewhere else
if (version_compare(PHP_VERSION, '8.2.0', '<')) { $version = '0.0.1';
echo 'This application requires PHP 8.2 or newer. You are running ' . PHP_VERSION . PHP_EOL;
echo 'If you are using KeyHelp, use keyhelp-php82 ' . $argv[0] . ' instead.' . PHP_EOL; if (!is_file(filename: dirname(path: __DIR__).'/vendor/autoload.php')) {
exit; die('Required runtime components are missing. Try running "composer install".' . PHP_EOL);
}
require dirname(path: __DIR__) . '/vendor/autoload.php';
$shortOpts = 'v::'; // version
$shortOpts = 'q::'; // version
$shortOpts .= "V::"; // verbose
$shortOpts .= "h::"; // help
$longOpts = [
'version::',
'quiet::',
'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: 'q', array: $options) || array_key_exists(key: 'quiet', array: $options)) {
$quiet = true;
} else {
$quiet = false;
}
if (array_key_exists(key: 'V', array: $options) || array_key_exists(key: 'verbose', array: $options)) {
$verbose = true;
} else {
$verbose = false;
}
$arguments = array_slice(array: $argv, offset: $restIndex);
try {
$app = new BindAPI(verbose: $verbose, quiet: $quiet);
$app->runCommand(arguments: $arguments);
} catch (DependencyException|NotFoundException|Exception $e) {
echo $e->getMessage() . PHP_EOL;
exit(1);
}
/**
* @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,8 +1,8 @@
{ {
"name": "tracer/bindapi", "name": "tracer/bindapi",
"description": "manage Bind9 client zones for KeyHelp", "decription": "fo",
"version": "1.1.2", "version": "2023.0.1",
"build_number": "380", "build_number": "1",
"authors": [ "authors": [
{ {
"name": "Micha Espey", "name": "Micha Espey",
@ -14,7 +14,7 @@
"minimum-stability": "stable", "minimum-stability": "stable",
"prefer-stable": true, "prefer-stable": true,
"require": { "require": {
"php": ">=8.2", "php": ">=8.1",
"ext-curl": "*", "ext-curl": "*",
"ext-json": "*", "ext-json": "*",
"ext-mbstring": "*", "ext-mbstring": "*",
@ -23,15 +23,13 @@
"ext-posix": "*", "ext-posix": "*",
"ext-sodium": "*", "ext-sodium": "*",
"arubacao/tld-checker": "^1.2", "arubacao/tld-checker": "^1.2",
"bartlett/php-compatinfo": "^7.1",
"monolog/monolog": "^3.1", "monolog/monolog": "^3.1",
"netresearch/jsonmapper": "^4.4", "netresearch/jsonmapper": "^4.0",
"php-di/php-di": "^6.3", "php-di/php-di": "^6.3",
"phplucidframe/console-table": "^1.2", "phplucidframe/console-table": "^1.2",
"robmorgan/phinx": "^0.15",
"symfony/property-access": "^6.1", "symfony/property-access": "^6.1",
"symfony/serializer": "^6.1", "symfony/serializer": "^6.1",
"zircote/swagger-php": "^4.8" "zircote/swagger-php": "^4.2"
}, },
"config": { "config": {
"optimize-autoloader": true, "optimize-autoloader": true,
@ -52,7 +50,6 @@
}, },
"require-dev": { "require-dev": {
"escapestudios/symfony2-coding-standard": "3.x-dev", "escapestudios/symfony2-coding-standard": "3.x-dev",
"odan/phinx-migrations-generator": "^6.1", "phpunit/phpunit": "^9.5"
"phpunit/phpunit": "10"
} }
} }

5162
composer.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -1,10 +1,9 @@
{ {
"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", "encryptionKey": "12345678901234567890123456789012",
"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

0
hooks/post-commit Executable file → Normal file
View File

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,20 +1,17 @@
<?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); $uri = parse_url(url: $_SERVER['REQUEST_URI'], component: PHP_URL_PATH);
$uri = explode(separator: '/', string: $parsedUrl); $uri = explode(separator: '/', string: $uri);
$baseRoutes = ['app', 'api']; if ($uri[1] !== 'api') {
$uriPrefix = $uriFirstThreeLetters = substr(string: $uri[1], offset: 0, length: 3);
if (!in_array(needle: $uriPrefix, haystack: $baseRoutes)) {
// only handle $baseRoutes, elso go to swagger ui
$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";
@ -26,22 +23,15 @@ 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); $app = new BindAPI();
$app->handleRequest(requestMethod: $requestMethod, uri: $uri); $app->handleRequest(requestMethod: $requestMethod, uri: $uri);
} catch (Exception $e) { } catch (Exception $e) {
echo json_encode(value: [ echo json_encode(value: [
'error' => $e->getMessage() 'error' => $e->getMessage()
]); ]);
} }

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,

View File

@ -1,13 +1,29 @@
<?php declare(strict_types=1); <?php declare(strict_types=1);
namespace App\Service; namespace App\Controller;
use UnhandledMatchError; use UnhandledMatchError;
error_reporting(error_level: E_ALL); error_reporting(error_level: E_ALL);
class ApiClient
/**
*
*/
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 function sendCommand(string $requestType, string $serverName, int $versionIP, string $apiKey, string $command, string $serverType, array $body = []): array
{ {
$error = false; $error = false;
@ -19,7 +35,7 @@ class ApiClient
'nameserver' => curl_setopt(handle: $curl, option: CURLOPT_URL, value: "https://$serverName/api/" . $command) 'nameserver' => curl_setopt(handle: $curl, option: CURLOPT_URL, value: "https://$serverName/api/" . $command)
}; };
} catch (UnhandledMatchError) { } catch (UnhandledMatchError) {
exit('Unhandled match: ' . $serverType .' in ' . __FILE__ . ' on line ' . __LINE__ . PHP_EOL); echo 'Unhandled match: ' . $serverType;
} }
curl_setopt(handle: $curl, option: CURLOPT_RETURNTRANSFER, value: 1); curl_setopt(handle: $curl, option: CURLOPT_RETURNTRANSFER, value: 1);
@ -63,7 +79,6 @@ class ApiClient
break; break;
case 400: case 400:
$result = $resultJSON; $result = $resultJSON;
$error = true;
break; break;
case 401: case 401:
$result = 'Missing or wrong API Key'; $result = 'Missing or wrong API Key';
@ -71,14 +86,11 @@ class ApiClient
break; break;
case 404: case 404:
$result = '404 Not Found'; $result = '404 Not Found';
$error = true;
break; break;
case 500: case 500:
$result = 'server error'; $result = 'server error';
$error = true;
break; break;
default: default:
$error = true;
$result = 'Unhandled error: ' . $httpResponse; $result = 'Unhandled error: ' . $httpResponse;
} }
} else { } else {
@ -105,7 +117,7 @@ class ApiClient
$options = array( $options = array(
CURLOPT_RETURNTRANSFER => true, CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => true, CURLOPT_FOLLOWLOCATION => true,
CURLOPT_ENCODING => '', CURLOPT_ENCODING => "",
CURLOPT_AUTOREFERER => true, CURLOPT_AUTOREFERER => true,
CURLOPT_CONNECTTIMEOUT => 120, CURLOPT_CONNECTTIMEOUT => 120,
CURLOPT_TIMEOUT => 120, CURLOPT_TIMEOUT => 120,
@ -131,6 +143,4 @@ class ApiClient
return $header; return $header;
} }
} }

93
src/Controller/BindAPI.php Executable file
View File

@ -0,0 +1,93 @@
<?php declare(strict_types=1);
namespace App\Controller;
error_reporting(error_level: E_ALL);
use App\Repository\DomainRepository;
use App\Repository\DynDNSRepository;
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;
/**
* @throws Exception
*/
public function __construct($verbose = false, $quiet = false)
{
// 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: 2) . '/bindAPI.log', level: Level::Debug);
} else {
$stream = new StreamHandler(stream: dirname(path: __DIR__, levels: 2) . '/bindAPI.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([
ConfigController::class => autowire()
->constructorParameter(parameter: 'quiet', value: $quiet)
->constructorParameter(parameter: 'verbose', value: $verbose),
CLIController::class => autowire()
->constructorParameter(parameter: 'logger', value: $this->logger),
DomainController::class => autowire()
->constructorParameter(parameter: 'logger', value: $this->logger),
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);
}
}

File diff suppressed because it is too large Load Diff

View File

@ -2,8 +2,6 @@
namespace App\Controller\Commands; namespace App\Controller\Commands;
use App\Utilities\Colors;
/** /**
* *
*/ */
@ -33,17 +31,17 @@ class CommandGroup
public function printCommands(int $longestCommandLength): void 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; echo COLOR_YELLOW . str_pad(string: $this->name, length: $longestCommandLength + 1) . COLOR_WHITE . $this->description . COLOR_DEFAULT . PHP_EOL;
foreach ($this->commands as $command) { foreach ($this->commands as $command) {
echo Colors::GREEN . str_pad(string: ' ', length: $longestCommandLength + 1, pad_type: STR_PAD_LEFT) . $this->name . ':' . $command->getName(); echo COLOR_GREEN . str_pad(string: ' ', length: $longestCommandLength + 1, pad_type: STR_PAD_LEFT) . $this->name . ':' . $command->getName();
foreach ($command->getMandatoryParameters() as $optionals) { foreach ($command->getMandatoryParameters() as $optionals) {
echo ' <' . $optionals . '>'; echo ' <' . $optionals . '>';
} }
foreach ($command->getOptionalParameters() as $mandatory) { foreach ($command->getOptionalParameters() as $mandatory) {
echo ' {' . $mandatory . '}'; echo ' {' . $mandatory . '}';
} }
echo Colors::WHITE . ' ' . $command->getDescription(); echo COLOR_WHITE . ' ' . $command->getDescription();
echo Colors::DEFAULT . PHP_EOL; echo COLOR_DEFAULT . PHP_EOL;
} }
} }
@ -57,28 +55,14 @@ class CommandGroup
return null; 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 public function exec(string $subcommand): void
{ {
if ($command = $this->findCommandByName(command: $subcommand)) { if ($command = $this->findCommandByName(command: $subcommand)) {
$command->exec(); $command->exec();
return true;
} else { } else {
return false; echo COLOR_DEFAULT . 'Command ' . COLOR_YELLOW . $this->name . ':' . $subcommand . COLOR_DEFAULT . ' not found.' . PHP_EOL;
exit(1);
} }
} }
} }

View File

@ -2,8 +2,6 @@
namespace App\Controller\Commands; namespace App\Controller\Commands;
use App\Utilities\Colors;
/** /**
* *
*/ */
@ -48,6 +46,10 @@ class CommandGroupContainer
} }
/**
* @param string $command
* @return ?CommandGroup
*/
private function findGroupByName(string $command): ?CommandGroup private function findGroupByName(string $command): ?CommandGroup
{ {
foreach ($this->commandGroups as $group) { foreach ($this->commandGroups as $group) {
@ -61,28 +63,11 @@ class CommandGroupContainer
public function run(string $command, string $subcommand): void public function run(string $command, string $subcommand): void
{ {
if ($subcommand !== '') {
if ($group = $this->findGroupByName(command: $command)) { if ($group = $this->findGroupByName(command: $command)) {
if ($group->exec(subcommand: $subcommand)) { $group->exec(subcommand: $subcommand);
exit(0);
} else { } else {
echo Colors::DEFAULT . 'Unknown subcommand ' . Colors::YELLOW . $subcommand . Colors::DEFAULT .' for ' . Colors::YELLOW . $command . Colors::DEFAULT . '.' . PHP_EOL; echo COLOR_DEFAULT . 'Unknown command ' . COLOR_YELLOW . $command . COLOR_DEFAULT . '.' . PHP_EOL;
exit(1); 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

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

View File

@ -0,0 +1,149 @@
<?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";
const TABLE_DYNDNS = self::TABLE_PREFIX . "dyndns";
public function __construct(private readonly ConfigController $configController)
{
$dbHost = $this->configController->getConfig(configKey: 'dbHost');
$dbPort = $this->configController->getConfig(configKey: 'dbPort');
$dbDatabase = $this->configController->getConfig(configKey: 'dbDatabase');
$dbUser = $this->configController->getConfig(configKey: 'dbUser');
$dbPassword = $this->configController->getConfig(configKey: 'dbPassword');
$this->dbConnection = new PDO(
dsn: "mysql:host=$dbHost;port=$dbPort;charset=utf8mb4;dbname=$dbDatabase",
username: $dbUser,
password: $dbPassword
);
if (!$this->configController->getConfig(configKey: 'test')) {
// TODO create config => encryption key
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 '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();
$sql = "
CREATE TABLE `dyndns` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` VARCHAR(255) NOT NULL,
`a` VARBINARY(255) NOT NULL,
`aaaa` VARBINARY(255) NOT NULL,
`last_update` TIMESTAMP NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci";
$statement = $this->dbConnection->prepare(query: $sql);
$statement->execute();
echo 'Tables have been created.' . PHP_EOL;
}
exit(1);
}
} catch (PDOException $exception) {
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);
@ -27,13 +25,11 @@ class DomainController
public function __construct( public function __construct(
private readonly NameserverRepository $nameserverRepository, private readonly NameserverRepository $nameserverRepository,
private readonly ApiClient $checkController, private readonly ApiController $checkController,
private readonly DomainRepository $domainRepository, private readonly DomainRepository $domainRepository,
private readonly PanelRepository $panelRepository, private readonly PanelRepository $panelRepository,
private readonly ConfigController $configController, private readonly ConfigController $configController,
private readonly Logger $logger, private readonly Logger $logger)
private readonly bool $quiet
)
{ {
$this->localZoneFile = '/etc/bind/local.zones'; $this->localZoneFile = '/etc/bind/local.zones';
$this->localZonesDir = '/etc/bind/zones/'; $this->localZonesDir = '/etc/bind/zones/';
@ -56,7 +52,7 @@ class DomainController
} }
fclose(stream: $oFile); fclose(stream: $oFile);
exec(command: '/usr/bin/named-checkconf', output: $output, result_code: $resultCode); exec(command: '/usr/sbin/named-checkconf', output: $output, result_code: $resultCode);
if ($resultCode != 0) { if ($resultCode != 0) {
echo 'There was an error:' . PHP_EOL; echo 'There was an error:' . PHP_EOL;
foreach ($output as $line) { foreach ($output as $line) {
@ -72,58 +68,23 @@ class DomainController
function updateSlaveZones(): void function updateSlaveZones(): void
{ {
$this->logger->debug(message: 'update slave zones'); $this->logger->debug(message: 'Delete all slave zones');
$existingZones = glob(pattern: $this->localZonesDir . '*'); $zones = glob(pattern: $this->localZonesDir . '*');
foreach ($zones as $zone) {
$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); unlink(filename: $zone);
} }
$semaphore = $this->localZonesDir . 'zones.flag'; $domains = $this->domainRepository->findAll();
if (file_exists(filename: $semaphore)) {
unlink(filename: $semaphore); foreach ($domains as $domain) {
$this->createIncludeFile(); if ($this->configController->getConfig(configKey: 'verbose')) {
echo 'Create zone: ' . $domain->getName() . PHP_EOL;
} }
$this->createSlaveZoneFile(domain: $domain);
}
$this->createIncludeFile();
} }
@ -177,90 +138,96 @@ class DomainController
} }
function checkPermissions($impersonatedUserId = null): bool /**
* @return bool
*/
function checkPermissions(bool $disableVerbose = false): bool
{ {
$this->logger->debug(message: "checkPermissions()");
$setupIsValid = true; $setupIsValid = true;
if (!$this->quiet) {
if (!$disableVerbose) {
$verbose = $this->configController->getConfig(configKey: 'verbose');
} else {
$verbose = false;
}
$this->logger->debug(message: "checkPermissions()");
if ($verbose) {
echo 'Checking permissions...' . PHP_EOL; echo 'Checking permissions...' . PHP_EOL;
} }
if ($impersonatedUserId) {
$uid = $impersonatedUserId;
} else {
$uid = posix_geteuid(); $uid = posix_geteuid();
} if ($verbose) {
if (!$this->quiet) { echo "UID:\t" . COLOR_YELLOW . $uid . PHP_EOL;
echo "UID:\t" . Colors::YELLOW . $uid . PHP_EOL;
} }
$pwuid = posix_getpwuid(user_id: $uid); $pwuid = posix_getpwuid(user_id: $uid);
$name = $pwuid['name']; $name = $pwuid['name'];
if (!$this->quiet) { if ($verbose) {
echo Colors::DEFAULT . "Name:\t" . Colors::YELLOW . $name . PHP_EOL; echo COLOR_DEFAULT . "Name:\t" . COLOR_YELLOW . $name . PHP_EOL;
} }
if (!$bindGroup = posix_getgrnam(name: 'bind')) { $bindGroup = posix_getgrnam(name: 'bind');
$bindGroup = []; $members = $bindGroup['members'];
}
$members = $bindGroup['members'] ?? [];
if (in_array(needle: $name, haystack: $members)) { if (in_array(needle: $name, haystack: $members)) {
if (!$this->quiet) { if ($verbose) {
echo "\t$name" . Colors::DEFAULT . ' is in group ' . Colors::YELLOW . 'bind' . PHP_EOL; echo "\t$name" . COLOR_DEFAULT . ' is in group ' . COLOR_YELLOW . 'bind' . PHP_EOL;
} }
} else { } else {
$setupIsValid = false; $setupIsValid = false;
if (!$this->quiet) { if ($verbose) {
echo Colors::RED . "\t$name needs to be in group " . Colors::YELLOW . 'bind' . Colors::DEFAULT . '!' . PHP_EOL; echo COLOR_RED . "\t$name needs to be in group " . COLOR_YELLOW . 'bind' . COLOR_DEFAULT . '!' . PHP_EOL;
} }
} }
if (!$this->quiet) { if ($verbose) {
echo Colors::DEFAULT . 'Checking ' . Colors::YELLOW . $this->localZoneFile . PHP_EOL; echo COLOR_DEFAULT . 'Checking ' . COLOR_YELLOW . $this->localZoneFile . PHP_EOL;
} }
$localZoneFilePermissions = @fileperms(filename: $this->localZoneFile); $localZoneFilePermissions = @fileperms(filename: $this->localZoneFile);
if ($localZoneFilePermissions & 0x0010) { if ($localZoneFilePermissions & 0x0010) {
if (!$this->quiet) { if ($verbose) {
echo Colors::DEFAULT . "\t✅ Group has write access." . PHP_EOL; echo COLOR_DEFAULT . "\t✅ Group has write access." . PHP_EOL;
} }
} else { } else {
$setupIsValid = false; $setupIsValid = false;
if (!$this->quiet) { if ($verbose) {
echo Colors::RED . "\t❌Group needs write permission!" . Colors::DEFAULT . PHP_EOL; echo COLOR_RED . "\t❌Group needs write permission!" . COLOR_DEFAULT . PHP_EOL;
} }
} }
if (!$this->quiet) { if ($verbose) {
echo 'Checking ' . Colors::YELLOW . $this->namedConfLocalFile . PHP_EOL; echo 'Checking ' . COLOR_YELLOW . $this->namedConfLocalFile . PHP_EOL;
} }
if (file_exists(filename: $this->namedConfLocalFile) && $namedConfLocal = file_get_contents(filename: $this->namedConfLocalFile)) { if ($namedConfLocal = file_get_contents(filename: $this->namedConfLocalFile)) {
if (!str_contains(haystack: $namedConfLocal, needle: $this->localZoneFile)) { if (!str_contains(haystack: $namedConfLocal, needle: $this->localZoneFile)) {
$setupIsValid = false; $setupIsValid = false;
if (!$this->quiet) { if ($verbose) {
echo "\t$this->localZoneFile" . Colors::RED . ' needs to be included in ' . Colors::YELLOW . $this->namedConfLocalFile . PHP_EOL; echo "\t$this->localZoneFile" . COLOR_RED . ' needs to be included in ' . COLOR_YELLOW . $this->namedConfLocalFile . PHP_EOL;
} }
} else { } else {
if (!$this->quiet) { if ($verbose) {
echo "\t$this->localZoneFile" . Colors::DEFAULT . ' is included in ' . Colors::YELLOW . $this->namedConfLocalFile . PHP_EOL; echo "\t$this->localZoneFile" . COLOR_DEFAULT . ' is included in ' . COLOR_YELLOW . $this->namedConfLocalFile . PHP_EOL;
} }
} }
} else { } else {
$setupIsValid = false; $setupIsValid = false;
if (!$this->quiet) { if ($verbose) {
echo "\t❌ No access to '$this->namedConfLocalFile' . Please check permissions" . PHP_EOL; echo "\t❌ No access to '$this->namedConfLocalFile' . Please check permissions" . PHP_EOL;
} }
} }
if (!$this->quiet) { if ($verbose) {
echo Colors::DEFAULT . 'Checking directory: ' . Colors::YELLOW . $this->localZonesDir . PHP_EOL; echo COLOR_DEFAULT . 'Checking directory: ' . COLOR_YELLOW . $this->localZonesDir . PHP_EOL;
} }
$localZoneDirPermissions = @fileperms(filename: $this->localZonesDir); $localZoneDirPermissions = @fileperms(filename: $this->localZonesDir);
if ($localZoneDirPermissions & 0x0010) { if ($localZoneDirPermissions & 0x0010) {
if (!$this->quiet) { if ($verbose) {
echo "\t✅ Group has write access." . PHP_EOL; echo "\t✅ Group has write access." . PHP_EOL;
} }
} else { } else {
$setupIsValid = false; $setupIsValid = false;
if (!$this->quiet) { if ($verbose) {
echo Colors::RED . "\t❌Group needs write permission!" . PHP_EOL; echo COLOR_RED . "\t❌Group needs write permission!" . PHP_EOL;
} }
} }
echo 'setup is valid:' . $setupIsValid ? 'true' : 'false';
return $setupIsValid; return $setupIsValid;
} }
@ -271,9 +238,7 @@ class DomainController
function checkDomains(): void function checkDomains(): void
{ {
if (!file_exists(filename: $this->localZoneFile)) { if (!file_exists(filename: $this->localZoneFile)) {
if (!$this->quiet) { echo COLOR_DEFAULT . 'Local Zone file ' . COLOR_YELLOW . $this->localZoneFile . COLOR_DEFAULT . ' does not exist.' . PHP_EOL;
echo Colors::DEFAULT . 'Local Zone file ' . Colors::YELLOW . $this->localZoneFile . Colors::DEFAULT . ' does not exist.' . PHP_EOL;
}
exit(1); exit(1);
} }
$localZones = file_get_contents(filename: $this->localZoneFile); $localZones = file_get_contents(filename: $this->localZoneFile);
@ -281,35 +246,27 @@ class DomainController
$domains = $this->domainRepository->findAll(); $domains = $this->domainRepository->findAll();
foreach ($domains as $domain) { foreach ($domains as $domain) {
$idString = '(' . $domain->getId() . ') '; $idString = '(' . strval(value: $domain->getId()) . ') ';
if (!$this->quiet) { echo COLOR_YELLOW .
echo Colors::YELLOW .
str_pad(string: $domain->getName(), length: $maxNameLength + 1) str_pad(string: $domain->getName(), length: $maxNameLength + 1)
. Colors::DEFAULT . COLOR_DEFAULT
. str_pad(string: $idString, length: 7, pad_type: STR_PAD_LEFT); . str_pad(string: $idString, length: 7, pad_type: STR_PAD_LEFT);
}
$hasError = false; $hasError = false;
if ($this->isMasterZone(domain: $domain)) { if ($this->isMasterZone(domain: $domain)) {
if (!$this->quiet) { echo 'Master Zone lies on this panel.';
echo Colors::GREEN . 'Master Zone';
}
} else { } else {
if (!str_contains(haystack: $localZones, needle: $domain->getName())) { if (!str_contains(haystack: $localZones, needle: $domain->getName())) {
if (!$this->quiet) { echo COLOR_RED . 'is missing in ' . COLOR_YELLOW . $this->localZoneFile . COLOR_DEFAULT;
echo Colors::RED . 'is missing in ' . Colors::YELLOW . $this->localZoneFile . Colors::DEFAULT;
}
$hasError = true; $hasError = true;
} else { } else {
if (!$this->quiet) { echo COLOR_GREEN . 'OK';
echo Colors::GREEN . 'OK';
}
} }
$zoneFile = $this->localZonesDir . $domain->getName(); $zoneFile = $this->localZonesDir . $domain->getName();
if (!file_exists(filename: $zoneFile)) { if (!file_exists(filename: $zoneFile)) {
echo ' Missing zone file for ' . Colors::YELLOW . $zoneFile . Colors::DEFAULT; echo ' Missing zone file for ' . COLOR_YELLOW . $zoneFile . COLOR_DEFAULT;
$hasError = true; $hasError = true;
} }
@ -317,9 +274,7 @@ class DomainController
echo " Update zone (Domain) to create it."; echo " Update zone (Domain) to create it.";
} }
} }
if (!$this->quiet) { echo COLOR_DEFAULT . PHP_EOL;
echo Colors::DEFAULT . PHP_EOL;
}
} }
} }
@ -330,26 +285,22 @@ class DomainController
* *
* @return void * @return void
*/ */
public function createSlaveZoneFile(Domain $domain): bool public function createSlaveZoneFile(Domain $domain): void
{ {
touch(filename: $this->localZonesDir . 'zones.flag');
$domainName = $domain->getName(); $domainName = $domain->getName();
$this->logger->info(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)) { if ($this->isMasterZone(domain: $domain)) {
//echo 'We are zone master for ' . $domainName . PHP_EOL; //echo 'We are zone master for ' . $domainName . PHP_EOL;
return true; return;
} }
if ($zoneFile = fopen(filename: $this->localZonesDir . $domainName, mode: 'w')) { if ($zoneFile = fopen(filename: $this->localZonesDir . $domainName, mode: 'w')) {
$panelName = $domain->getPanel(); $panelName = $domain->getPanel();
if (!$panel = $this->panelRepository->findByName(name: $panelName)) { if (!$panel = $this->panelRepository->findByName(name: $panelName)) {
if (!$this->quiet) {
echo "Error: Panel $panelName doesn't exist." . PHP_EOL; echo "Error: Panel $panelName doesn't exist." . PHP_EOL;
} die();
return false;
} }
$a = $panel->getA(); $a = $panel->getA();
$aaaa = $panel->getAaaa(); $aaaa = $panel->getAaaa();
@ -365,12 +316,6 @@ class DomainController
} }
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;
} }
} }

View File

@ -28,7 +28,7 @@ class EncryptionController
sodium_memzero(string: $binKey); sodium_memzero(string: $binKey);
return $cipher; return $cipher;
} catch (Exception|SodiumException $e) { } catch (Exception|SodiumException $e) {
exit($e->getMessage() . PHP_EOL); die($e->getMessage() . PHP_EOL);
} }
} }
@ -58,13 +58,13 @@ class EncryptionController
$plain = sodium_crypto_secretbox_open(ciphertext: $ciphertext, nonce: $nonce, key: $binKey); $plain = sodium_crypto_secretbox_open(ciphertext: $ciphertext, nonce: $nonce, key: $binKey);
if ($plain === false) { if ($plain === false) {
throw new Exception(message: ' Incorrect key.' . PHP_EOL); throw new Exception(message: ' Incorrect key.');
} }
sodium_memzero(string: $ciphertext); sodium_memzero(string: $ciphertext);
sodium_memzero(string: $key); sodium_memzero(string: $key);
return $plain; return $plain;
} catch(Exception|SodiumException $e) { } catch(Exception|SodiumException $e) {
exit($e->getMessage()); die($e->getMessage());
} }
} }

View File

@ -10,40 +10,39 @@ use App\Repository\ApikeyRepository;
use App\Repository\DomainRepository; use App\Repository\DomainRepository;
use App\Repository\DynDNSRepository; use App\Repository\DynDNSRepository;
use App\Repository\PanelRepository; use App\Repository\PanelRepository;
use App\Service\ApiClient;
use Monolog\Logger; use Monolog\Logger;
use OpenApi\Attributes as OA; use OpenApi\Attributes as OAT;
use OpenApi\Attributes\OpenApi;
use OpenApi\Generator;
use UnhandledMatchError; use UnhandledMatchError;
use function Symfony\Component\String\s;
// TODO attributes for swaggerUI // TODO attributes for swaggerUI
#[OA\Info(version: VERSION, title: 'bindAPI')] /**
#[OA\Server( *
*/
#[OAT\Info(version: '0.0.1', title: 'bindAPI')]
#[OAT\Server(
url: "{schema}://{hostname}/api", url: "{schema}://{hostname}/api",
description: "The bindAPI URL.", description: "The bindAPI URL.",
variables: [ variables: [
new OA\ServerVariable( new OAT\ServerVariable(
serverVariable: 'schema', serverVariable: "schema",
default: 'https', default: "https",
enum: ['http', 'https'] enum: ["https", "http"]
), ),
new OA\ServerVariable( new OAT\ServerVariable(
serverVariable: 'hostname', serverVariable: "hostname",
default: DEFAULT_NS, default: "ns2.24unix.net",
enum: NAMESERVERS
) )
] ]
)] )]
#[OA\Tag( #[OAT\Tag(
name: "Server" name: "Server"
)] )]
#[OA\SecurityScheme( #[OAT\SecurityScheme(
securityScheme: "Authorization", securityScheme: "Authorization",
type: "apiKey", type: "apiKey",
description: "Api Authentication", description: "description",
name: "X-API-Key", name: "X-API-Key",
in: "header" in: "header"
)] )]
@ -57,96 +56,60 @@ class RequestController
private array $uri; private array $uri;
// server tag /**
private string $baseDir; * @param ApiController $apiController
* @param ApikeyRepository $apikeyRepository
#[OA\Get( * @param DomainController $domainController
path: '/ping', * @param DomainRepository $domainRepository
operationId: 'ping', * @param DynDNSRepository $dynDNSRepository
description: 'Checks for connectivity and valid APIkey', * @param PanelRepository $panelRepository
security: [ * @param ConfigController $configController
['Authorization' => []] * @param EncryptionController $encryptionController
], * @param Logger $logger
tags: ['Server'], */
responses: [ public function __construct(
new OA\Response( private readonly ApiController $apiController,
response: 200, private readonly ApikeyRepository $apikeyRepository,
description: 'OK' private readonly DomainController $domainController,
), private readonly DomainRepository $domainRepository,
new OA\Response( private readonly DynDNSRepository $dynDNSRepository,
response: 401, private readonly PanelRepository $panelRepository,
description: 'API key is missing or invalid.' private readonly ConfigController $configController,
) private readonly EncryptionController $encryptionController,
] private readonly Logger $logger)
)]
private function handlePing(): void
{ {
if ($this->validateApiKey()) { $this->status = '';
$this->status = '200 OK'; $this->response = '';
$this->response = 'pong'; $this->message = '';
} else { $this->result = [];
$this->status = '401 Unauthorized';
$this->message = 'API key is missing or invalid';
}
} }
#[OA\Get( /**
path: '/version', * @return void
operationId: 'version', */
description: 'Check the API version of the nameserver.', #[OAT\Get(
security: [
['Authorization' => []]
],
tags: ['Server'],
responses: [
new OA\Response(
response: 200,
description: 'x.y.z, aka major, minor, patch'
),
new OA\Response(
response: 401,
description: 'API key is missing or invalid.'
)
]
)]
private function getVersion(): void
{
if ($this->validateApiKey()) {
$this->status = '200 OK';
$composerJson = json_decode(json: file_get_contents(filename: $this->baseDir . 'composer.json'));
$version = $composerJson->version;
$buildNumber = $composerJson->build_number;
$this->result = [
'version' => $version,
'buildnumber' => $buildNumber,
];
} else {
$this->status = '401 Unauthorized';
$this->message = 'API key is missing or invalid';
}
}
#[OA\Get(
path: '/domains', path: '/domains',
operationId: 'getAllDomains', operationId: 'getAllDomains',
description: 'Returns a list of all domains on this server.', description: 'Returns a list of all domains on this server.',
summary: 'List all domains.', summary: 'Listing all domains.',
security: [ // security: [
['Authorization' => []] // 'Authorization' => [
], //
// "read:api"
// ]
// ],
servers: [],
tags: ['Domains'], tags: ['Domains'],
responses: [ responses: [
new OA\Response( new OAT\Response(
response: 200, response: 200,
description: 'OK' description: 'OK'
), ),
new OA\Response( new OAT\Response(
response: 401, response: 401,
description: 'API key is missing or invalid.' description: 'API key is missing or invalid.'
), ),
new OA\Response( new OAT\Response(
response: 404, response: 404,
description: 'Domain not found.' description: 'Domain not found.'
)] )]
@ -168,6 +131,16 @@ class RequestController
/** /**
*/ */
private function handlePing(): void
{
if ($this->checkPassword()) {
$this->status = '200 OK';
$this->response = 'pong';
} else {
$this->status = '401 Unauthorized';
$this->message = 'API key is missing or invalid';
}
}
/** /**
@ -175,7 +148,7 @@ class RequestController
*/ */
private function handleDomains(): void private function handleDomains(): void
{ {
if ($this->validateApiKey()) { if ($this->checkPassword()) {
try { try {
match ($this->requestMethod) { match ($this->requestMethod) {
'GET' => $this->handleDomainsGetRequest(), 'GET' => $this->handleDomainsGetRequest(),
@ -191,8 +164,131 @@ class RequestController
} }
/**
* @OA\Tag(name = "Server")
* @OA\Get(
* path = "/ping",
* summary = "Returning pong.",
* description = "Can be used to check API or server availability.",
* tags={"Server"},
* @OA\Response(response = "200", description = "OK"),
* @OA\Response(response = "401", description = "API key is missing or invalid."),
* security={
* {"Authorization":{"read"}}
* }
* )
*
* @OA\Tag(name = "Domains")
* @OA\Put(
* path="/domains/{name}",
* summary="Updates a domain.",
* description="Updates a domain. Only supplied fields will be updated, existing won't be affected.",
* tags={"Domains"},
* @OA\Response(response="200", description="OK"),
* @OA\Response(response = "401", description = "API key is missing or invalid."),
* @OA\Response(response="404", description="Domain not found."),
* security={
* {"Authorization":{"read":"write"}}
* }
* )
* @OA\Delete (
* path="/domains/{name}",
* summary="Deletes a domain.",
* description="Deletes a domain.",
* tags={"Domains"},
* @OA\Response(response="200", description="OK"),
* @OA\Response(response = "401", description = "API key is missing or invalid."),
* @OA\Response(response="404", description="Domain not found."),
* security={
* {"Authorization":{"read":"write"}}
* }
* )
* @param string $requestMethod
* @param array $uri
*
* @return void
*/
private function validateApiKey(): bool #[
OAT\Get(
path: '/domains/{name}',
operationId: 'getSingleDomain',
description: 'Returns information of a single domain specified by its domain name.',
summary: 'Returns a single domain.',
security: [
],
tags: ['Domains'],
parameters: [
new OAT\Parameter(name: 'name', in: 'path', required: true, schema: new OAT\Schema(type: 'string')),
],
responses: [
new OAT\Response(
response: 200,
description: 'OK'
),
new OAT\Response(
response: 401,
description: 'API key is missing or invalid.'
),
new OAT\Response(
response: 404,
description: 'Domain not found.'
)]
)]
public function handleRequest(string $requestMethod, array $uri): void
{
$this->logger->debug(message: "Request: $requestMethod $uri[1]");
$this->requestMethod = strtoupper(string: $requestMethod);
$this->uri = $uri;
$command = $this->uri[2];
if (empty($command) || !(($command == 'domains') || ($command == 'ping') || ($command == 'apidoc') || ($command == 'dyndns'))) {
$this->status = "404 Not Found";
$this->message = "Endpoint not found.";
} else {
try {
match ($command) {
'dyndns' => $this->handleDynDNS(),
'ping' => $this->handlePing(),
'domains' => $this->handleDomains(),
};
} catch (UnhandledMatchError) {
$this->status = '400 Bad Request';
$this->message = 'Unknown path: ' . $command;
}
}
if (!empty($this->status)) {
header(header: $_SERVER['SERVER_PROTOCOL'] . ' ' . $this->status);
}
if (!empty($this->response)) {
echo json_encode(value: [
'response' => $this->response
]);
} elseif (!empty($this->result)) {
echo json_encode(value: [
'result' => $this->result
]);
} elseif (!empty($this->message)) {
echo json_encode(value: [
'message' => $this->message
]);
} else {
echo json_encode(value: [
'message' => $this->message ?? 'Error: No message.'
]);
}
}
/**
* @return bool
*/
private function checkPassword(): bool
{ {
$headers = array_change_key_case(array: getallheaders(), case: CASE_UPPER); $headers = array_change_key_case(array: getallheaders(), case: CASE_UPPER);
$apiKey = $headers['X-API-KEY'] ?? ''; $apiKey = $headers['X-API-KEY'] ?? '';
@ -222,33 +318,10 @@ class RequestController
return true; return true;
} }
#[OA\Get(
path: '/domains/{name}',
operationId: 'getSingleDomain',
description: 'Returns information of a single domain specified by its domain name.',
summary: 'Returns a single domain.',
security: [
['Authorization' => []]
],
tags: ['Domains'],
parameters: [
new OA\Parameter(name: 'name', in: 'path', required: true, schema: new OA\Schema(type: 'string')),
],
responses: [
new OA\Response(
response: 200,
description: 'OK'
),
new OA\Response(
response: 401,
description: 'API key is missing or invalid.'
),
new OA\Response(
response: 404,
description: 'Domain not found.'
)]
)] /**
* @return void
*/
private function handleDomainsGetRequest(): void private function handleDomainsGetRequest(): void
{ {
$name = $this->uri[3] ?? ''; $name = $this->uri[3] ?? '';
@ -360,6 +433,9 @@ class RequestController
} }
/**
* @return void
*/
private function handleDomainsDeleteRequest(): void private function handleDomainsDeleteRequest(): void
{ {
$deleteData = fopen(filename: 'php://input', mode: 'r'); $deleteData = fopen(filename: 'php://input', mode: 'r');
@ -394,7 +470,7 @@ class RequestController
{ {
$this->logger->debug(message: 'handleDynDNS()'); $this->logger->debug(message: 'handleDynDNS()');
if ($this->validateApiKey()) { if ($this->checkPassword()) {
$host = $this->uri[3] ?? ''; $host = $this->uri[3] ?? '';
if (empty($host)) { if (empty($host)) {
@ -461,7 +537,7 @@ class RequestController
$panel = $this->panelRepository->findByName(name: $domain->getPanel()); $panel = $this->panelRepository->findByName(name: $domain->getPanel());
if (!empty($panel->getAaaa())) { if (!empty($panel->getAaaa())) {
$domainData = $this->apiClient->sendCommand( $domainData = $this->apiController->sendCommand(
requestType: 'GET', requestType: 'GET',
serverName: $panel->getName(), serverName: $panel->getName(),
versionIP: 6, versionIP: 6,
@ -469,7 +545,7 @@ class RequestController
command: 'domains/name/' . $domainName, command: 'domains/name/' . $domainName,
serverType: 'panel'); serverType: 'panel');
} else { } else {
$domainData = $this->apiClient->sendCommand( $domainData = $this->apiController->sendCommand(
requestType: 'GET', requestType: 'GET',
serverName: $panel->getName(), serverName: $panel->getName(),
versionIP: 4, versionIP: 4,
@ -482,7 +558,7 @@ class RequestController
$domainID = $domainDecodedData->id; $domainID = $domainDecodedData->id;
if (!empty($panel->getAaaa())) { if (!empty($panel->getAaaa())) {
$dnsData = $this->apiClient->sendCommand( $dnsData = $this->apiController->sendCommand(
requestType: 'GET', requestType: 'GET',
serverName: $panel->getName(), serverName: $panel->getName(),
versionIP: 6, versionIP: 6,
@ -490,7 +566,7 @@ class RequestController
command: 'dns/' . $domainID, command: 'dns/' . $domainID,
serverType: 'panel'); serverType: 'panel');
} else { } else {
$dnsData = $this->apiClient->sendCommand( $dnsData = $this->apiController->sendCommand(
requestType: 'GET', requestType: 'GET',
serverName: $panel->getName(), serverName: $panel->getName(),
versionIP: 4, versionIP: 4,
@ -531,7 +607,7 @@ class RequestController
]); ]);
if (!empty($panel->getAaaa())) { if (!empty($panel->getAaaa())) {
$result = $this->apiClient->sendCommand( $result = $this->apiController->sendCommand(
requestType: 'PUT', requestType: 'PUT',
serverName: $panel->getName(), serverName: $panel->getName(),
versionIP: 6, versionIP: 6,
@ -541,7 +617,7 @@ class RequestController
body: json_decode(json: $newDnsData, associative: true) body: json_decode(json: $newDnsData, associative: true)
); );
} else { } else {
$result = $this->apiClient->sendCommand( $result = $this->apiController->sendCommand(
requestType: 'PUT', requestType: 'PUT',
serverName: $panel->getName(), serverName: $panel->getName(),
versionIP: 4, versionIP: 4,
@ -569,6 +645,11 @@ class RequestController
} }
/**
* @param String $host
*
* @return string
*/
private function getDomain(string $host): string private function getDomain(string $host): string
{ {
$host = strtolower(string: trim(string: $host)); $host = strtolower(string: trim(string: $host));
@ -583,89 +664,5 @@ class RequestController
return $host; return $host;
} }
// private function apiDoc(): void
// {
// $srcDir = dirname(path: __DIR__);
// $requestControllerPath = $srcDir . '/Controller/RequestController.php';
//
// $openApi = Generator::scan(sources: [$requestControllerPath]);
// header(header: 'Content-Type: application/json');
//
// echo $openApi->toJson();
// exit(0);
// }
public function __construct(
private readonly ApiClient $apiClient,
private readonly ApikeyRepository $apikeyRepository,
private readonly DomainController $domainController,
private readonly DomainRepository $domainRepository,
private readonly DynDNSRepository $dynDNSRepository,
private readonly PanelRepository $panelRepository,
private readonly ConfigController $configController,
private readonly EncryptionController $encryptionController,
private readonly Logger $logger)
{
$this->baseDir = dirname(path: __DIR__, levels: 2) . '/';
$this->status = '';
$this->response = '';
$this->message = '';
$this->result = [];
}
public function handleRequest(string $requestMethod, array $uri): void
{
$this->logger->debug(message: "Request: $requestMethod $uri[1]");
$this->requestMethod = strtoupper(string: $requestMethod);
$this->uri = $uri;
$command = $this->uri[2];
// use my router class from address book?
$routes = ['ping', 'version', 'domains', 'apidoc', 'dyndns'];
if (empty($command) || !(in_array(needle: $command, haystack: $routes))) {
$this->status = "404 Not Found";
$this->message = "Endpoint not found.";
} else {
try {
match ($command) {
// server
'ping' => $this->handlePing(),
'version' => $this->getVersion(),
// domains
'domains' => $this->handleDomains(),
'dyndns' => $this->handleDynDNS(),
// 'apidoc' => $this->apiDoc(),
};
} catch (UnhandledMatchError) {
$this->status = '400 Bad Request';
$this->message = 'Unknown path: ' . $command;
}
}
// process api requests
if (!empty($this->status)) {
header(header: $_SERVER['SERVER_PROTOCOL'] . ' ' . $this->status);
}
if (!empty($this->response)) {
echo json_encode(value: [
'response' => $this->response
]);
} elseif (!empty($this->result)) {
echo json_encode(value: $this->result);
} elseif (!empty($this->message)) {
echo json_encode(value: [
'message' => $this->message
]);
} else {
echo json_encode(value: [
'message' => $this->message ?? 'Error: No message.'
]);
}
}
} }

View File

@ -5,20 +5,24 @@ namespace App\Entity;
use App\Controller\ConfigController; use App\Controller\ConfigController;
use App\Controller\EncryptionController; use App\Controller\EncryptionController;
use Exception; use Exception;
use SodiumException;
/**
*
*/
class Apikey class Apikey
{ {
public function __construct( public function __construct(
private int $id = 0, private int $id = 0,
private string $name = '', private string $name = '',
private string $apikey = '', private string $apikey = '',
private string $apikeyPrefix = '', private string $apikeyPrefix = '',
private readonly string $passphrase = '', private readonly string $passphrase = ''
private string $createdAt = ''
) )
{ {
if ($this->passphrase) { if ($this->passphrase) {
$configController = new ConfigController(quiet: true); $configController = new ConfigController();
$encryptionController = new EncryptionController(); $encryptionController = new EncryptionController();
$encryptionKey = $configController->getConfig(configKey: 'encryptionKey'); $encryptionKey = $configController->getConfig(configKey: 'encryptionKey');
@ -27,45 +31,82 @@ class Apikey
try { try {
$this->apikey = $encryptionController->safeEncrypt(message: $this->passphrase, key: $encryptionKey); $this->apikey = $encryptionController->safeEncrypt(message: $this->passphrase, key: $encryptionKey);
} catch (Exception $e) { } catch (Exception|SodiumException $e) {
exit($e->getMessage() . PHP_EOL); die($e->getMessage() . PHP_EOL);
} }
} }
} }
public function getCreatedAt(): string /**
* @return string
*/
public function getPassphrase(): string
{ {
return $this->createdAt; return $this->passphrase;
} }
/**
* @return String
*/
public function getApikey(): string public function getApikey(): string
{ {
return $this->apikey; return $this->apikey;
} }
/**
* @return string
*/
public function getApikeyPrefix(): string public function getApikeyPrefix(): string
{ {
return $this->apikeyPrefix; return $this->apikeyPrefix;
} }
/**
* @return int
*/
public function getId(): int public function getId(): int
{ {
return $this->id; return $this->id;
} }
/**
* @param int $id
*/
public function setId(int $id): void
{
$this->id = $id;
}
/**
* @return String
*/
public function getName(): string public function getName(): string
{ {
return $this->name; return $this->name;
} }
/**
* @param string $apikeyPrefix
*/
public function setApikeyPrefix(string $apikeyPrefix): void
{
$this->apikeyPrefix = $apikeyPrefix;
}
/**
* @param String $apiToken
*/
public function setApikey(string $apikey): void public function setApikey(string $apikey): void
{ {
$this->apikey = $apikey; $this->apikey = $apikey;
} }
/**
* @param String $name
*/
public function setName(string $name): void public function setName(string $name): void
{ {
$this->name = $name; $this->name = $name;

View File

@ -28,70 +28,6 @@ class KeyHelpDomain
private Target $target; private Target $target;
private Security $security; private Security $security;
private Apache $apache; 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 * @return Apache

View File

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

View File

@ -12,6 +12,7 @@ use SodiumException;
* *
*/ */
#[OAT\Schema(schema: 'nameserver')] #[OAT\Schema(schema: 'nameserver')]
class Nameserver class Nameserver
{ {
/** /**
@ -30,12 +31,10 @@ class Nameserver
private string $aaaa = '', private string $aaaa = '',
private readonly string $passphrase = '', private readonly string $passphrase = '',
private string $apikey = '', private string $apikey = '',
private string $apikeyPrefix = '', private string $apikeyPrefix = '')
private string $self = 'no'
)
{ {
if ($this->passphrase) { if ($this->passphrase) {
$configController = new ConfigController(quiet: false); $configController = new ConfigController();
$encryptionController = new EncryptionController(); $encryptionController = new EncryptionController();
$encryptionKey = $configController->getConfig(configKey: 'encryptionKey'); $encryptionKey = $configController->getConfig(configKey: 'encryptionKey');
@ -45,22 +44,12 @@ class Nameserver
try { try {
$this->apikey = $encryptionController->safeEncrypt(message: $this->passphrase, key: $encryptionKey); $this->apikey = $encryptionController->safeEncrypt(message: $this->passphrase, key: $encryptionKey);
} catch (Exception|SodiumException $e) { } catch (Exception|SodiumException $e) {
exit($e->getMessage() . PHP_EOL); die($e->getMessage() . PHP_EOL);
} }
} }
} }
public function getSelf(): string
{
return $this->self;
}
public function setSelf(string $self): void
{
$this->self = $self;
}
/** /**
* @return string * @return string
*/ */

View File

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

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,7 +3,7 @@ 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\EncryptionController;
use App\Entity\Apikey; use App\Entity\Apikey;
use PDO; use PDO;
@ -18,24 +18,27 @@ class ApikeyRepository
{} {}
/**
* @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, apikey_prefix, apikey
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(id: $result['id'], name: $result['name'], apikey: $result['apikey'], apikeyPrefix: $result['apikey_prefix']);
$apiKeys[] = $apikey; $apikeys[] = $apikey;
} }
return $apiKeys; return $apikeys;
} catch (PDOException $e) { } catch (PDOException $e) {
exit($e->getMessage()); exit($e->getMessage());
} }

View File

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

@ -2,7 +2,7 @@
namespace App\Repository; namespace App\Repository;
use App\Provider\DatabaseConnection; use App\Controller\DatabaseConnection;
use App\Entity\DynDNS; use App\Entity\DynDNS;
use Monolog\Logger; use Monolog\Logger;
use PDO; use PDO;

View File

@ -2,7 +2,7 @@
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;
@ -26,7 +26,7 @@ class NameserverRepository
{ {
$nameservers = []; $nameservers = [];
$sql = " $sql = "
SELECT id, name, a, aaaa, apikey, apikey_prefix, self SELECT id, name, a, aaaa, apikey, apikey_prefix
FROM " . DatabaseConnection::TABLE_NAMESERVERS . " FROM " . DatabaseConnection::TABLE_NAMESERVERS . "
ORDER BY name"; ORDER BY name";
@ -34,7 +34,7 @@ class NameserverRepository
$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'], apikeyPrefix: $result['apikey_prefix']);
$nameservers[] = $nameserver; $nameservers[] = $nameserver;
} }
return $nameservers; return $nameservers;
@ -50,7 +50,7 @@ class NameserverRepository
public function findFirst(): ?Nameserver public function findFirst(): ?Nameserver
{ {
$sql = " $sql = "
SELECT id, name, a, aaaa, apikey, apikey_prefix, self SELECT id, name, a, aaaa, apikey, apikey_prefix
FROM " . DatabaseConnection::TABLE_NAMESERVERS . " FROM " . DatabaseConnection::TABLE_NAMESERVERS . "
ORDER BY name"; ORDER BY name";
@ -58,7 +58,7 @@ class NameserverRepository
$statement = $this->databaseConnection->getConnection()->prepare(query: $sql); $statement = $this->databaseConnection->getConnection()->prepare(query: $sql);
$statement->execute(); $statement->execute();
$result = $statement->fetch(mode: PDO::FETCH_ASSOC); $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']); return new Nameserver(name: $result['name'], id: $result['id'], a: $result['a'], aaaa: $result['aaaa'], apikey: $result['apikey'], apikeyPrefix: $result['apikey_prefix']);
} catch (PDOException $e) { } catch (PDOException $e) {
exit($e->getMessage()); exit($e->getMessage());
} }
@ -73,7 +73,7 @@ class NameserverRepository
public function findByID(int $id): ?Nameserver public function findByID(int $id): ?Nameserver
{ {
$sql = " $sql = "
SELECT id, name, a, aaaa, apikey, apikey_prefix, self SELECT id, name, a, aaaa, apikey, apikey_prefix
FROM . " . DatabaseConnection::TABLE_NAMESERVERS . " FROM . " . DatabaseConnection::TABLE_NAMESERVERS . "
WHERE id = :id"; WHERE id = :id";
@ -82,7 +82,7 @@ class NameserverRepository
$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 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'], apikeyPrefix: $result['apikey_prefix']);
} else { } else {
return null; return null;
} }
@ -100,7 +100,7 @@ class NameserverRepository
public function findByName(string $name): ?Nameserver public function findByName(string $name): ?Nameserver
{ {
$sql = " $sql = "
SELECT id, name, a, aaaa, apikey, apikey_prefix, self SELECT id, name, a, aaaa, apikey, apikey_prefix
FROM " . DatabaseConnection::TABLE_NAMESERVERS . " FROM " . DatabaseConnection::TABLE_NAMESERVERS . "
WHERE name = :name"; WHERE name = :name";
@ -109,7 +109,7 @@ class NameserverRepository
$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'], apikey: $result['apikey'], apikeyPrefix: $result['apikey_prefix']);
} else { } else {
return null; return null;
} }
@ -131,17 +131,11 @@ class NameserverRepository
$aaaa = $nameserver->getAaaa(); $aaaa = $nameserver->getAaaa();
$apikey = $nameserver->getApikey(); $apikey = $nameserver->getApikey();
$apikeyPrefix = $nameserver->getApikeyPrefix(); $apikeyPrefix = $nameserver->getApikeyPrefix();
$self = $nameserver->getSelf();
if ($self === '') {
$selfValue = 'no';
} else {
$selfValue = $self;
}
$sql = " $sql = "
INSERT INTO " . DatabaseConnection::TABLE_NAMESERVERS . " (name, a, aaaa, apikey, apikey_prefix, self) INSERT INTO " . DatabaseConnection::TABLE_NAMESERVERS . " (name, a, aaaa, apikey, apikey_prefix)
VALUES (:name, :a, :aaaa, :apikey, :apikey_prefix, :self)"; VALUES (:name, :a, :aaaa, :apikey, :apikey_prefix)";
try { try {
$statement = $this->databaseConnection->getConnection()->prepare(query: $sql); $statement = $this->databaseConnection->getConnection()->prepare(query: $sql);
@ -150,7 +144,6 @@ class NameserverRepository
$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->bindParam(param: ':apikey_prefix', var: $apikeyPrefix);
$statement->bindParam(param: ':self', var: $selfValue);
$statement->execute(); $statement->execute();
return intval(value: $this->databaseConnection->getConnection()->lastInsertId()); return intval(value: $this->databaseConnection->getConnection()->lastInsertId());
@ -173,7 +166,6 @@ class NameserverRepository
$apikey = $nameserver->getApikey(); $apikey = $nameserver->getApikey();
$apikeyPrefix = $nameserver->getApikeyPrefix(); $apikeyPrefix = $nameserver->getApikeyPrefix();
$passphrase = $nameserver->getPassphrase(); $passphrase = $nameserver->getPassphrase();
$self =$nameserver->getSelf();
$current = $this->findByID(id: $id); $current = $this->findByID(id: $id);
@ -193,10 +185,6 @@ class NameserverRepository
$apikeyPrefix = $current->getApikeyPrefix(); $apikeyPrefix = $current->getApikeyPrefix();
} }
if (empty($self)) {
$self = $current->getSelf();
}
$sql = " $sql = "
UPDATE " . DatabaseConnection::TABLE_NAMESERVERS . " SET UPDATE " . DatabaseConnection::TABLE_NAMESERVERS . " SET
@ -204,8 +192,7 @@ class NameserverRepository
a = :a, a = :a,
aaaa = :aaaa, aaaa = :aaaa,
apikey = :apikey, apikey = :apikey,
apikey_prefix = :apikey_prefix, apikey_prefix = :apikey_prefix
self = :self
WHERE id = :id"; WHERE id = :id";
try { try {
@ -216,12 +203,11 @@ class NameserverRepository
$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->bindParam(param: 'apikey_prefix', var: $apikeyPrefix);
$statement->bindParam(param: 'self', var: $self);
$statement->execute(); $statement->execute();
try { try {
sodium_memzero(string: $apikey); sodium_memzero(string: $apikey);
} catch(SodiumException $e) { } catch(SodiumException $e) {
exit($e->getMessage() . PHP_EOL); die($e->getMessage() . PHP_EOL);
} }
return intval(value: $statement->rowCount()); return intval(value: $statement->rowCount());
} catch (PDOException $e) { } catch (PDOException $e) {

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;
@ -162,8 +162,6 @@ class PanelRepository
$apikey = $panel->getApikey(); $apikey = $panel->getApikey();
$apikeyPrefix = $panel->getApikeyPrefix(); $apikeyPrefix = $panel->getApikeyPrefix();
$passphrase = $panel->getPassphrase(); $passphrase = $panel->getPassphrase();
$self = $panel->getSelf();
echo 'self: ' . $self;
$current = $this->findByID(id: $id); $current = $this->findByID(id: $id);
@ -187,6 +185,7 @@ class PanelRepository
$self = $current->getSelf(); $self = $current->getSelf();
} }
$sql = " $sql = "
UPDATE " . DatabaseConnection::TABLE_PANELS . " SET UPDATE " . DatabaseConnection::TABLE_PANELS . " SET
name = :name, name = :name,

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,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;
}