work on backup storages
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
This commit is contained in:
@@ -30,7 +30,7 @@ return [
|
|||||||
'icon' => 'fa-solid fa-sliders',
|
'icon' => 'fa-solid fa-sliders',
|
||||||
'advanced_mode' => true,
|
'advanced_mode' => true,
|
||||||
'fields' => [
|
'fields' => [
|
||||||
'system_backup_enabled' => [
|
'backup_enabled' => [
|
||||||
'label' => lng('serversettings.backup_enabled'),
|
'label' => lng('serversettings.backup_enabled'),
|
||||||
'settinggroup' => 'backup',
|
'settinggroup' => 'backup',
|
||||||
'varname' => 'enabled',
|
'varname' => 'enabled',
|
||||||
@@ -40,74 +40,39 @@ return [
|
|||||||
'overview_option' => true,
|
'overview_option' => true,
|
||||||
'cronmodule' => 'froxlor/backup'
|
'cronmodule' => 'froxlor/backup'
|
||||||
],
|
],
|
||||||
'system_backup_type' => [
|
'backup_default_storage' => [
|
||||||
'label' => lng('serversettings.backup_type'),
|
'label' => lng('serversettings.backup_default_storage'),
|
||||||
'settinggroup' => 'backup',
|
'settinggroup' => 'backup',
|
||||||
'varname' => 'type',
|
'varname' => 'default_storage',
|
||||||
'type' => 'select',
|
'type' => 'select',
|
||||||
'default' => 'Local',
|
'default' => '1',
|
||||||
'select_var' => [
|
'option_options_method' => [
|
||||||
'Local' => lng('serversettings.local'),
|
'\\Froxlor\\Backup\\Backup',
|
||||||
'SFTP' => lng('serversettings.sftp'),
|
'getBackupStorages'
|
||||||
'FTPS' => lng('serversettings.ftps'),
|
|
||||||
'S3' => lng('serversettings.s3'),
|
|
||||||
],
|
],
|
||||||
'save_method' => 'storeSettingField',
|
'save_method' => 'storeSettingField'
|
||||||
'overview_option' => true,
|
|
||||||
],
|
],
|
||||||
'system_backup_region' => [
|
'backup_default_retention' => [
|
||||||
'label' => lng('serversettings.backup_region'),
|
'label' => lng('serversettings.backup_default_retention'),
|
||||||
'settinggroup' => 'backup',
|
'settinggroup' => 'backup',
|
||||||
'varname' => 'region',
|
'varname' => 'default_retention',
|
||||||
'type' => 'text',
|
'type' => 'number',
|
||||||
'default' => 'eu-central-1',
|
'default' => 3,
|
||||||
|
'min' => 0,
|
||||||
'save_method' => 'storeSettingField',
|
'save_method' => 'storeSettingField',
|
||||||
],
|
],
|
||||||
'system_backup_bucket' => [
|
'backup_default_customer_access' => [
|
||||||
'label' => lng('serversettings.backup_bucket'),
|
'label' => lng('serversettings.backup_default_customer_access'),
|
||||||
'settinggroup' => 'backup',
|
'settinggroup' => 'backup',
|
||||||
'varname' => 'bucket',
|
'varname' => 'default_customer_access',
|
||||||
'type' => 'text',
|
'type' => 'checkbox',
|
||||||
'default' => '',
|
'default' => true,
|
||||||
'save_method' => 'storeSettingField',
|
'save_method' => 'storeSettingField',
|
||||||
],
|
],
|
||||||
'system_backup_destination_path' => [
|
'backup_default_pgp_public_key' => [
|
||||||
'label' => lng('serversettings.backup_destination_path'),
|
'label' => lng('serversettings.backup_default_pgp_public_key'),
|
||||||
'settinggroup' => 'backup',
|
'settinggroup' => 'backup',
|
||||||
'varname' => 'destination_path',
|
'varname' => 'default_pgp_public_key',
|
||||||
'type' => 'text',
|
|
||||||
'string_type' => 'confdir',
|
|
||||||
'default' => '/srv/backups/',
|
|
||||||
'save_method' => 'storeSettingField',
|
|
||||||
],
|
|
||||||
'system_backup_hostname' => [
|
|
||||||
'label' => lng('serversettings.backup_hostname'),
|
|
||||||
'settinggroup' => 'backup',
|
|
||||||
'varname' => 'hostname',
|
|
||||||
'type' => 'text',
|
|
||||||
'default' => '',
|
|
||||||
'save_method' => 'storeSettingField',
|
|
||||||
],
|
|
||||||
'system_backup_username' => [
|
|
||||||
'label' => lng('serversettings.backup_username'),
|
|
||||||
'settinggroup' => 'backup',
|
|
||||||
'varname' => 'username',
|
|
||||||
'type' => 'text',
|
|
||||||
'default' => '',
|
|
||||||
'save_method' => 'storeSettingField',
|
|
||||||
],
|
|
||||||
'system_backup_password' => [
|
|
||||||
'label' => lng('serversettings.backup_password'),
|
|
||||||
'settinggroup' => 'backup',
|
|
||||||
'varname' => 'password',
|
|
||||||
'type' => 'password',
|
|
||||||
'default' => '',
|
|
||||||
'save_method' => 'storeSettingField',
|
|
||||||
],
|
|
||||||
'system_backup_pgp_public_key' => [
|
|
||||||
'label' => lng('serversettings.backup_pgp_public_key'),
|
|
||||||
'settinggroup' => 'backup',
|
|
||||||
'varname' => 'pgp_public_key',
|
|
||||||
'type' => 'textarea',
|
'type' => 'textarea',
|
||||||
'default' => '',
|
'default' => '',
|
||||||
'save_method' => 'storeSettingField',
|
'save_method' => 'storeSettingField',
|
||||||
@@ -116,15 +81,6 @@ return [
|
|||||||
'checkPgpPublicKeySetting'
|
'checkPgpPublicKeySetting'
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
'system_backup_retention' => [
|
|
||||||
'label' => lng('serversettings.backup_retention'),
|
|
||||||
'settinggroup' => 'backup',
|
|
||||||
'varname' => 'retention',
|
|
||||||
'type' => 'number',
|
|
||||||
'default' => 3,
|
|
||||||
'min' => 0,
|
|
||||||
'save_method' => 'storeSettingField',
|
|
||||||
],
|
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -236,7 +236,7 @@ if (($page == 'customers' || $page == 'overview') && $userinfo['customers'] != '
|
|||||||
$result_json = BackupStorages::getLocal($userinfo)->listing();
|
$result_json = BackupStorages::getLocal($userinfo)->listing();
|
||||||
$result_decoded = json_decode($result_json, true)['data']['list'];
|
$result_decoded = json_decode($result_json, true)['data']['list'];
|
||||||
foreach ($result_decoded as $storagedata) {
|
foreach ($result_decoded as $storagedata) {
|
||||||
$backup_storages[$storagedata['id']] = $storagedata['description'] . ' (' . $storagedata['type'] . ')';
|
$backup_storages[$storagedata['id']] = "[" . $storagedata['type'] . "] " . html_entity_decode($storagedata['description']);
|
||||||
}
|
}
|
||||||
} catch (Exception $e) {
|
} catch (Exception $e) {
|
||||||
/* just none */
|
/* just none */
|
||||||
@@ -335,7 +335,7 @@ if (($page == 'customers' || $page == 'overview') && $userinfo['customers'] != '
|
|||||||
$result_json = BackupStorages::getLocal($userinfo)->listing();
|
$result_json = BackupStorages::getLocal($userinfo)->listing();
|
||||||
$result_decoded = json_decode($result_json, true)['data']['list'];
|
$result_decoded = json_decode($result_json, true)['data']['list'];
|
||||||
foreach ($result_decoded as $storagedata) {
|
foreach ($result_decoded as $storagedata) {
|
||||||
$backup_storages[$storagedata['id']] = $storagedata['description'] . ' (' . $storagedata['type'] . ')';
|
$backup_storages[$storagedata['id']] = "[" . $storagedata['type'] . "] " . html_entity_decode($storagedata['description']);
|
||||||
}
|
}
|
||||||
} catch (Exception $e) {
|
} catch (Exception $e) {
|
||||||
/* just none */
|
/* just none */
|
||||||
|
|||||||
@@ -46,6 +46,7 @@
|
|||||||
"ext-fileinfo": "*",
|
"ext-fileinfo": "*",
|
||||||
"ext-gmp": "*",
|
"ext-gmp": "*",
|
||||||
"ext-gd": "*",
|
"ext-gd": "*",
|
||||||
|
"ext-ftp": "*",
|
||||||
"phpmailer/phpmailer": "~6.0",
|
"phpmailer/phpmailer": "~6.0",
|
||||||
"monolog/monolog": "^1.24",
|
"monolog/monolog": "^1.24",
|
||||||
"robthree/twofactorauth": "^1.6",
|
"robthree/twofactorauth": "^1.6",
|
||||||
|
|||||||
131
composer.lock
generated
131
composer.lock
generated
@@ -561,16 +561,16 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/console",
|
"name": "symfony/console",
|
||||||
"version": "v5.4.22",
|
"version": "v5.4.24",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/symfony/console.git",
|
"url": "https://github.com/symfony/console.git",
|
||||||
"reference": "3cd51fd2e6c461ca678f84d419461281bd87a0a8"
|
"reference": "560fc3ed7a43e6d30ea94a07d77f9a60b8ed0fb8"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/symfony/console/zipball/3cd51fd2e6c461ca678f84d419461281bd87a0a8",
|
"url": "https://api.github.com/repos/symfony/console/zipball/560fc3ed7a43e6d30ea94a07d77f9a60b8ed0fb8",
|
||||||
"reference": "3cd51fd2e6c461ca678f84d419461281bd87a0a8",
|
"reference": "560fc3ed7a43e6d30ea94a07d77f9a60b8ed0fb8",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
@@ -640,7 +640,7 @@
|
|||||||
"terminal"
|
"terminal"
|
||||||
],
|
],
|
||||||
"support": {
|
"support": {
|
||||||
"source": "https://github.com/symfony/console/tree/v5.4.22"
|
"source": "https://github.com/symfony/console/tree/v5.4.24"
|
||||||
},
|
},
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
@@ -656,7 +656,7 @@
|
|||||||
"type": "tidelift"
|
"type": "tidelift"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"time": "2023-03-25T09:27:28+00:00"
|
"time": "2023-05-26T05:13:16+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/deprecation-contracts",
|
"name": "symfony/deprecation-contracts",
|
||||||
@@ -1547,16 +1547,16 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "twig/twig",
|
"name": "twig/twig",
|
||||||
"version": "v3.5.1",
|
"version": "v3.7.0",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/twigphp/Twig.git",
|
"url": "https://github.com/twigphp/Twig.git",
|
||||||
"reference": "a6e0510cc793912b451fd40ab983a1d28f611c15"
|
"reference": "5cf942bbab3df42afa918caeba947f1b690af64b"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/twigphp/Twig/zipball/a6e0510cc793912b451fd40ab983a1d28f611c15",
|
"url": "https://api.github.com/repos/twigphp/Twig/zipball/5cf942bbab3df42afa918caeba947f1b690af64b",
|
||||||
"reference": "a6e0510cc793912b451fd40ab983a1d28f611c15",
|
"reference": "5cf942bbab3df42afa918caeba947f1b690af64b",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
@@ -1565,15 +1565,10 @@
|
|||||||
"symfony/polyfill-mbstring": "^1.3"
|
"symfony/polyfill-mbstring": "^1.3"
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
"psr/container": "^1.0",
|
"psr/container": "^1.0|^2.0",
|
||||||
"symfony/phpunit-bridge": "^4.4.9|^5.0.9|^6.0"
|
"symfony/phpunit-bridge": "^4.4.9|^5.0.9|^6.0"
|
||||||
},
|
},
|
||||||
"type": "library",
|
"type": "library",
|
||||||
"extra": {
|
|
||||||
"branch-alias": {
|
|
||||||
"dev-master": "3.5-dev"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"autoload": {
|
"autoload": {
|
||||||
"psr-4": {
|
"psr-4": {
|
||||||
"Twig\\": "src/"
|
"Twig\\": "src/"
|
||||||
@@ -1607,7 +1602,7 @@
|
|||||||
],
|
],
|
||||||
"support": {
|
"support": {
|
||||||
"issues": "https://github.com/twigphp/Twig/issues",
|
"issues": "https://github.com/twigphp/Twig/issues",
|
||||||
"source": "https://github.com/twigphp/Twig/tree/v3.5.1"
|
"source": "https://github.com/twigphp/Twig/tree/v3.7.0"
|
||||||
},
|
},
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
@@ -1619,20 +1614,20 @@
|
|||||||
"type": "tidelift"
|
"type": "tidelift"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"time": "2023-02-08T07:49:20+00:00"
|
"time": "2023-07-26T07:16:09+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "voku/anti-xss",
|
"name": "voku/anti-xss",
|
||||||
"version": "4.1.41",
|
"version": "4.1.42",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/voku/anti-xss.git",
|
"url": "https://github.com/voku/anti-xss.git",
|
||||||
"reference": "55a403436494e44a2547a8d42de68e6cad4bca1d"
|
"reference": "bca1f8607e55a3c5077483615cd93bd8f11bd675"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/voku/anti-xss/zipball/55a403436494e44a2547a8d42de68e6cad4bca1d",
|
"url": "https://api.github.com/repos/voku/anti-xss/zipball/bca1f8607e55a3c5077483615cd93bd8f11bd675",
|
||||||
"reference": "55a403436494e44a2547a8d42de68e6cad4bca1d",
|
"reference": "bca1f8607e55a3c5077483615cd93bd8f11bd675",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
@@ -1678,7 +1673,7 @@
|
|||||||
],
|
],
|
||||||
"support": {
|
"support": {
|
||||||
"issues": "https://github.com/voku/anti-xss/issues",
|
"issues": "https://github.com/voku/anti-xss/issues",
|
||||||
"source": "https://github.com/voku/anti-xss/tree/4.1.41"
|
"source": "https://github.com/voku/anti-xss/tree/4.1.42"
|
||||||
},
|
},
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
@@ -1702,7 +1697,7 @@
|
|||||||
"type": "tidelift"
|
"type": "tidelift"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"time": "2023-02-12T15:56:55+00:00"
|
"time": "2023-07-03T14:40:46+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "voku/portable-ascii",
|
"name": "voku/portable-ascii",
|
||||||
@@ -2151,16 +2146,16 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "nikic/php-parser",
|
"name": "nikic/php-parser",
|
||||||
"version": "v4.15.4",
|
"version": "v4.16.0",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/nikic/PHP-Parser.git",
|
"url": "https://github.com/nikic/PHP-Parser.git",
|
||||||
"reference": "6bb5176bc4af8bcb7d926f88718db9b96a2d4290"
|
"reference": "19526a33fb561ef417e822e85f08a00db4059c17"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/6bb5176bc4af8bcb7d926f88718db9b96a2d4290",
|
"url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/19526a33fb561ef417e822e85f08a00db4059c17",
|
||||||
"reference": "6bb5176bc4af8bcb7d926f88718db9b96a2d4290",
|
"reference": "19526a33fb561ef417e822e85f08a00db4059c17",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
@@ -2201,22 +2196,22 @@
|
|||||||
],
|
],
|
||||||
"support": {
|
"support": {
|
||||||
"issues": "https://github.com/nikic/PHP-Parser/issues",
|
"issues": "https://github.com/nikic/PHP-Parser/issues",
|
||||||
"source": "https://github.com/nikic/PHP-Parser/tree/v4.15.4"
|
"source": "https://github.com/nikic/PHP-Parser/tree/v4.16.0"
|
||||||
},
|
},
|
||||||
"time": "2023-03-05T19:49:14+00:00"
|
"time": "2023-06-25T14:52:30+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "pdepend/pdepend",
|
"name": "pdepend/pdepend",
|
||||||
"version": "2.13.0",
|
"version": "2.14.0",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/pdepend/pdepend.git",
|
"url": "https://github.com/pdepend/pdepend.git",
|
||||||
"reference": "31be7cd4f305f3f7b52af99c1cb13fc938d1cfad"
|
"reference": "1121d4b04af06e33e9659bac3a6741b91cab1de1"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/pdepend/pdepend/zipball/31be7cd4f305f3f7b52af99c1cb13fc938d1cfad",
|
"url": "https://api.github.com/repos/pdepend/pdepend/zipball/1121d4b04af06e33e9659bac3a6741b91cab1de1",
|
||||||
"reference": "31be7cd4f305f3f7b52af99c1cb13fc938d1cfad",
|
"reference": "1121d4b04af06e33e9659bac3a6741b91cab1de1",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
@@ -2250,9 +2245,15 @@
|
|||||||
"BSD-3-Clause"
|
"BSD-3-Clause"
|
||||||
],
|
],
|
||||||
"description": "Official version of pdepend to be handled with Composer",
|
"description": "Official version of pdepend to be handled with Composer",
|
||||||
|
"keywords": [
|
||||||
|
"PHP Depend",
|
||||||
|
"PHP_Depend",
|
||||||
|
"dev",
|
||||||
|
"pdepend"
|
||||||
|
],
|
||||||
"support": {
|
"support": {
|
||||||
"issues": "https://github.com/pdepend/pdepend/issues",
|
"issues": "https://github.com/pdepend/pdepend/issues",
|
||||||
"source": "https://github.com/pdepend/pdepend/tree/2.13.0"
|
"source": "https://github.com/pdepend/pdepend/tree/2.14.0"
|
||||||
},
|
},
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
@@ -2260,7 +2261,7 @@
|
|||||||
"type": "tidelift"
|
"type": "tidelift"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"time": "2023-02-28T20:56:15+00:00"
|
"time": "2023-05-26T13:15:18+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "phar-io/manifest",
|
"name": "phar-io/manifest",
|
||||||
@@ -2582,16 +2583,16 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "phpstan/phpstan",
|
"name": "phpstan/phpstan",
|
||||||
"version": "1.10.14",
|
"version": "1.10.26",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/phpstan/phpstan.git",
|
"url": "https://github.com/phpstan/phpstan.git",
|
||||||
"reference": "d232901b09e67538e5c86a724be841bea5768a7c"
|
"reference": "5d660cbb7e1b89253a47147ae44044f49832351f"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/phpstan/phpstan/zipball/d232901b09e67538e5c86a724be841bea5768a7c",
|
"url": "https://api.github.com/repos/phpstan/phpstan/zipball/5d660cbb7e1b89253a47147ae44044f49832351f",
|
||||||
"reference": "d232901b09e67538e5c86a724be841bea5768a7c",
|
"reference": "5d660cbb7e1b89253a47147ae44044f49832351f",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
@@ -2640,7 +2641,7 @@
|
|||||||
"type": "tidelift"
|
"type": "tidelift"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"time": "2023-04-19T13:47:27+00:00"
|
"time": "2023-07-19T12:44:37+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "phpunit/php-code-coverage",
|
"name": "phpunit/php-code-coverage",
|
||||||
@@ -2962,16 +2963,16 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "phpunit/phpunit",
|
"name": "phpunit/phpunit",
|
||||||
"version": "9.6.7",
|
"version": "9.6.10",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/sebastianbergmann/phpunit.git",
|
"url": "https://github.com/sebastianbergmann/phpunit.git",
|
||||||
"reference": "c993f0d3b0489ffc42ee2fe0bd645af1538a63b2"
|
"reference": "a6d351645c3fe5a30f5e86be6577d946af65a328"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/c993f0d3b0489ffc42ee2fe0bd645af1538a63b2",
|
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/a6d351645c3fe5a30f5e86be6577d946af65a328",
|
||||||
"reference": "c993f0d3b0489ffc42ee2fe0bd645af1538a63b2",
|
"reference": "a6d351645c3fe5a30f5e86be6577d946af65a328",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
@@ -3045,7 +3046,7 @@
|
|||||||
"support": {
|
"support": {
|
||||||
"issues": "https://github.com/sebastianbergmann/phpunit/issues",
|
"issues": "https://github.com/sebastianbergmann/phpunit/issues",
|
||||||
"security": "https://github.com/sebastianbergmann/phpunit/security/policy",
|
"security": "https://github.com/sebastianbergmann/phpunit/security/policy",
|
||||||
"source": "https://github.com/sebastianbergmann/phpunit/tree/9.6.7"
|
"source": "https://github.com/sebastianbergmann/phpunit/tree/9.6.10"
|
||||||
},
|
},
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
@@ -3061,7 +3062,7 @@
|
|||||||
"type": "tidelift"
|
"type": "tidelift"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"time": "2023-04-14T08:58:40+00:00"
|
"time": "2023-07-10T04:04:23+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "sebastian/cli-parser",
|
"name": "sebastian/cli-parser",
|
||||||
@@ -3363,16 +3364,16 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "sebastian/diff",
|
"name": "sebastian/diff",
|
||||||
"version": "4.0.4",
|
"version": "4.0.5",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/sebastianbergmann/diff.git",
|
"url": "https://github.com/sebastianbergmann/diff.git",
|
||||||
"reference": "3461e3fccc7cfdfc2720be910d3bd73c69be590d"
|
"reference": "74be17022044ebaaecfdf0c5cd504fc9cd5a7131"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/3461e3fccc7cfdfc2720be910d3bd73c69be590d",
|
"url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/74be17022044ebaaecfdf0c5cd504fc9cd5a7131",
|
||||||
"reference": "3461e3fccc7cfdfc2720be910d3bd73c69be590d",
|
"reference": "74be17022044ebaaecfdf0c5cd504fc9cd5a7131",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
@@ -3417,7 +3418,7 @@
|
|||||||
],
|
],
|
||||||
"support": {
|
"support": {
|
||||||
"issues": "https://github.com/sebastianbergmann/diff/issues",
|
"issues": "https://github.com/sebastianbergmann/diff/issues",
|
||||||
"source": "https://github.com/sebastianbergmann/diff/tree/4.0.4"
|
"source": "https://github.com/sebastianbergmann/diff/tree/4.0.5"
|
||||||
},
|
},
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
@@ -3425,7 +3426,7 @@
|
|||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"time": "2020-10-26T13:10:38+00:00"
|
"time": "2023-05-07T05:35:17+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "sebastian/environment",
|
"name": "sebastian/environment",
|
||||||
@@ -4227,16 +4228,16 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/dependency-injection",
|
"name": "symfony/dependency-injection",
|
||||||
"version": "v5.4.22",
|
"version": "v5.4.25",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/symfony/dependency-injection.git",
|
"url": "https://github.com/symfony/dependency-injection.git",
|
||||||
"reference": "e1b7c1432efb4ad1dd89d62906187271e2601ed9"
|
"reference": "f0410c30a6c86bbce6c719c2b5cfc343362b982e"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/symfony/dependency-injection/zipball/e1b7c1432efb4ad1dd89d62906187271e2601ed9",
|
"url": "https://api.github.com/repos/symfony/dependency-injection/zipball/f0410c30a6c86bbce6c719c2b5cfc343362b982e",
|
||||||
"reference": "e1b7c1432efb4ad1dd89d62906187271e2601ed9",
|
"reference": "f0410c30a6c86bbce6c719c2b5cfc343362b982e",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
@@ -4296,7 +4297,7 @@
|
|||||||
"description": "Allows you to standardize and centralize the way objects are constructed in your application",
|
"description": "Allows you to standardize and centralize the way objects are constructed in your application",
|
||||||
"homepage": "https://symfony.com",
|
"homepage": "https://symfony.com",
|
||||||
"support": {
|
"support": {
|
||||||
"source": "https://github.com/symfony/dependency-injection/tree/v5.4.22"
|
"source": "https://github.com/symfony/dependency-injection/tree/v5.4.25"
|
||||||
},
|
},
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
@@ -4312,20 +4313,20 @@
|
|||||||
"type": "tidelift"
|
"type": "tidelift"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"time": "2023-03-10T10:02:45+00:00"
|
"time": "2023-06-24T09:45:28+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/filesystem",
|
"name": "symfony/filesystem",
|
||||||
"version": "v5.4.21",
|
"version": "v5.4.25",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/symfony/filesystem.git",
|
"url": "https://github.com/symfony/filesystem.git",
|
||||||
"reference": "e75960b1bbfd2b8c9e483e0d74811d555ca3de9f"
|
"reference": "0ce3a62c9579a53358d3a7eb6b3dfb79789a6364"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/symfony/filesystem/zipball/e75960b1bbfd2b8c9e483e0d74811d555ca3de9f",
|
"url": "https://api.github.com/repos/symfony/filesystem/zipball/0ce3a62c9579a53358d3a7eb6b3dfb79789a6364",
|
||||||
"reference": "e75960b1bbfd2b8c9e483e0d74811d555ca3de9f",
|
"reference": "0ce3a62c9579a53358d3a7eb6b3dfb79789a6364",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
@@ -4360,7 +4361,7 @@
|
|||||||
"description": "Provides basic utilities for the filesystem",
|
"description": "Provides basic utilities for the filesystem",
|
||||||
"homepage": "https://symfony.com",
|
"homepage": "https://symfony.com",
|
||||||
"support": {
|
"support": {
|
||||||
"source": "https://github.com/symfony/filesystem/tree/v5.4.21"
|
"source": "https://github.com/symfony/filesystem/tree/v5.4.25"
|
||||||
},
|
},
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
@@ -4376,7 +4377,7 @@
|
|||||||
"type": "tidelift"
|
"type": "tidelift"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"time": "2023-02-14T08:03:56+00:00"
|
"time": "2023-05-31T13:04:02+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/polyfill-php81",
|
"name": "symfony/polyfill-php81",
|
||||||
|
|||||||
@@ -705,6 +705,8 @@ opcache.validate_timestamps'),
|
|||||||
('backup', 'enabled', 0),
|
('backup', 'enabled', 0),
|
||||||
('backup', 'default_storage', '1'),
|
('backup', 'default_storage', '1'),
|
||||||
('backup', 'default_customer_access', '1'),
|
('backup', 'default_customer_access', '1'),
|
||||||
|
('backup', 'default_pgp_public_key', ''),
|
||||||
|
('backup', 'default_retention', '3'),
|
||||||
('api', 'enabled', '0'),
|
('api', 'enabled', '0'),
|
||||||
('api', 'customer_default', '1'),
|
('api', 'customer_default', '1'),
|
||||||
('2fa', 'enabled', '1'),
|
('2fa', 'enabled', '1'),
|
||||||
@@ -1079,8 +1081,8 @@ CREATE TABLE `panel_backup_storages` (
|
|||||||
`destination_path` varchar(255) NOT NULL,
|
`destination_path` varchar(255) NOT NULL,
|
||||||
`hostname` varchar(255) NULL,
|
`hostname` varchar(255) NULL,
|
||||||
`username` varchar(255) NULL,
|
`username` varchar(255) NULL,
|
||||||
`password` varchar(255) NULL,
|
`password` text,
|
||||||
`pgp_public_key` varchar(255) NULL,
|
`pgp_public_key` text,
|
||||||
`retention` int(3) NOT NULL DEFAULT 3,
|
`retention` int(3) NOT NULL DEFAULT 3,
|
||||||
PRIMARY KEY (`id`)
|
PRIMARY KEY (`id`)
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci;
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci;
|
||||||
|
|||||||
@@ -73,8 +73,8 @@ if (Froxlor::isDatabaseVersion('202304260')) {
|
|||||||
`destination_path` varchar(255) NOT NULL,
|
`destination_path` varchar(255) NOT NULL,
|
||||||
`hostname` varchar(255) NULL,
|
`hostname` varchar(255) NULL,
|
||||||
`username` varchar(255) NULL,
|
`username` varchar(255) NULL,
|
||||||
`password` varchar(255) NULL,
|
`password` text,
|
||||||
`pgp_public_key` varchar(255) NULL,
|
`pgp_public_key` text,
|
||||||
`retention` int(3) NOT NULL DEFAULT 3,
|
`retention` int(3) NOT NULL DEFAULT 3,
|
||||||
PRIMARY KEY (`id`)
|
PRIMARY KEY (`id`)
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci;";
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci;";
|
||||||
@@ -105,6 +105,8 @@ if (Froxlor::isDatabaseVersion('202304260')) {
|
|||||||
Settings::AddNew('backup.enabled', 0);
|
Settings::AddNew('backup.enabled', 0);
|
||||||
Settings::AddNew('backup.default_storage', 1);
|
Settings::AddNew('backup.default_storage', 1);
|
||||||
Settings::AddNew('backup.default_customer_access', 1);
|
Settings::AddNew('backup.default_customer_access', 1);
|
||||||
|
Settings::AddNew('backup.default_pgp_public_key', '');
|
||||||
|
Settings::AddNew('backup.default_retention', 3);
|
||||||
Update::lastStepStatus(0);
|
Update::lastStepStatus(0);
|
||||||
|
|
||||||
Update::showUpdateStep("Adjusting cronjobs");
|
Update::showUpdateStep("Adjusting cronjobs");
|
||||||
|
|||||||
@@ -73,8 +73,8 @@ class BackupStorages extends ApiCommand implements ResourceEntity
|
|||||||
$this->logger()->logAction(FroxlorLogger::ADM_ACTION, LOG_INFO, "[API] list backup storages");
|
$this->logger()->logAction(FroxlorLogger::ADM_ACTION, LOG_INFO, "[API] list backup storages");
|
||||||
$query_fields = [];
|
$query_fields = [];
|
||||||
$result_stmt = Database::prepare("
|
$result_stmt = Database::prepare("
|
||||||
SELECT * FROM `" . TABLE_PANEL_BACKUP_STORAGES . "`
|
SELECT * FROM `" . TABLE_PANEL_BACKUP_STORAGES . "` ". $this->getSearchWhere($query_fields) . $this->getOrderBy() . $this->getLimit()
|
||||||
");
|
);
|
||||||
Database::pexecute($result_stmt, $query_fields, true, true);
|
Database::pexecute($result_stmt, $query_fields, true, true);
|
||||||
$result = [];
|
$result = [];
|
||||||
while ($row = $result_stmt->fetch(PDO::FETCH_ASSOC)) {
|
while ($row = $result_stmt->fetch(PDO::FETCH_ASSOC)) {
|
||||||
|
|||||||
@@ -95,7 +95,8 @@ class Backups extends ApiCommand implements ResourceEntity
|
|||||||
FROM `" . TABLE_PANEL_BACKUPS . "` `b`
|
FROM `" . TABLE_PANEL_BACKUPS . "` `b`
|
||||||
LEFT JOIN `" . TABLE_PANEL_ADMINS . "` `a` USING(`adminid`)
|
LEFT JOIN `" . TABLE_PANEL_ADMINS . "` `a` USING(`adminid`)
|
||||||
WHERE `b`.`customerid` IN (" . implode(', ', $customer_ids) . ")
|
WHERE `b`.`customerid` IN (" . implode(', ', $customer_ids) . ")
|
||||||
");
|
" . $this->getSearchWhere($query_fields, true) . $this->getOrderBy() . $this->getLimit()
|
||||||
|
);
|
||||||
Database::pexecute($result_stmt, $query_fields, true, true);
|
Database::pexecute($result_stmt, $query_fields, true, true);
|
||||||
$result = [];
|
$result = [];
|
||||||
while ($row = $result_stmt->fetch(PDO::FETCH_ASSOC)) {
|
while ($row = $result_stmt->fetch(PDO::FETCH_ASSOC)) {
|
||||||
|
|||||||
53
lib/Froxlor/Backup/Backup.php
Normal file
53
lib/Froxlor/Backup/Backup.php
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This file is part of the Froxlor project.
|
||||||
|
* Copyright (c) 2010 the Froxlor Team (see authors).
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, you can also view it online at
|
||||||
|
* https://files.froxlor.org/misc/COPYING.txt
|
||||||
|
*
|
||||||
|
* @copyright the authors
|
||||||
|
* @author Froxlor team <team@froxlor.org>
|
||||||
|
* @license https://files.froxlor.org/misc/COPYING.txt GPLv2
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Froxlor\Backup;
|
||||||
|
|
||||||
|
use Froxlor\Database\Database;
|
||||||
|
use PDO;
|
||||||
|
|
||||||
|
class Backup
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* returns an array of existing backup-storages
|
||||||
|
* in our database for the settings-array
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public static function getBackupStorages(): array
|
||||||
|
{
|
||||||
|
$storages_array = [
|
||||||
|
0 => lng('backup.storage_none')
|
||||||
|
];
|
||||||
|
// get all storages
|
||||||
|
$result_stmt = Database::query("SELECT id, type, description FROM `" . TABLE_PANEL_BACKUP_STORAGES . "` ORDER BY type, description");
|
||||||
|
while ($row = $result_stmt->fetch(PDO::FETCH_ASSOC)) {
|
||||||
|
if (!isset($storages_array[$row['id']]) && !in_array($row['id'], $storages_array)) {
|
||||||
|
$storages_array[$row['id']] = "[" . $row['type'] . "] " . html_entity_decode($row['description']);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $storages_array;
|
||||||
|
}
|
||||||
|
}
|
||||||
98
lib/Froxlor/Backup/Storages/Ftp.php
Normal file
98
lib/Froxlor/Backup/Storages/Ftp.php
Normal file
@@ -0,0 +1,98 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Froxlor\Backup\Storages;
|
||||||
|
|
||||||
|
use Exception;
|
||||||
|
use Froxlor\FileDir;
|
||||||
|
|
||||||
|
class Ftp extends Storage
|
||||||
|
{
|
||||||
|
private $ftp_conn = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return bool
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
public function init(): bool
|
||||||
|
{
|
||||||
|
$hostname = $this->sData['storage']['hostname'] ?? '';
|
||||||
|
$username = $this->sData['storage']['username'] ?? '';
|
||||||
|
$password = $this->sData['storage']['password'] ?? '';
|
||||||
|
if (!empty($hostname) && !empty($username) && !empty($password)) {
|
||||||
|
$tmp = explode(":", $hostname);
|
||||||
|
$hostname = $tmp[0];
|
||||||
|
$port = $tmp[1] ?? 21;
|
||||||
|
$this->ftp_conn = ftp_connect($hostname, $port);
|
||||||
|
if ($this->ftp_conn === false) {
|
||||||
|
throw new Exception('Unable to connect to ftp-server "' . $hostname . ':' . $port . '"');
|
||||||
|
}
|
||||||
|
if (!ftp_login($this->ftp_conn, $username, $password)) {
|
||||||
|
throw new Exception('Unable to login to ftp-server "' . $hostname . ':' . $port . '"');
|
||||||
|
}
|
||||||
|
return $this->changeToCorrectDirectory();
|
||||||
|
}
|
||||||
|
throw new Exception('Empty hostname for FTP backup storage');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $filename
|
||||||
|
* @param string $tmp_source_directory
|
||||||
|
* @return bool
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
protected function putFile(string $filename, string $tmp_source_directory): bool
|
||||||
|
{
|
||||||
|
$source = FileDir::makeCorrectFile($tmp_source_directory . "/" . $filename);
|
||||||
|
$target = basename($filename);
|
||||||
|
if (file_exists($source) && !file_exists($target)) {
|
||||||
|
return ftp_put($this->ftp_conn, $target, $source, FTP_BINARY);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $filename
|
||||||
|
* @return bool
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
protected function rmFile(string $filename): bool
|
||||||
|
{
|
||||||
|
$target = basename($filename);
|
||||||
|
if (ftp_size($this->ftp_conn, $target) >= 0) {
|
||||||
|
return ftp_delete($this->ftp_conn, $target);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function shutdown(): bool
|
||||||
|
{
|
||||||
|
return ftp_close($this->ftp_conn);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return bool
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
private function changeToCorrectDirectory(): bool
|
||||||
|
{
|
||||||
|
$dirs = explode("/", $this->getDestinationDirectory());
|
||||||
|
array_shift($dirs);
|
||||||
|
if (count($dirs) > 0 && !empty($dirs[0])) {
|
||||||
|
foreach ($dirs as $dir) {
|
||||||
|
if (empty($dir)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (!@ftp_chdir($this->ftp_conn, $dir)) {
|
||||||
|
ftp_mkdir($this->ftp_conn, $dir);
|
||||||
|
ftp_chmod($this->ftp_conn, 0700, $dir);
|
||||||
|
ftp_chdir($this->ftp_conn, $dir);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return ftp_chdir($this->ftp_conn, "/");
|
||||||
|
}
|
||||||
|
}
|
||||||
60
lib/Froxlor/Backup/Storages/Local.php
Normal file
60
lib/Froxlor/Backup/Storages/Local.php
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Froxlor\Backup\Storages;
|
||||||
|
|
||||||
|
use Exception;
|
||||||
|
use Froxlor\FileDir;
|
||||||
|
|
||||||
|
class Local extends Storage
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
public function init(): bool
|
||||||
|
{
|
||||||
|
// create destination_path
|
||||||
|
if (!file_exists($this->getDestinationDirectory())) {
|
||||||
|
return mkdir($this->getDestinationDirectory(), 0700, true);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $filename
|
||||||
|
* @param string $tmp_source_directory
|
||||||
|
* @return bool
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
protected function putFile(string $filename, string $tmp_source_directory): bool
|
||||||
|
{
|
||||||
|
$source = FileDir::makeCorrectFile($tmp_source_directory . "/" . $filename);
|
||||||
|
$target = FileDir::makeCorrectFile($this->getDestinationDirectory() . "/" . $filename);
|
||||||
|
if (file_exists($source) && !file_exists($target)) {
|
||||||
|
return rename($source, $target);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $filename
|
||||||
|
* @return bool
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
protected function rmFile(string $filename): bool
|
||||||
|
{
|
||||||
|
$target = FileDir::makeCorrectFile($this->getDestinationDirectory() . "/" . $filename);
|
||||||
|
if (file_exists($target)) {
|
||||||
|
return @unlink($target);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function shutdown(): bool
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
42
lib/Froxlor/Backup/Storages/Rsync.php
Normal file
42
lib/Froxlor/Backup/Storages/Rsync.php
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Froxlor\Backup\Storages;
|
||||||
|
|
||||||
|
class Rsync extends Storage
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function init(): bool
|
||||||
|
{
|
||||||
|
// TODO: Implement init() method.
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $filename
|
||||||
|
* @param string $tmp_source_directory
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
protected function putFile(string $filename, string $tmp_source_directory): bool
|
||||||
|
{
|
||||||
|
// TODO: Implement putFiles() method.
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $filename
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
protected function rmFile(string $filename): bool
|
||||||
|
{
|
||||||
|
// TODO: Implement removeOld() method.
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function shutdown(): bool
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
42
lib/Froxlor/Backup/Storages/S3.php
Normal file
42
lib/Froxlor/Backup/Storages/S3.php
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Froxlor\Backup\Storages;
|
||||||
|
|
||||||
|
class S3 extends Storage
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function init(): bool
|
||||||
|
{
|
||||||
|
// TODO: Implement init() method.
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $filename
|
||||||
|
* @param string $tmp_source_directory
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
protected function putFile(string $filename, string $tmp_source_directory): bool
|
||||||
|
{
|
||||||
|
// TODO: Implement putFiles() method.
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $filename
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
protected function rmFile(string $filename): bool
|
||||||
|
{
|
||||||
|
// TODO: Implement removeOld() method.
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function shutdown(): bool
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
42
lib/Froxlor/Backup/Storages/Sftp.php
Normal file
42
lib/Froxlor/Backup/Storages/Sftp.php
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Froxlor\Backup\Storages;
|
||||||
|
|
||||||
|
class Sftp extends Storage
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function init(): bool
|
||||||
|
{
|
||||||
|
// TODO: Implement init() method.
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $filename
|
||||||
|
* @param string $tmp_source_directory
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
protected function putFile(string $filename, string $tmp_source_directory): bool
|
||||||
|
{
|
||||||
|
// TODO: Implement putFiles() method.
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $filename
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
protected function rmFile(string $filename): bool
|
||||||
|
{
|
||||||
|
// TODO: Implement removeOld() method.
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function shutdown(): bool
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
155
lib/Froxlor/Backup/Storages/Storage.php
Normal file
155
lib/Froxlor/Backup/Storages/Storage.php
Normal file
@@ -0,0 +1,155 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Froxlor\Backup\Storages;
|
||||||
|
|
||||||
|
use Exception;
|
||||||
|
use Froxlor\Database\Database;
|
||||||
|
use Froxlor\FileDir;
|
||||||
|
|
||||||
|
abstract class Storage
|
||||||
|
{
|
||||||
|
private string $tmpDirectory;
|
||||||
|
protected array $sData;
|
||||||
|
|
||||||
|
protected array $filesToStore;
|
||||||
|
|
||||||
|
public function __construct(array $storage_data)
|
||||||
|
{
|
||||||
|
$this->sData = $storage_data;
|
||||||
|
$this->tmpDirectory = sys_get_temp_dir();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validate sData, open connection to target storage, etc.
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
abstract public function init(): bool;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Disconnect / clean up connection if needed
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
abstract public function shutdown(): bool;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* prepare files to back up (e.g. create archive or similar) and fill $filesToStore
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function prepareFiles(): void
|
||||||
|
{
|
||||||
|
$this->filesToStore = [];
|
||||||
|
|
||||||
|
// create archive of web, mail and database data
|
||||||
|
|
||||||
|
// create json-info-file
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $filename
|
||||||
|
* @param string $tmp_source_directory
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
abstract protected function putFile(string $filename, string $tmp_source_directory): bool;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $filename
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
abstract protected function rmFile(string $filename): bool;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return bool
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
public function removeOld(): bool
|
||||||
|
{
|
||||||
|
// retention in days
|
||||||
|
$retention = $this->sData['storage']['retention'] ?? 3;
|
||||||
|
// keep date
|
||||||
|
$keepDate = new \DateTime();
|
||||||
|
$keepDate->setTime(0, 0, 0, 1);
|
||||||
|
// subtract retention days
|
||||||
|
$keepDate->sub(new \DateInterval('P' . $retention . 'D'));
|
||||||
|
// select target backups to remove for this storage-id and customer
|
||||||
|
$sel_stmt = Database::prepare("
|
||||||
|
SELECT * FROM `" . TABLE_PANEL_BACKUPS . "`
|
||||||
|
WHERE `created_at` < :keepdate
|
||||||
|
AND `storage_id` = :sid
|
||||||
|
AND `customerid` = :cid
|
||||||
|
");
|
||||||
|
Database::pexecute($sel_stmt, [
|
||||||
|
'keepdate' => $keepDate->format('U'),
|
||||||
|
'sid' => $this->sData['backup'],
|
||||||
|
'cid' => $this->sData['customerid']
|
||||||
|
]);
|
||||||
|
while ($oldBackup = $sel_stmt->fetch(\PDO::FETCH_ASSOC)) {
|
||||||
|
$this->rmFile($oldBackup['filename']);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return string
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
public function getDestinationDirectory(): string
|
||||||
|
{
|
||||||
|
return FileDir::makeCorrectDir($this->sData['storage']['destination_path'] ?? "/");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create backup-archive/file from $filesToStore and call putFile()
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
public function createFromFiles(): bool
|
||||||
|
{
|
||||||
|
if (empty($this->filesToStore)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$filename = FileDir::makeCorrectFile("/backup-" . $this->sData['loginname'] . "-" . date('c') . ".tar.gz");
|
||||||
|
|
||||||
|
// @todo create archive $filename from $filesToStore
|
||||||
|
|
||||||
|
// determine filesize (use stat locally here b/c files are possibly large and php's filesize() can't handle them)
|
||||||
|
$sizeCheckFile = FileDir::makeCorrectFile($this->tmpDirectory . "/" . $filename);
|
||||||
|
$fileSizeOutput = FileDir::safe_exec('/usr/bin/stat -c "%s" ' . escapeshellarg($sizeCheckFile));
|
||||||
|
$fileSize = (int)array_shift($fileSizeOutput);
|
||||||
|
|
||||||
|
// add entry to database and upload/store file
|
||||||
|
$this->addEntry($filename, $fileSize);
|
||||||
|
return $this->putFile($filename, $this->tmpDirectory);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $filename
|
||||||
|
* @param int $fileSize
|
||||||
|
* @return void
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
private function addEntry(string $filename, int $fileSize): void
|
||||||
|
{
|
||||||
|
$ins_stmt = Database::prepare("
|
||||||
|
INSERT INTO `" . TABLE_PANEL_BACKUPS . "` SET
|
||||||
|
`adminid` = :adminid,
|
||||||
|
`customerid` = :customerid,
|
||||||
|
`loginname` = :loginname,
|
||||||
|
`size` = :size,
|
||||||
|
`storage_id` = :sid,
|
||||||
|
`filename` = :filename,
|
||||||
|
`created_at` = UNIX_TIMESTAMP()
|
||||||
|
");
|
||||||
|
Database::pexecute($ins_stmt, [
|
||||||
|
'adminid' => $this->sData['adminid'],
|
||||||
|
'customerid' => $this->sData['customerid'],
|
||||||
|
'loginname' => $this->sData['loginname'],
|
||||||
|
'size' => $fileSize,
|
||||||
|
'sid' => $this->sData['backup'],
|
||||||
|
'filename' => $filename
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
12
lib/Froxlor/Backup/Storages/StorageFactory.php
Normal file
12
lib/Froxlor/Backup/Storages/StorageFactory.php
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Froxlor\Backup\Storages;
|
||||||
|
|
||||||
|
class StorageFactory
|
||||||
|
{
|
||||||
|
public static function fromType(string $type, array $storage_data): Storage
|
||||||
|
{
|
||||||
|
$type = "\\Froxlor\\Backup\\Storages\\" . ucfirst($type);
|
||||||
|
return new $type($storage_data);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -25,6 +25,8 @@
|
|||||||
|
|
||||||
namespace Froxlor\Cron\Backup;
|
namespace Froxlor\Cron\Backup;
|
||||||
|
|
||||||
|
use Exception;
|
||||||
|
use Froxlor\Backup\Storages\StorageFactory;
|
||||||
use Froxlor\Cron\Forkable;
|
use Froxlor\Cron\Forkable;
|
||||||
use Froxlor\Cron\FroxlorCron;
|
use Froxlor\Cron\FroxlorCron;
|
||||||
use Froxlor\Database\Database;
|
use Froxlor\Database\Database;
|
||||||
@@ -38,7 +40,7 @@ class BackupCron extends FroxlorCron
|
|||||||
|
|
||||||
public static function run()
|
public static function run()
|
||||||
{
|
{
|
||||||
if(!Settings::Get('backup.enabled')) {
|
if (!Settings::Get('backup.enabled')) {
|
||||||
FroxlorLogger::getInstanceOf()->logAction(FroxlorLogger::CRON_ACTION, LOG_DEBUG, 'BackupCron: disabled - exiting');
|
FroxlorLogger::getInstanceOf()->logAction(FroxlorLogger::CRON_ACTION, LOG_DEBUG, 'BackupCron: disabled - exiting');
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@@ -71,11 +73,22 @@ class BackupCron extends FroxlorCron
|
|||||||
self::runFork([self::class, 'handle'], $customers);
|
self::runFork([self::class, 'handle'], $customers);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
private static function handle(array $userdata)
|
private static function handle(array $userdata)
|
||||||
{
|
{
|
||||||
echo "BackupCron: started - creating customer backup for user " . $userdata['loginname'] . "\n";
|
echo "BackupCron: started - creating customer backup for user " . $userdata['loginname'] . "\n";
|
||||||
|
|
||||||
echo json_encode($userdata['storage']) . "\n";
|
$backupStorage = StorageFactory::fromType($userdata['storage']['type'], $userdata);
|
||||||
|
// initialize storage
|
||||||
|
$backupStorage->init();
|
||||||
|
// do what is required to obtain files/archives and move/upload
|
||||||
|
$backupStorage->prepareFiles();
|
||||||
|
// upload/move to target
|
||||||
|
$backupStorage->createFromFiles();
|
||||||
|
// remove by retention
|
||||||
|
$backupStorage->removeOld();
|
||||||
|
|
||||||
echo "BackupCron: finished - creating customer backup for user " . $userdata['loginname'] . "\n";
|
echo "BackupCron: finished - creating customer backup for user " . $userdata['loginname'] . "\n";
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user