diff --git a/public/static/style.css b/public/static/style.css index 4fd2214..ab04854 100644 --- a/public/static/style.css +++ b/public/static/style.css @@ -54,12 +54,13 @@ nav a { nav a:link, nav a:visited { background-color: #eeeeee; - color: blue; + color: #ff00e6; text-decoration: none; } nav a:hover, nav a:focus { background-color: #ffffff; + color: #0066ff; text-decoration: underline; } @@ -94,6 +95,16 @@ h2 { margin: 0 0 0.5em 0; } +a:link, a:visited { + color: #ff00e6; + text-decoration: none; +} + +a:hover, a:focus { + color: #0066ff; + text-decoration: underline; +} + .error { background: #ff4444; width: 30em; @@ -101,6 +112,40 @@ h2 { padding: 1em; } +.gray { + color: gray; +} + button { padding: 0.2em 1em; } + +table, tr, td, th { + border: 1px solid #999999; + border-collapse: collapse; + padding: 0.25em 0.5em; +} + +.inactive { + color: gray; +} + +/* --- Filter options --- */ +.filter_options { + border: 1px solid #999999; + padding: 1em; + margin: 1em 0; +} + +.filter_options h4 { + margin: 0 0 0.5em 0; +} + +/* --- Detail columns --- */ +input#show_details_checkbox { + margin-bottom: 1em; +} + +input#show_details_checkbox:not(:checked) ~ table .detail_column { + display: none; +} diff --git a/src/Dependencies.php b/src/Dependencies.php index ac6fbb4..f7f9742 100644 --- a/src/Dependencies.php +++ b/src/Dependencies.php @@ -9,7 +9,9 @@ use MailAccountAdmin\Frontend\Accounts\AccountController; use MailAccountAdmin\Frontend\Domains\DomainController; use MailAccountAdmin\Frontend\Login\LoginController; use MailAccountAdmin\Frontend\Dashboard\DashboardController; +use MailAccountAdmin\Repositories\AccountRepository; use MailAccountAdmin\Repositories\AdminUserRepository; +use MailAccountAdmin\Repositories\DomainRepository; use PDO; use Psr\Container\ContainerInterface; use Slim\Views\Twig; @@ -58,6 +60,16 @@ class Dependencies $c->get(self::DATABASE), ); }); + $container->set(DomainRepository::class, function (ContainerInterface $c) { + return new DomainRepository( + $c->get(self::DATABASE), + ); + }); + $container->set(AccountRepository::class, function (ContainerInterface $c) { + return new AccountRepository( + $c->get(self::DATABASE), + ); + }); // Helper classes $container->set(UserHelper::class, function (ContainerInterface $c) { @@ -84,12 +96,14 @@ class Dependencies return new DomainController( $c->get(self::TWIG), $c->get(UserHelper::class), + $c->get(DomainRepository::class), ); }); $container->set(AccountController::class, function (ContainerInterface $c) { return new AccountController( $c->get(self::TWIG), $c->get(UserHelper::class), + $c->get(AccountRepository::class), ); }); diff --git a/src/Frontend/Accounts/AccountController.php b/src/Frontend/Accounts/AccountController.php index d948371..a93ed33 100644 --- a/src/Frontend/Accounts/AccountController.php +++ b/src/Frontend/Accounts/AccountController.php @@ -3,15 +3,33 @@ declare(strict_types=1); namespace MailAccountAdmin\Frontend\Accounts; +use MailAccountAdmin\Common\UserHelper; use MailAccountAdmin\Frontend\BaseController; +use MailAccountAdmin\Repositories\AccountRepository; use Psr\Http\Message\ResponseInterface as Response; use Psr\Http\Message\ServerRequestInterface as Request; +use Slim\Views\Twig; class AccountController extends BaseController { + /** @var AccountRepository */ + private $accountRepository; + + public function __construct(Twig $view, UserHelper $userHelper, AccountRepository $accountRepository) + { + parent::__construct($view, $userHelper); + $this->accountRepository = $accountRepository; + } + public function showAccounts(Request $request, Response $response): Response { + // Parse query parameters for filters + $queryParams = $request->getQueryParams(); + $filterByDomain = $queryParams['domain'] ?? null; + $renderData = [ + 'filterDomain' => $filterByDomain, + 'accountList' => $this->accountRepository->fetchAccountList($filterByDomain), ]; return $this->view->render($response, 'accounts.html.twig', $renderData); diff --git a/src/Frontend/Domains/DomainController.php b/src/Frontend/Domains/DomainController.php index 172e25f..5451a1c 100644 --- a/src/Frontend/Domains/DomainController.php +++ b/src/Frontend/Domains/DomainController.php @@ -3,15 +3,28 @@ declare(strict_types=1); namespace MailAccountAdmin\Frontend\Domains; +use MailAccountAdmin\Common\UserHelper; use MailAccountAdmin\Frontend\BaseController; +use MailAccountAdmin\Repositories\DomainRepository; use Psr\Http\Message\ResponseInterface as Response; use Psr\Http\Message\ServerRequestInterface as Request; +use Slim\Views\Twig; class DomainController extends BaseController { + /** @var DomainRepository */ + private $domainRepository; + + public function __construct(Twig $view, UserHelper $userHelper, DomainRepository $domainRepository) + { + parent::__construct($view, $userHelper); + $this->domainRepository = $domainRepository; + } + public function showDomains(Request $request, Response $response): Response { $renderData = [ + 'domainList' => $this->domainRepository->fetchDomainList(), ]; return $this->view->render($response, 'domains.html.twig', $renderData); diff --git a/src/Repositories/AccountRepository.php b/src/Repositories/AccountRepository.php new file mode 100644 index 0000000..a97e3cd --- /dev/null +++ b/src/Repositories/AccountRepository.php @@ -0,0 +1,35 @@ +pdo->prepare($query); + $statement->execute($queryParams); + return $statement->fetchAll(PDO::FETCH_ASSOC); + } +} diff --git a/src/Repositories/AdminUserRepository.php b/src/Repositories/AdminUserRepository.php index 84376f5..bc10c38 100644 --- a/src/Repositories/AdminUserRepository.php +++ b/src/Repositories/AdminUserRepository.php @@ -7,16 +7,8 @@ use MailAccountAdmin\Exceptions\AdminUserNotFoundException; use MailAccountAdmin\Models\AdminUser; use PDO; -class AdminUserRepository +class AdminUserRepository extends BaseRepository { - /** @var PDO */ - private $pdo; - - public function __construct(PDO $pdo) - { - $this->pdo = $pdo; - } - /** * @throws AdminUserNotFoundException */ diff --git a/src/Repositories/BaseRepository.php b/src/Repositories/BaseRepository.php new file mode 100644 index 0000000..2108442 --- /dev/null +++ b/src/Repositories/BaseRepository.php @@ -0,0 +1,17 @@ +pdo = $pdo; + } +} diff --git a/src/Repositories/DomainRepository.php b/src/Repositories/DomainRepository.php new file mode 100644 index 0000000..94dddb9 --- /dev/null +++ b/src/Repositories/DomainRepository.php @@ -0,0 +1,38 @@ +pdo->query(' + SELECT + REGEXP_REPLACE(address, "^.*@", "") AS domain, + COUNT(is_account) AS account_count, + COUNT(is_alias) AS alias_count + FROM ( + SELECT username AS address, 1 AS is_account, NULL AS is_alias FROM mail_users + UNION + SELECT mail_address AS address, NULL AS is_account, 1 AS is_alias FROM mail_aliases + ) AS addresses + GROUP BY domain + '); + + $domainRows = $statement->fetchAll(PDO::FETCH_ASSOC); + $domainsCounted = []; + foreach ($domainRows as $row) { + $domainsCounted[$row['domain']] = [ + 'accounts' => $row['account_count'], + 'aliases' => $row['alias_count'], + ]; + } + + ksort($domainsCounted); + return $domainsCounted; + } +} diff --git a/templates/accounts.html.twig b/templates/accounts.html.twig index ecfaddd..b920b3b 100644 --- a/templates/accounts.html.twig +++ b/templates/accounts.html.twig @@ -5,6 +5,48 @@ {% block content %}
List of accounts ... TODO
- +List of all mail accounts.
+ + + + + +| Username | +Domain | +Aliases | +Active | +Home directory | +Memo | +Created | +Last modified | +||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| {{ account['username'] }} | +{{ account['domain'] }} | +{{ account['alias_count'] }} | +{{ account['is_active'] == 1 ? 'Yes' : 'No' }} | +vmail/{{ account['home_dir'] }} | +{{ account['memo'] }} | +{{ account['created_at'] }} | +{{ account['modified_at'] }} | +||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| No accounts found. | +|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
List of domains ... TODO
- +This is a list of all domains auto-generated from the existing mail accounts and aliases. As such it is read-only.
+ +| Domain | +Accounts | +Aliases | +|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| {{ domain }} | +{{ domainCounts['accounts'] }} | +{{ domainCounts['aliases'] }} | +|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| No domains found. | +|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||