From 1c6ca098d529c3bd800342f5f07264f13f747797 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 25 Apr 2026 16:43:49 +0000 Subject: [PATCH] refactor: move deSEC password-reveal logic from JS to Twig (PRG pattern) Agent-Logs-Url: https://github.com/nextcloud/all-in-one/sessions/159fc9de-4eb7-4131-8dee-9166045156e6 Co-authored-by: szaimen <42591237+szaimen@users.noreply.github.com> --- php/public/forms.js | 12 ++--------- php/public/index.php | 4 ++++ php/src/Controller/DesecController.php | 21 ++++++++++++++------ php/src/Desec/AlreadyRegisteredException.php | 20 +++++++++++++++++++ php/src/Desec/DesecManager.php | 5 +---- php/templates/includes/desec-register.twig | 13 +++++++----- 6 files changed, 50 insertions(+), 25 deletions(-) create mode 100644 php/src/Desec/AlreadyRegisteredException.php diff --git a/php/public/forms.js b/php/public/forms.js index ec326b8c..b37fdcdb 100644 --- a/php/public/forms.js +++ b/php/public/forms.js @@ -16,21 +16,13 @@ setTimeout(toast.remove.bind(toast), 10000) } - function handleEvent(e, form) { + function handleEvent(e) { const xhr = e.target; if (xhr.status === 201) { window.location.replace(xhr.getResponseHeader('Location')); } else if (xhr.status === 422) { disableSpinner() showError(xhr.response); - if (form) { - const revealSelector = form.dataset.revealOnError; - const revealWhen = form.dataset.revealWhen; - if (revealSelector && (!revealWhen || xhr.response.includes(revealWhen))) { - const target = document.querySelector(revealSelector); - if (target) target.style.display = ''; - } - } } else if (xhr.status === 500) { showError("Server error. Please check the mastercontainer logs for details. This page will reload after 10s automatically. Then you can check the mastercontainer logs."); // Reload after 10s since it is expected that the updated view is shown (e.g. after starting containers) @@ -58,7 +50,7 @@ lastError.remove() } let xhr = new XMLHttpRequest(); - xhr.addEventListener('load', function(e) { handleEvent(e, form); }); + xhr.addEventListener('load', handleEvent); xhr.addEventListener('error', () => showError("Failed to talk to server.")); xhr.addEventListener('error', () => disableSpinner()); xhr.open(form.method, form.getAttribute("action")); diff --git a/php/public/index.php b/php/public/index.php index 9d34eabd..00e4c2a3 100644 --- a/php/public/index.php +++ b/php/public/index.php @@ -185,7 +185,11 @@ $app->get('/containers', function (Request $request, Response $response, array $ 'desec_password' => $configurationManager->desecPassword, 'is_desec_domain' => $configurationManager->isDesecDomain(), 'desec_account_registered' => $configurationManager->isDesecAccountRegistered(), + 'desec_show_password' => (bool)($_SESSION['desec_show_password'] ?? false), + 'desec_prefill_email' => (string)($_SESSION['desec_prefill_email'] ?? ''), + 'desec_error' => (string)($_SESSION['desec_error'] ?? ''), ]); + unset($_SESSION['desec_show_password'], $_SESSION['desec_prefill_email'], $_SESSION['desec_error']); })->setName('profile'); $app->get('/login', function (Request $request, Response $response, array $args) use ($container) { $view = Twig::fromRequest($request); diff --git a/php/src/Controller/DesecController.php b/php/src/Controller/DesecController.php index 42f5c96d..82eb90b5 100644 --- a/php/src/Controller/DesecController.php +++ b/php/src/Controller/DesecController.php @@ -3,6 +3,7 @@ declare(strict_types=1); namespace AIO\Controller; +use AIO\Desec\AlreadyRegisteredException; use AIO\Desec\DesecManager; use Psr\Http\Message\ResponseInterface as Response; use Psr\Http\Message\ServerRequestInterface as Request; @@ -14,15 +15,23 @@ readonly class DesecController { } public function Register(Request $request, Response $response, array $args): Response { + $email = (string)($request->getParsedBody()['desec_email'] ?? ''); + $slug = (string)($request->getParsedBody()['desec_slug'] ?? ''); + $password = (string)($request->getParsedBody()['desec_password'] ?? ''); + try { - $email = (string)($request->getParsedBody()['desec_email'] ?? ''); - $slug = (string)($request->getParsedBody()['desec_slug'] ?? ''); - $password = (string)($request->getParsedBody()['desec_password'] ?? ''); $this->desecManager->register($email, $slug, $password); - return $response->withStatus(201)->withHeader('Location', '.'); + } catch (AlreadyRegisteredException $ex) { + $_SESSION['desec_show_password'] = true; + $_SESSION['desec_prefill_email'] = $ex->email; + $_SESSION['desec_error'] = $ex->getMessage(); } catch (\Exception $ex) { - $response->getBody()->write($ex->getMessage()); - return $response->withStatus(422); + $_SESSION['desec_error'] = $ex->getMessage(); } + + // Post/Redirect/Get: always redirect back to the containers page. + // The browser follows the Location header and issues a fresh GET, + // which prevents form-resubmission on reload. + return $response->withStatus(303)->withHeader('Location', '../../containers'); } } diff --git a/php/src/Desec/AlreadyRegisteredException.php b/php/src/Desec/AlreadyRegisteredException.php new file mode 100644 index 00000000..aaa9a8b4 --- /dev/null +++ b/php/src/Desec/AlreadyRegisteredException.php @@ -0,0 +1,20 @@ +Your deSEC account ({{ desec_email }}) was registered successfully but the domain could not be registered. Please enter a desired subdomain slug (the part before .dedyn.io) and try again, or leave it blank for a random one.

Your deSEC login credentials (for desec.io): Email: {{ desec_email }}.

Reveal deSEC password{{ desec_password }}
. Please save these in a safe place.

-
+ @@ -12,14 +12,17 @@
{% else %}

Please enter your email address. You can also enter a desired subdomain slug (the part before .dedyn.io); leave it blank for a random one.

-
+ {% if desec_error %} +

{{ desec_error }}

+ {% endif %} + - - + {% endif %}