mail-account-admin/src/Frontend/Accounts/AccountController.php

214 lines
8.3 KiB
PHP

<?php
declare(strict_types=1);
namespace MailAccountAdmin\Frontend\Accounts;
use MailAccountAdmin\Common\ActionResult;
use MailAccountAdmin\Common\SessionHelper;
use MailAccountAdmin\Common\UserHelper;
use MailAccountAdmin\Exceptions\AccountNotFoundException;
use MailAccountAdmin\Exceptions\AppException;
use MailAccountAdmin\Exceptions\InputValidationError;
use MailAccountAdmin\Frontend\BaseController;
use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request;
use Slim\Views\Twig;
class AccountController extends BaseController
{
private AccountHandler $accountHandler;
public function __construct(Twig $view, SessionHelper $sessionHelper, UserHelper $userHelper, AccountHandler $accountHandler)
{
parent::__construct($view, $sessionHelper, $userHelper);
$this->accountHandler = $accountHandler;
}
// -- Error pages
public function showAccount404(Response $response, int $accountId): Response
{
return $this->view->render($response, 'account_404.html.twig', ['id' => $accountId])->withStatus(404);
}
// -- /accounts - List all accounts
public function showAccounts(Request $request, Response $response): Response
{
// Parse query parameters for filters
$queryParams = $request->getQueryParams();
$filterByDomain = $queryParams['domain'] ?? '';
// Get list of all accounts
$renderData = $this->accountHandler->listAccounts($filterByDomain);
// If the form has been submitted, add the result message to the render data array
$renderData = $this->addLastActionResultToRenderData($renderData);
return $this->view->render($response, 'accounts.html.twig', $renderData);
}
// -- /accounts/{id} - Show account details
public function showAccountDetails(Request $request, Response $response, array $args): Response
{
// Parse URL arguments
$accountId = (int)$args['id'];
try {
$renderData = $this->accountHandler->getAccountDetails($accountId);
} catch (AccountNotFoundException $e) {
return $this->showAccount404($response, $accountId);
}
return $this->view->render($response, 'account_details.html.twig', $renderData);
}
// -- /accounts/new - Create new account
public function showAccountCreate(Request $request, Response $response): Response
{
$renderData = $this->accountHandler->getPageDataForCreate();
// If the form has been submitted, add the result message and form input data to the render data array
$renderData = $this->addLastActionResultToRenderData($renderData);
return $this->view->render($response, 'account_create.html.twig', $renderData);
}
public function createAccount(Request $request, Response $response): Response
{
// Parse form data
$createData = $request->getParsedBody();
try {
// Validate input
$validatedCreateData = AccountCreateData::createFromArray($createData);
$createResult = $this->accountHandler->createNewAccount($validatedCreateData);
// Save success result
$successMessage = "Account <a href=\"/accounts/{$createResult['id']}\">{$createResult['username']}</a> was created.";
if (!empty($createResult['generatedPassword'])) {
$successMessage .= "\nThe password generated for this account is: <i>{$createResult['generatedPassword']}</i>";
}
$this->sessionHelper->setLastActionResult(ActionResult::createSuccessResult($successMessage));
} catch (InputValidationError $e) {
// Save error result
$this->sessionHelper->setLastActionResult(ActionResult::createErrorResult($e->getMessage(), $createData));
}
// Redirect to edit form page via GET (PRG)
return $response->withHeader('Location', '/accounts/new')->withStatus(303);
}
// -- /accounts/{id}/edit - Edit account
public function showAccountEdit(Request $request, Response $response, array $args): Response
{
// Parse URL arguments
$accountId = (int)$args['id'];
try {
// Get account data from database
$renderData = $this->accountHandler->getAccountDataForEdit($accountId);
} catch (AccountNotFoundException $e) {
return $this->showAccount404($response, $accountId);
}
// If the form has been submitted, add the result message and form input data to the render data array
$renderData = $this->addLastActionResultToRenderData($renderData);
return $this->view->render($response, 'account_edit.html.twig', $renderData);
}
public function editAccount(Request $request, Response $response, array $args): Response
{
// Parse URL arguments and form data
$accountId = (int)$args['id'];
$editData = $request->getParsedBody();
try {
// Validate input
$validatedEditData = AccountEditData::createFromArray($editData);
$editResult = $this->accountHandler->editAccountData($accountId, $validatedEditData);
// Save success result
$successMessage = "Account data was saved.";
if (!empty($editResult['generatedPassword'])) {
$successMessage .= "\nThe new password generated for this account is: <i>{$editResult['generatedPassword']}</i>";
}
$this->sessionHelper->setLastActionResult(ActionResult::createSuccessResult($successMessage));
} catch (InputValidationError $e) {
// Save error result
$this->sessionHelper->setLastActionResult(ActionResult::createErrorResult($e->getMessage(), $editData));
}
// Redirect to edit form page via GET (PRG)
return $response->withHeader('Location', '/accounts/' . $accountId . '/edit')->withStatus(303);
}
// -- /accounts/{id}/delete - Delete account
public function showAccountDelete(Request $request, Response $response, array $args): Response
{
// Parse URL arguments
$accountId = (int)$args['id'];
try {
// Get account data and list of aliases from database
$renderData = $this->accountHandler->getAccountDataForDelete($accountId);
} catch (AccountNotFoundException $e) {
return $this->showAccount404($response, $accountId);
}
// If the form has been submitted, add the result message to the render data array
$renderData = $this->addLastActionResultToRenderData($renderData);
return $this->view->render($response, 'account_delete.html.twig', $renderData);
}
public function deleteAccount(Request $request, Response $response, array $args): Response
{
// Parse URL arguments and form data
$accountId = (int)$args['id'];
$formData = $request->getParsedBody();
try {
// Confirm action by entering the admin password
$this->userHelper->confirmActionByAdminPassword($formData['admin_password'] ?? '');
// Delete account
$deleteResult = $this->accountHandler->deleteAccount($accountId);
// Save success result
$successMessage = "Account <i>{$deleteResult['username']}</i> ";
$deletedAliasCount = $deleteResult['deleted_alias_count'];
if ($deletedAliasCount > 0) {
$aliasWordPlural = $deletedAliasCount > 1 ? 'aliases' : 'alias';
$successMessage .= "and {$deletedAliasCount} {$aliasWordPlural} were deleted.";
} else {
$successMessage .= "was deleted.";
}
$this->sessionHelper->setLastActionResult(ActionResult::createSuccessResult($successMessage));
// Redirect to account list (where the success message will be displayed)
$redirectTarget = '/accounts';
} catch (AppException $e) {
// Save error result
$this->sessionHelper->setLastActionResult(ActionResult::createErrorResult($e->getMessage()));
// Stay on delete page
$redirectTarget = '/accounts/' . $accountId . '/delete';
}
// Redirect to edit form page via GET (PRG)
return $response->withHeader('Location', $redirectTarget)->withStatus(303);
}
}