From d5789fdedf405129b7ca19f2eedb3cb44510839e Mon Sep 17 00:00:00 2001 From: binaryDiv Date: Fri, 30 Jul 2021 01:50:36 +0200 Subject: [PATCH 1/3] Domains: Fetch list of domains from database --- public/static/style.css | 6 ++++ src/Dependencies.php | 7 +++++ src/Frontend/Domains/DomainController.php | 13 ++++++++ src/Repositories/AdminUserRepository.php | 10 +----- src/Repositories/BaseRepository.php | 17 ++++++++++ src/Repositories/DomainRepository.php | 38 +++++++++++++++++++++++ templates/domains.html.twig | 18 +++++++++-- 7 files changed, 98 insertions(+), 11 deletions(-) create mode 100644 src/Repositories/BaseRepository.php create mode 100644 src/Repositories/DomainRepository.php diff --git a/public/static/style.css b/public/static/style.css index 4fd2214..993d5da 100644 --- a/public/static/style.css +++ b/public/static/style.css @@ -104,3 +104,9 @@ h2 { button { padding: 0.2em 1em; } + +table, tr, td, th { + border: 1px solid #999999; + border-collapse: collapse; + padding: 0.25em 0.5em; +} diff --git a/src/Dependencies.php b/src/Dependencies.php index ac6fbb4..e3cc9f7 100644 --- a/src/Dependencies.php +++ b/src/Dependencies.php @@ -10,6 +10,7 @@ use MailAccountAdmin\Frontend\Domains\DomainController; use MailAccountAdmin\Frontend\Login\LoginController; use MailAccountAdmin\Frontend\Dashboard\DashboardController; use MailAccountAdmin\Repositories\AdminUserRepository; +use MailAccountAdmin\Repositories\DomainRepository; use PDO; use Psr\Container\ContainerInterface; use Slim\Views\Twig; @@ -58,6 +59,11 @@ class Dependencies $c->get(self::DATABASE), ); }); + $container->set(DomainRepository::class, function (ContainerInterface $c) { + return new DomainRepository( + $c->get(self::DATABASE), + ); + }); // Helper classes $container->set(UserHelper::class, function (ContainerInterface $c) { @@ -84,6 +90,7 @@ class Dependencies return new DomainController( $c->get(self::TWIG), $c->get(UserHelper::class), + $c->get(DomainRepository::class), ); }); $container->set(AccountController::class, function (ContainerInterface $c) { 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/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/domains.html.twig b/templates/domains.html.twig index 6ac7814..f1f5ef7 100644 --- a/templates/domains.html.twig +++ b/templates/domains.html.twig @@ -5,6 +5,20 @@ {% block content %}

Domains

-

List of domains ... TODO

-

Test

+

This is a list of all domains auto-generated from the existing mail accounts and aliases. As such it is read-only.

+ + + + + + + + {% for domain, domainCounts in domainList -%} + + + + + + {% endfor %} +
DomainAccountsAliases
{{ domain }}{{ domainCounts['accounts'] }}{{ domainCounts['aliases'] }}
{% endblock %} From 279f4492e8a0e377518f8e94afaea8d502a8e143 Mon Sep 17 00:00:00 2001 From: binaryDiv Date: Fri, 30 Jul 2021 03:45:21 +0200 Subject: [PATCH 2/3] Styles: Change link colors --- public/static/style.css | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/public/static/style.css b/public/static/style.css index 993d5da..0c69551 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; From 985f46c65266fb7f6cdabb8f016675e3a0d29332 Mon Sep 17 00:00:00 2001 From: binaryDiv Date: Fri, 30 Jul 2021 03:46:43 +0200 Subject: [PATCH 3/3] Accounts: Fetch list of all accounts (optionally filtered by domain) --- public/static/style.css | 28 +++++++++++++ src/Dependencies.php | 7 ++++ src/Frontend/Accounts/AccountController.php | 18 ++++++++ src/Repositories/AccountRepository.php | 35 ++++++++++++++++ templates/accounts.html.twig | 46 ++++++++++++++++++++- templates/domains.html.twig | 20 +++++---- 6 files changed, 145 insertions(+), 9 deletions(-) create mode 100644 src/Repositories/AccountRepository.php diff --git a/public/static/style.css b/public/static/style.css index 0c69551..ab04854 100644 --- a/public/static/style.css +++ b/public/static/style.css @@ -112,6 +112,10 @@ a:hover, a:focus { padding: 1em; } +.gray { + color: gray; +} + button { padding: 0.2em 1em; } @@ -121,3 +125,27 @@ table, tr, td, th { 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 e3cc9f7..f7f9742 100644 --- a/src/Dependencies.php +++ b/src/Dependencies.php @@ -9,6 +9,7 @@ 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; @@ -64,6 +65,11 @@ class Dependencies $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) { @@ -97,6 +103,7 @@ class Dependencies 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/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/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 %}

Accounts

-

List of accounts ... TODO

-

Test

+

List of all mail accounts.

+ +
+
+

Filter:

+ + + + +
+
+ + + + + + + + + + + + + + + {% if accountList %} + {% for account in accountList -%} + + + + + + + + + + + {% endfor %} + {% else %} + + + + {% endif %} +
UsernameDomainAliasesActiveHome directoryMemoCreatedLast 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.
{% endblock %} diff --git a/templates/domains.html.twig b/templates/domains.html.twig index f1f5ef7..79d0044 100644 --- a/templates/domains.html.twig +++ b/templates/domains.html.twig @@ -13,12 +13,18 @@ Accounts Aliases - {% for domain, domainCounts in domainList -%} - - {{ domain }} - {{ domainCounts['accounts'] }} - {{ domainCounts['aliases'] }} - - {% endfor %} + {% if domainList %} + {% for domain, domainCounts in domainList -%} + + {{ domain }} + {{ domainCounts['accounts'] }} + {{ domainCounts['aliases'] }} + + {% endfor %} + {% else %} + + No domains found. + + {% endif %} {% endblock %}