diff --git a/php/public/base_path.js b/php/public/base_path.js new file mode 100644 index 00000000..a55ed943 --- /dev/null +++ b/php/public/base_path.js @@ -0,0 +1,7 @@ +document.addEventListener("DOMContentLoaded", function() { + basePath = document.getElementById("base_path") + if (basePath) { + // Remove '/containers' from the end of the path, to get the base path only + basePath.value = window.location.pathname.slice(0, -11); + } +}); \ No newline at end of file diff --git a/php/public/index.php b/php/public/index.php index aac83826..d3fbbeb9 100644 --- a/php/public/index.php +++ b/php/public/index.php @@ -178,17 +178,17 @@ $app->get('/', function (\Psr\Http\Message\RequestInterface $request, Response $ $setup = $container->get(\AIO\Data\Setup::class); if($setup->CanBeInstalled()) { return $response - ->withHeader('Location', '/setup') + ->withHeader('Location', 'setup') ->withStatus(302); } if($authManager->IsAuthenticated()) { return $response - ->withHeader('Location', '/containers') + ->withHeader('Location', 'containers') ->withStatus(302); } else { return $response - ->withHeader('Location', '/login') + ->withHeader('Location', 'login') ->withStatus(302); } }); diff --git a/php/src/Controller/ConfigurationController.php b/php/src/Controller/ConfigurationController.php index ed3be505..5727c364 100644 --- a/php/src/Controller/ConfigurationController.php +++ b/php/src/Controller/ConfigurationController.php @@ -161,7 +161,7 @@ readonly class ConfigurationController { $this->configurationManager->DeleteBorgBackupLocationVars(); } - return $response->withStatus(201)->withHeader('Location', '/'); + return $response->withStatus(201)->withHeader('Location', '.'); } catch (InvalidSettingConfigurationException $ex) { $response->getBody()->write($ex->getMessage()); return $response->withStatus(422); diff --git a/php/src/Controller/DockerController.php b/php/src/Controller/DockerController.php index 678bbdc9..8473ed57 100644 --- a/php/src/Controller/DockerController.php +++ b/php/src/Controller/DockerController.php @@ -85,7 +85,7 @@ readonly class DockerController { public function StartBackupContainerBackup(Request $request, Response $response, array $args) : Response { $forceStopNextcloud = true; $this->startBackup($forceStopNextcloud); - return $response->withStatus(201)->withHeader('Location', '/'); + return $response->withStatus(201)->withHeader('Location', '.'); } public function startBackup(bool $forceStopNextcloud = false) : void { @@ -102,7 +102,7 @@ readonly class DockerController { public function StartBackupContainerCheck(Request $request, Response $response, array $args) : Response { $this->checkBackup(); - return $response->withStatus(201)->withHeader('Location', '/'); + return $response->withStatus(201)->withHeader('Location', '.'); } public function checkBackup() : void { @@ -132,7 +132,7 @@ readonly class DockerController { $id = 'nextcloud-aio-borgbackup'; $this->PerformRecursiveContainerStart($id); - return $response->withStatus(201)->withHeader('Location', '/'); + return $response->withStatus(201)->withHeader('Location', '.'); } public function StartBackupContainerCheckRepair(Request $request, Response $response, array $args) : Response { @@ -148,7 +148,7 @@ readonly class DockerController { $config['backup-mode'] = 'check'; $this->configurationManager->WriteConfig($config); - return $response->withStatus(201)->withHeader('Location', '/'); + return $response->withStatus(201)->withHeader('Location', '.'); } public function StartBackupContainerTest(Request $request, Response $response, array $args) : Response { @@ -163,7 +163,7 @@ readonly class DockerController { $id = 'nextcloud-aio-borgbackup'; $this->PerformRecursiveContainerStart($id); - return $response->withStatus(201)->withHeader('Location', '/'); + return $response->withStatus(201)->withHeader('Location', '.'); } public function StartContainer(Request $request, Response $response, array $args) : Response @@ -171,6 +171,7 @@ readonly class DockerController { $uri = $request->getUri(); $host = $uri->getHost(); $port = $uri->getPort(); + $path = $request->getParsedBody()['base_path'] ?? ''; if ($port === 8000) { error_log('The AIO_URL-port was discovered to be 8000 which is not expected. It is now set to 443.'); $port = 443; @@ -184,7 +185,7 @@ readonly class DockerController { $config = $this->configurationManager->GetConfig(); // set AIO_URL - $config['AIO_URL'] = $host . ':' . $port; + $config['AIO_URL'] = $host . ':' . $port . $path; // set wasStartButtonClicked $config['wasStartButtonClicked'] = 1; // set install_latest_major @@ -204,7 +205,7 @@ readonly class DockerController { // Temporarily disabled as it leads much faster to docker rate limits // apcu_clear_cache(); - return $response->withStatus(201)->withHeader('Location', '/'); + return $response->withStatus(201)->withHeader('Location', '.'); } public function startTopContainer(bool $pullImage) : void { @@ -223,7 +224,7 @@ readonly class DockerController { public function StartWatchtowerContainer(Request $request, Response $response, array $args) : Response { $this->startWatchtower(); - return $response->withStatus(201)->withHeader('Location', '/'); + return $response->withStatus(201)->withHeader('Location', '.'); } public function startWatchtower() : void { @@ -261,7 +262,7 @@ readonly class DockerController { $forceStopNextcloud = true; $this->PerformRecursiveContainerStop($id, $forceStopNextcloud); - return $response->withStatus(201)->withHeader('Location', '/'); + return $response->withStatus(201)->withHeader('Location', '.'); } public function stopTopContainer() : void { diff --git a/php/src/Controller/LoginController.php b/php/src/Controller/LoginController.php index 196e7138..412ff9df 100644 --- a/php/src/Controller/LoginController.php +++ b/php/src/Controller/LoginController.php @@ -19,33 +19,33 @@ readonly class LoginController { public function TryLogin(Request $request, Response $response, array $args) : Response { if (!$this->dockerActionManager->isLoginAllowed()) { $response->getBody()->write("The login is blocked since Nextcloud is running."); - return $response->withHeader('Location', '/')->withStatus(422); + return $response->withHeader('Location', '.')->withStatus(422); } $password = $request->getParsedBody()['password'] ?? ''; if($this->authManager->CheckCredentials($password)) { $this->authManager->SetAuthState(true); - return $response->withHeader('Location', '/')->withStatus(201); + return $response->withHeader('Location', '.')->withStatus(201); } $response->getBody()->write("The password is incorrect."); - return $response->withHeader('Location', '/')->withStatus(422); + return $response->withHeader('Location', '.')->withStatus(422); } public function GetTryLogin(Request $request, Response $response, array $args) : Response { $token = $request->getQueryParams()['token'] ?? ''; if($this->authManager->CheckToken($token)) { $this->authManager->SetAuthState(true); - return $response->withHeader('Location', '/')->withStatus(302); + return $response->withHeader('Location', '../..')->withStatus(302); } - return $response->withHeader('Location', '/')->withStatus(302); + return $response->withHeader('Location', '../..')->withStatus(302); } public function Logout(Request $request, Response $response, array $args) : Response { $this->authManager->SetAuthState(false); return $response - ->withHeader('Location', '/') + ->withHeader('Location', '../..') ->withStatus(302); } } diff --git a/php/src/Middleware/AuthMiddleware.php b/php/src/Middleware/AuthMiddleware.php index f8d44857..724f1776 100644 --- a/php/src/Middleware/AuthMiddleware.php +++ b/php/src/Middleware/AuthMiddleware.php @@ -27,7 +27,24 @@ readonly class AuthMiddleware { if(!in_array($request->getUri()->getPath(), $publicRoutes)) { if(!$this->authManager->IsAuthenticated()) { $status = 302; - $headers = ['Location' => '/']; + + // Check the url of the request: split the string by '/' and count the number of elements + // Note that the path that gets to this middleware is not aware of any base path managed by a reverse proxy, so if the url is 'https://example.com/AIO/somepage', the path will be 'https://mastercontainer/somepage' + if (count(explode('/', $request->getUri()->getPath())) < 2) { + // If there are less than 2 elements it means we are somewhere in the root folder (no '/', so no subfolder), so we redirect to the same folder level to offload the redirection to the appropriate page to 'index.php' (specifically, once in the root level the login page will be loaded since we are not authenticated) + $location = '.'; + } else { + // If there are 2 or more elements it means we are in a subfolder, so we need to go back to the root folder + // In the best case we need to go back by 1 level only + $location = '..'; + // In the worst case we need to go back by n levels, where n is the number of elements - 2 (the first element is not a folder, the second element is already accounted for by the initial '..') + for ($i = 1; $i < count(explode('/', $request->getUri()->getPath())) - 2; $i++) { + // For each extra level we need to go back by another level + $location = $location . '/..'; + } + } + + $headers = ['Location' => $location]; $response = new Response($status, $headers); return $response; } diff --git a/php/templates/already-installed.twig b/php/templates/already-installed.twig index fa18f988..e16e6792 100644 --- a/php/templates/already-installed.twig +++ b/php/templates/already-installed.twig @@ -3,11 +3,11 @@ {% block body %}
{% endblock %} diff --git a/php/templates/components/container-state.twig b/php/templates/components/container-state.twig index 4cf5dd4e..8375d033 100644 --- a/php/templates/components/container-state.twig +++ b/php/templates/components/container-state.twig @@ -4,15 +4,15 @@ {% if c.GetStartingState().value == 'starting' %} {{ c.GetDisplayName() }} - (Starting) + (Starting) {% elseif c.GetRunningState().value == 'running' %} {{ c.GetDisplayName() }} - (Running) + (Running) {% else %} {{ c.GetDisplayName() }} - (Stopped) + (Stopped) {% endif %} {% if c.GetDocumentation() != '' %} (docs) diff --git a/php/templates/containers.twig b/php/templates/containers.twig index 12b4d81b..1e795149 100644 --- a/php/templates/containers.twig +++ b/php/templates/containers.twig @@ -6,9 +6,9 @@Choose the backup that you want to restore and click on the button below to restore the selected backup. This will restore the whole AIO instance. Please note that the current AIO passphrase will be kept and the previous AIO passphrase will not be restored from backup!
Important: If the backup that you want to restore contained any community container, you need to restore the same backup a second time after this attempt so that the community container data is also correctly restored.
-