diff --git a/php/src/Controller/ConfigurationController.php b/php/src/Controller/ConfigurationController.php index 45586f9c..c56757bc 100644 --- a/php/src/Controller/ConfigurationController.php +++ b/php/src/Controller/ConfigurationController.php @@ -17,6 +17,8 @@ readonly class ConfigurationController { public function SetConfig(Request $request, Response $response, array $args): Response { try { + $this->configurationManager->startTransaction(); + if (isset($request->getParsedBody()['domain'])) { $domain = $request->getParsedBody()['domain'] ?? ''; $skipDomainValidation = isset($request->getParsedBody()['skip_domain_validation']); @@ -162,6 +164,8 @@ readonly class ConfigurationController { $this->configurationManager->DeleteBorgBackupLocationItems(); } + $this->configurationManager->commitTransaction(); + return $response->withStatus(201)->withHeader('Location', '.'); } catch (InvalidSettingConfigurationException $ex) { $response->getBody()->write($ex->getMessage()); diff --git a/php/src/Controller/DockerController.php b/php/src/Controller/DockerController.php index a924e61f..5f9c461c 100644 --- a/php/src/Controller/DockerController.php +++ b/php/src/Controller/DockerController.php @@ -123,15 +123,18 @@ readonly class DockerController { } public function StartBackupContainerRestore(Request $request, Response $response, array $args) : Response { - $this->configurationManager->SetBackupMode('restore'); - $config = $this->configurationManager->GetConfig(); - $config['selected-restore-time'] = $request->getParsedBody()['selected_restore_time'] ?? ''; + $restoreTime = $request->getParsedBody()['selected_restore_time'] ?? ''; if (isset($request->getParsedBody()['restore-exclude-previews'])) { - $config['restore-exclude-previews'] = 1; + $excludePreviews = '1'; } else { - $config['restore-exclude-previews'] = ''; + $excludePreviews = ''; } - $this->configurationManager->WriteConfig($config); + + $this->configurationManager->startTransaction(); + $this->configurationManager->SetBackupMode('restore'); + $this->configurationManager->SetRestoreTime($restoreTime); + $this->configurationManager->SetRestoreExcludePreviews($excludePreviews); + $this->configurationManager->commitTransaction(); $id = self::TOP_CONTAINER; $forceStopNextcloud = true; @@ -156,10 +159,10 @@ readonly class DockerController { } public function StartBackupContainerTest(Request $request, Response $response, array $args) : Response { + $this->configurationManager->startTransaction(); $this->configurationManager->SetBackupMode('test'); - $config = $this->configurationManager->GetConfig(); - $config['instance_restore_attempt'] = 0; - $this->configurationManager->WriteConfig($config); + $this->configurationManager->SetInstanceRestoreAttempt(0); + $this->configurationManager->commitTransaction(); $id = self::TOP_CONTAINER; $this->PerformRecursiveContainerStop($id); @@ -182,19 +185,16 @@ readonly class DockerController { } if (isset($request->getParsedBody()['install_latest_major'])) { - $installLatestMajor = 32; + $latestMajor = 32; } else { - $installLatestMajor = ""; + $latestMajor = 0; } - $config = $this->configurationManager->GetConfig(); - // set AIO_URL - $config['AIO_URL'] = $host . ':' . (string)$port . $path; - // set wasStartButtonClicked - $config['wasStartButtonClicked'] = 1; - // set install_latest_major - $config['install_latest_major'] = $installLatestMajor; - $this->configurationManager->WriteConfig($config); + $this->configurationManager->startTransaction(); + $this->configurationManager->SetAIOURL($host . ':' . (string)$port . $path); + $this->configurationManager->SetWasStartButtonClicked(1); + $this->configurationManager->SetInstallLatestMajor($latestMajor); + $this->configurationManager->commitTransaction(); // Do not pull container images in case 'bypass_container_update' is set via url params // Needed for local testing @@ -213,10 +213,8 @@ readonly class DockerController { } public function startTopContainer(bool $pullImage) : void { - $config = $this->configurationManager->GetConfig(); - // set AIO_TOKEN - $config['AIO_TOKEN'] = bin2hex(random_bytes(24)); - $this->configurationManager->WriteConfig($config); + $aioToken = bin2hex(random_bytes(24)); + $this->configurationManager->SetToken($aioToken); // Stop domaincheck since apache would not be able to start otherwise $this->StopDomaincheckContainer(); diff --git a/php/src/Data/ConfigurationManager.php b/php/src/Data/ConfigurationManager.php index 320bc477..b55d9940 100644 --- a/php/src/Data/ConfigurationManager.php +++ b/php/src/Data/ConfigurationManager.php @@ -9,8 +9,15 @@ class ConfigurationManager { private array $secrets = []; - public function GetConfig() : array + private array $config = []; + + private bool $noWrite = false; + + private function GetConfig() : array { + if (count($this->config) > 0) { + return $this->config; + } if(file_exists(DataConst::GetConfigFile())) { $configContent = (string)file_get_contents(DataConst::GetConfigFile()); @@ -20,10 +27,29 @@ class ConfigurationManager return []; } + public function startTransaction() : void { + $this->config = $this->GetConfig(); + $this->noWrite = true; + } + + public function commitTransaction() : void { + $this->noWrite = false; + if (count($this->config) > 0) { + $this->WriteConfig($this->config); + } + $this->config = []; + } + public function GetPassword() : string { return $this->GetConfig()['password']; } + public function SetToken(string $token) : void { + $config = $this->GetConfig(); + $config['AIO_TOKEN'] = $token; + $this->WriteConfig($config); + } + public function GetToken() : string { return $this->GetConfig()['AIO_TOKEN']; } @@ -122,6 +148,12 @@ class ConfigurationManager return $backupTimes; } + public function SetWasStartButtonClicked(int $value) : void { + $config = $this->GetConfig(); + $config['wasStartButtonClicked'] = $value; + $this->WriteConfig($config); + } + public function wasStartButtonClicked() : bool { if (isset($this->GetConfig()['wasStartButtonClicked'])) { return true; @@ -392,11 +424,16 @@ class ConfigurationManager } } - // Write domain + $this->startTransaction(); + $this->setValidDomain($domain); + // Reset the borg restore password when setting the domain + $this->SetBorgRestorePassword(''); + $this->commitTransaction(); + } + + private function setValidDomain(string $domain) : void { $config = $this->GetConfig(); $config['domain'] = $domain; - // Reset the borg restore password when setting the domain - $config['borg_restore_password'] = ''; $this->WriteConfig($config); } @@ -432,6 +469,12 @@ class ConfigurationManager $this->WriteConfig($config); } + public function SetRestoreTime(string $restoreTime) : void { + $config = $this->GetConfig(); + $config['selected-restore-time'] = $restoreTime; + $this->WriteConfig($config); + } + public function GetSelectedRestoreTime() : string { $config = $this->GetConfig(); if(!isset($config['selected-restore-time'])) { @@ -441,13 +484,19 @@ class ConfigurationManager return $config['selected-restore-time']; } + public function SetRestoreExcludePreviews(string $excludePreviews) : void { + $config = $this->GetConfig(); + $config['restore-exclude-previews'] = $excludePreviews; + $this->WriteConfig($config); + } + public function GetRestoreExcludePreviews() : string { $config = $this->GetConfig(); if(!isset($config['restore-exclude-previews'])) { $config['restore-exclude-previews'] = ''; } - return $config['restore-exclude-previews']; + return (string)$config['restore-exclude-previews']; } public function GetAIOURL() : string { @@ -459,16 +508,22 @@ class ConfigurationManager return $config['AIO_URL']; } + public function SetAIOURL(string $aioURL) : void { + $config = $this->GetConfig(); + $config['AIO_URL'] = $aioURL; + $this->WriteConfig($config); + } + /** * @throws InvalidSettingConfigurationException */ public function SetBorgLocationVars(string $location, string $repo) : void { $this->ValidateBorgLocationVars($location, $repo); - $config = $this->GetConfig(); - $config['borg_backup_host_location'] = $location; - $config['borg_remote_repo'] = $repo; - $this->WriteConfig($config); + $this->startTransaction(); + $this->SetBorgBackupHostLocation($location); + $this->SetBorgRemoteRepo($repo); + $this->commitTransaction(); } private function ValidateBorgLocationVars(string $location, string $repo) : void { @@ -514,10 +569,10 @@ class ConfigurationManager public function DeleteBorgBackupLocationItems() : void { // Delete the variables - $config = $this->GetConfig(); - $config['borg_backup_host_location'] = ''; - $config['borg_remote_repo'] = ''; - $this->WriteConfig($config); + $this->startTransaction(); + $this->SetBorgBackupHostLocation(''); + $this->SetBorgRemoteRepo(''); + $this->commitTransaction(); // Also delete the borg config file to be able to start over if (file_exists(DataConst::GetBackupKeyFile())) { @@ -537,12 +592,12 @@ class ConfigurationManager throw new InvalidSettingConfigurationException("Please enter the password!"); } - $config = $this->GetConfig(); - $config['borg_backup_host_location'] = $location; - $config['borg_remote_repo'] = $repo; - $config['borg_restore_password'] = $password; - $config['instance_restore_attempt'] = 1; - $this->WriteConfig($config); + $this->startTransaction(); + $this->SetBorgBackupHostLocation($location); + $this->SetBorgRemoteRepo($repo); + $this->SetBorgRestorePassword($password); + $this->SetInstanceRestoreAttempt(1); + $this->commitTransaction(); } /** @@ -599,7 +654,11 @@ class ConfigurationManager /** * @throws InvalidSettingConfigurationException */ - public function WriteConfig(array $config) : void { + private function WriteConfig(array $config) : void { + if ($this->noWrite) { + $this->config = $config; + return; + } if(!is_dir(DataConst::GetDataDirectory())) { throw new InvalidSettingConfigurationException(DataConst::GetDataDirectory() . " does not exist! Something was set up falsely!"); } @@ -634,6 +693,12 @@ class ConfigurationManager return $envVariableOutput; } + public function SetBorgBackupHostLocation(string $borgBackupHostLocation) : void { + $config = $this->GetConfig(); + $config['borg_backup_host_location'] = $borgBackupHostLocation; + $this->WriteConfig($config); + } + public function GetBorgBackupHostLocation() : string { $config = $this->GetConfig(); if(!isset($config['borg_backup_host_location'])) { @@ -643,6 +708,12 @@ class ConfigurationManager return $config['borg_backup_host_location']; } + public function SetBorgRemoteRepo(string $borgRemoteRepo) : void { + $config = $this->GetConfig(); + $config['borg_remote_repo'] = $borgRemoteRepo; + $this->WriteConfig($config); + } + public function GetBorgRemoteRepo() : string { $config = $this->GetConfig(); if(!isset($config['borg_remote_repo'])) { @@ -660,6 +731,12 @@ class ConfigurationManager return trim((string)file_get_contents(DataConst::GetBackupPublicKey())); } + public function SetBorgRestorePassword(string $restorePassword) : void { + $config = $this->GetConfig(); + $config['borg_restore_password'] = $restorePassword; + $this->WriteConfig($config); + } + public function GetBorgRestorePassword() : string { $config = $this->GetConfig(); if(!isset($config['borg_restore_password'])) { @@ -669,6 +746,12 @@ class ConfigurationManager return $config['borg_restore_password']; } + public function SetInstanceRestoreAttempt(int $instanceRestoreAttempt) : void { + $config = $this->GetConfig(); + $config['instance_restore_attempt'] = $instanceRestoreAttempt; + $this->WriteConfig($config); + } + public function isInstanceRestoreAttempt() : bool { $config = $this->GetConfig(); if(!isset($config['instance_restore_attempt'])) { @@ -862,12 +945,25 @@ class ConfigurationManager } } + public function setKeyAndValue(string $key, string $value) : void { + $config = $this->GetConfig(); + $config[$key] = $value; + $this->WriteConfig($config); + } + + + public function SetInstallLatestMajor(int $latestMajor) : void { + $config = $this->GetConfig(); + $config['install_latest_major'] = $latestMajor; + $this->WriteConfig($config); + } + public function shouldLatestMajorGetInstalled() : bool { $config = $this->GetConfig(); - if(!isset($config['install_latest_major'])) { - $config['install_latest_major'] = ''; + if(!isset($config['install_latest_major']) || $config['install_latest_major'] === '') { + $config['install_latest_major'] = 0; } - return $config['install_latest_major'] !== ''; + return $config['install_latest_major'] > 0; } public function GetAdditionalBackupDirectoriesString() : string { diff --git a/php/src/Docker/DockerActionManager.php b/php/src/Docker/DockerActionManager.php index fb3701a4..bd87f0aa 100644 --- a/php/src/Docker/DockerActionManager.php +++ b/php/src/Docker/DockerActionManager.php @@ -229,14 +229,15 @@ readonly class DockerActionManager { } $aioVariables = $container->aioVariables->GetVariables(); + $this->configurationManager->startTransaction(); foreach ($aioVariables as $variable) { - $config = $this->configurationManager->GetConfig(); $variable = $this->replaceEnvPlaceholders($variable); $variableArray = explode('=', $variable); - $config[$variableArray[0]] = $variableArray[1]; - $this->configurationManager->WriteConfig($config); - sleep(1); + $key = $variableArray[0]; + $value = $variableArray[1]; + $this->configurationManager->setKeyAndValue($key, $value); } + $this->configurationManager->commitTransaction(); $envs = $container->containerEnvironmentVariables->GetVariables(); // Special thing for the nextcloud container