diff --git a/src/Common/FormData.php b/src/Common/FormData.php index fde1281..2756aba 100644 --- a/src/Common/FormData.php +++ b/src/Common/FormData.php @@ -9,7 +9,7 @@ abstract class FormData { // Abstract methods - abstract public static function createFromArray(array $raw): self; + abstract public static function createFromArray($raw): self; // Input validation - Base types @@ -26,16 +26,6 @@ abstract class FormData return $raw; } - protected static function validateInteger(string $raw, bool $required = true, string $fieldName = 'Field'): int - { - if ($raw === '' && $required) { - throw new InputValidationError("$fieldName is required."); - } elseif (!is_numeric($raw)) { - throw new InputValidationError("$fieldName is not a number."); - } - return (int)$raw; - } - protected static function validateBoolOption(string $raw): bool { return $raw !== ''; diff --git a/src/Frontend/Accounts/AccountAddAliasData.php b/src/Frontend/Accounts/AccountAddAliasData.php index 6e5a3c6..306ca90 100644 --- a/src/Frontend/Accounts/AccountAddAliasData.php +++ b/src/Frontend/Accounts/AccountAddAliasData.php @@ -14,7 +14,7 @@ class AccountAddAliasData extends FormData $this->aliasAddress = $aliasAddress; } - public static function createFromArray(array $raw): self + public static function createFromArray($raw): self { return new self( self::validateAliasAddress(trim($raw['alias_address'] ?? '')), diff --git a/src/Frontend/Accounts/AccountController.php b/src/Frontend/Accounts/AccountController.php index 42ee4bb..1f9d6ac 100644 --- a/src/Frontend/Accounts/AccountController.php +++ b/src/Frontend/Accounts/AccountController.php @@ -236,33 +236,7 @@ class AccountController extends BaseController $this->sessionHelper->setLastActionResult(ActionResult::createErrorResult($e->getMessage(), $addAliasData)); } - // Redirect to account details page via GET (PRG) - return $response->withHeader('Location', '/accounts/' . $accountId . '#aliases')->withStatus(303); - } - - - // -- /accounts/{id}/deletealiases - Deletes a list of aliases - - public function deleteAliasesFromAccount(Request $request, Response $response, array $args): Response - { - // Parse URL arguments and form data - $accountId = (int)$args['id']; - $deleteAliasesData = $request->getParsedBody(); - - try { - // Validate input - $validatedDeleteAliasesData = AccountDeleteAliasesData::createFromArray($deleteAliasesData); - $deletedCount = $this->accountHandler->deleteAliasesFromAccount($accountId, $validatedDeleteAliasesData); - - // Save success result - $successMessage = $deletedCount === 1 ? "1 alias was deleted." : "{$deletedCount} aliases were deleted."; - $this->sessionHelper->setLastActionResult(ActionResult::createSuccessResult($successMessage)); - } catch (AppException $e) { - // Save error result - $this->sessionHelper->setLastActionResult(ActionResult::createErrorResult($e->getMessage())); - } - - // Redirect to account details page via GET (PRG) - return $response->withHeader('Location', '/accounts/' . $accountId . '#aliases')->withStatus(303); + // Redirect to edit form page via GET (PRG) + return $response->withHeader('Location', '/accounts/' . $accountId)->withStatus(303); } } diff --git a/src/Frontend/Accounts/AccountCreateData.php b/src/Frontend/Accounts/AccountCreateData.php index 166fa6e..265e5ed 100644 --- a/src/Frontend/Accounts/AccountCreateData.php +++ b/src/Frontend/Accounts/AccountCreateData.php @@ -22,7 +22,7 @@ class AccountCreateData extends FormData $this->memo = $memo; } - public static function createFromArray(array $raw): self + public static function createFromArray($raw): self { return new self( self::validateUsername(trim($raw['username'] ?? '')), diff --git a/src/Frontend/Accounts/AccountDeleteAliasesData.php b/src/Frontend/Accounts/AccountDeleteAliasesData.php deleted file mode 100644 index 2f828f3..0000000 --- a/src/Frontend/Accounts/AccountDeleteAliasesData.php +++ /dev/null @@ -1,42 +0,0 @@ -selectedAliasIds = $selectedAliasIds; - } - - public static function createFromArray(array $raw): self - { - $rawAliasIds = $raw['selected_aliases'] ?? []; - - if (!is_array($rawAliasIds)) { - throw new InputValidationError('selected_aliases is not an array.'); - } - if (empty($rawAliasIds)) { - throw new InputValidationError('No aliases were selected.'); - } - - $selectedAliasIds = []; - foreach ($rawAliasIds as $i => $id) { - $selectedAliasIds[] = self::validateInteger($id, true, "selected_aliases[$i]"); - } - - return new self($selectedAliasIds); - } - - public function getSelectedAliasIds(): array - { - return $this->selectedAliasIds; - } -} diff --git a/src/Frontend/Accounts/AccountEditData.php b/src/Frontend/Accounts/AccountEditData.php index 499b6f8..a48a88e 100644 --- a/src/Frontend/Accounts/AccountEditData.php +++ b/src/Frontend/Accounts/AccountEditData.php @@ -29,7 +29,7 @@ class AccountEditData extends FormData $this->memo = $memo; } - public static function createFromArray(array $raw): self + public static function createFromArray($raw): self { return new self( self::validateUsername(trim($raw['username'] ?? ''), false), diff --git a/src/Frontend/Accounts/AccountHandler.php b/src/Frontend/Accounts/AccountHandler.php index 4a71fc0..32dce32 100644 --- a/src/Frontend/Accounts/AccountHandler.php +++ b/src/Frontend/Accounts/AccountHandler.php @@ -6,7 +6,6 @@ namespace MailAccountAdmin\Frontend\Accounts; use MailAccountAdmin\Common\PasswordHelper; use MailAccountAdmin\Exceptions\AccountNotFoundException; use MailAccountAdmin\Exceptions\InputValidationError; -use MailAccountAdmin\Models\Account; use MailAccountAdmin\Repositories\AccountRepository; use MailAccountAdmin\Repositories\AliasRepository; use MailAccountAdmin\Repositories\DomainRepository; @@ -28,17 +27,6 @@ class AccountHandler } - // -- Helper methods - - private function ensureAccountExists(int $accountId): Account - { - try { - return $this->accountRepository->fetchAccountById($accountId); - } catch (AccountNotFoundException $e) { - throw new InputValidationError('Account with ID ' . $accountId . ' does not exist!'); - } - } - // -- /accounts - List all accounts public function listAccounts(string $filterByDomain): array @@ -146,7 +134,11 @@ class AccountHandler $returnData = []; // Check if account exists - $account = $this->ensureAccountExists($accountId); + try { + $account = $this->accountRepository->fetchAccountById($accountId); + } catch (AccountNotFoundException $e) { + throw new InputValidationError('Account with ID ' . $accountId . ' does not exist!'); + } $newUsername = $editData->getUsername(); if ($newUsername === $account->getUsername()) { @@ -154,9 +146,9 @@ class AccountHandler $newUsername = null; } - // If the user wants to change their username, has an existing alias with this username and checked the "replace existing alias" - // option, this variable will be set to the ID of the alias that needs to be deleted. - $aliasNeedsToBeReplaced = null; + // This variable will be set to true if the user wants to change their username, has an existing alias with this username, + // and checked the "replace existing alias" option. + $aliasNeedsToBeReplaced = false; // Check if new username is still available if ($newUsername !== null) { @@ -175,7 +167,7 @@ class AccountHandler if ($editData->getUsernameReplaceAlias()) { $existingAlias = $this->aliasRepository->fetchAliasByAddress($newUsername); if ($existingAlias->getUserId() === $accountId) { - $aliasNeedsToBeReplaced = $existingAlias->getId(); + $aliasNeedsToBeReplaced = true; $newUsernameAvailable = true; } } @@ -219,8 +211,8 @@ class AccountHandler ); // Remove existing alias for new username (if wanted) - if ($editData->getUsernameReplaceAlias() && $aliasNeedsToBeReplaced !== null) { - $this->aliasRepository->deleteAliasById($accountId, $aliasNeedsToBeReplaced); + if ($editData->getUsernameReplaceAlias() && $aliasNeedsToBeReplaced) { + $this->aliasRepository->deleteAlias($accountId, $newUsername); } // Commit database transaction @@ -250,7 +242,11 @@ class AccountHandler public function deleteAccount(int $accountId): array { // Check if account exists - $account = $this->ensureAccountExists($accountId); + try { + $account = $this->accountRepository->fetchAccountById($accountId); + } catch (AccountNotFoundException $e) { + throw new InputValidationError('Account with ID ' . $accountId . ' does not exist!'); + } // Start database transaction $this->accountRepository->beginTransaction(); @@ -276,7 +272,11 @@ class AccountHandler public function addAliasToAccount(int $accountId, AccountAddAliasData $aliasAddData): void { // Check if account exists - $this->ensureAccountExists($accountId); + try { + $this->accountRepository->fetchAccountById($accountId); + } catch (AccountNotFoundException $e) { + throw new InputValidationError('Account with ID ' . $accountId . ' does not exist!'); + } // Check if alias address is still available $address = $aliasAddData->getAliasAddress(); @@ -287,29 +287,4 @@ class AccountHandler // Create alias in database $this->aliasRepository->createNewAlias($accountId, $address); } - - - // -- /accounts/{id}/deletealiases - Deletes a list of aliases from the account - - public function deleteAliasesFromAccount(int $accountId, AccountDeleteAliasesData $aliasesDeleteData): int - { - // Check if account exists - $this->ensureAccountExists($accountId); - - // Start database transaction - $this->aliasRepository->beginTransaction(); - - // Delete aliases - $deletedCount = 0; - foreach ($aliasesDeleteData->getSelectedAliasIds() as $aliasId) { - if ($this->aliasRepository->deleteAliasById($accountId, $aliasId)) { - $deletedCount++; - } - } - - // Commit database transaction - $this->aliasRepository->commitTransaction(); - - return $deletedCount; - } } diff --git a/src/Repositories/AliasRepository.php b/src/Repositories/AliasRepository.php index 45ed640..86b9caf 100644 --- a/src/Repositories/AliasRepository.php +++ b/src/Repositories/AliasRepository.php @@ -52,15 +52,14 @@ class AliasRepository extends BaseRepository ]); } - public function deleteAliasById(int $userId, int $aliasId): bool + public function deleteAlias(int $userId, string $mailAddress): void { // Check user ID in WHERE clause to make sure we don't accidentally delete someone else's alias - $statement = $this->pdo->prepare('DELETE FROM mail_aliases WHERE user_id = :user_id AND alias_id = :alias_id LIMIT 1'); + $statement = $this->pdo->prepare('DELETE FROM mail_aliases WHERE user_id = :user_id AND mail_address = :mail_address LIMIT 1'); $statement->execute([ 'user_id' => $userId, - 'alias_id' => $aliasId, + 'mail_address' => $mailAddress, ]); - return $statement->rowCount() > 0; } public function deleteAllAliasesForUserId(int $userId): int diff --git a/src/Routes.php b/src/Routes.php index 159a6ad..00611ab 100644 --- a/src/Routes.php +++ b/src/Routes.php @@ -34,12 +34,5 @@ class Routes $app->get('/accounts/{id:[1-9][0-9]*}/delete', AccountController::class . ':showAccountDelete'); $app->post('/accounts/{id:[1-9][0-9]*}/delete', AccountController::class . ':deleteAccount'); $app->post('/accounts/{id:[1-9][0-9]*}/addalias', AccountController::class . ':addAliasToAccount'); - $app->post('/accounts/{id:[1-9][0-9]*}/deletealiases', AccountController::class . ':deleteAliasesFromAccount'); - - // Redirect URLs with trailing slashes to correct URLs - $app->redirect('/login/', '/login'); - $app->redirect('/logout/', '/logout'); - $app->redirect('/domains/', '/domains'); - $app->redirect('/accounts/', '/accounts'); } } diff --git a/templates/account_details.html.twig b/templates/account_details.html.twig index 0c092cc..4e00c14 100644 --- a/templates/account_details.html.twig +++ b/templates/account_details.html.twig @@ -62,41 +62,34 @@ -