Compare commits
No commits in common. "7859ef77ee23aefefd7e8c1ee5132dee3a17f27d" and "985f46c65266fb7f6cdabb8f016675e3a0d29332" have entirely different histories.
7859ef77ee
...
985f46c652
|
|
@ -86,8 +86,12 @@ main.login_page {
|
||||||
border: 1px solid #666666;
|
border: 1px solid #666666;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
main.login_page table td {
|
||||||
|
padding: 0.2em;
|
||||||
|
}
|
||||||
|
|
||||||
/* --- Text and other styling --- */
|
/* --- Text and other styling --- */
|
||||||
h2, h4 {
|
h2 {
|
||||||
margin: 0 0 0.5em 0;
|
margin: 0 0 0.5em 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -101,9 +105,9 @@ a:hover, a:focus {
|
||||||
text-decoration: underline;
|
text-decoration: underline;
|
||||||
}
|
}
|
||||||
|
|
||||||
.error_box {
|
.error {
|
||||||
background: #ff4444;
|
background: #ff4444;
|
||||||
max-width: 50em;
|
width: 30em;
|
||||||
margin: 1em 0;
|
margin: 1em 0;
|
||||||
padding: 1em;
|
padding: 1em;
|
||||||
}
|
}
|
||||||
|
|
@ -112,50 +116,31 @@ a:hover, a:focus {
|
||||||
color: gray;
|
color: gray;
|
||||||
}
|
}
|
||||||
|
|
||||||
.green {
|
|
||||||
color: green;
|
|
||||||
}
|
|
||||||
|
|
||||||
.red {
|
|
||||||
color: red;
|
|
||||||
}
|
|
||||||
|
|
||||||
button {
|
button {
|
||||||
padding: 0.2em 1em;
|
padding: 0.2em 1em;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
table, tr, td, th {
|
||||||
|
border: 1px solid #999999;
|
||||||
|
border-collapse: collapse;
|
||||||
|
padding: 0.25em 0.5em;
|
||||||
|
}
|
||||||
|
|
||||||
.inactive {
|
.inactive {
|
||||||
color: gray;
|
color: gray;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* --- Tables --- */
|
/* --- Filter options --- */
|
||||||
|
.filter_options {
|
||||||
table td, table th {
|
|
||||||
padding: 0.25em 0.5em;
|
|
||||||
}
|
|
||||||
|
|
||||||
table.bordered_table,
|
|
||||||
table.bordered_table tr,
|
|
||||||
table.bordered_table td,
|
|
||||||
table.bordered_table th {
|
|
||||||
border: 1px solid #999999;
|
|
||||||
border-collapse: collapse;
|
|
||||||
padding: 0.25em 0.5em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.vertical_table_headers th {
|
|
||||||
text-align: left;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* --- Boxes --- */
|
|
||||||
.filter_options,
|
|
||||||
.edit_box,
|
|
||||||
.confirmation_box {
|
|
||||||
border: 1px solid #999999;
|
border: 1px solid #999999;
|
||||||
padding: 1em;
|
padding: 1em;
|
||||||
margin: 1em 0;
|
margin: 1em 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.filter_options h4 {
|
||||||
|
margin: 0 0 0.5em 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* --- Detail columns --- */
|
/* --- Detail columns --- */
|
||||||
input#show_details_checkbox {
|
input#show_details_checkbox {
|
||||||
margin-bottom: 1em;
|
margin-bottom: 1em;
|
||||||
|
|
@ -164,13 +149,3 @@ input#show_details_checkbox {
|
||||||
input#show_details_checkbox:not(:checked) ~ table .detail_column {
|
input#show_details_checkbox:not(:checked) ~ table .detail_column {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* --- Edit box --- */
|
|
||||||
.edit_box p:last-child {
|
|
||||||
margin-bottom: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* --- Confirmation box --- */
|
|
||||||
.confirmation_box p:first-child {
|
|
||||||
margin-top: 0;
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,6 @@ use MailAccountAdmin\Frontend\Login\LoginController;
|
||||||
use MailAccountAdmin\Frontend\Dashboard\DashboardController;
|
use MailAccountAdmin\Frontend\Dashboard\DashboardController;
|
||||||
use MailAccountAdmin\Repositories\AccountRepository;
|
use MailAccountAdmin\Repositories\AccountRepository;
|
||||||
use MailAccountAdmin\Repositories\AdminUserRepository;
|
use MailAccountAdmin\Repositories\AdminUserRepository;
|
||||||
use MailAccountAdmin\Repositories\AliasRepository;
|
|
||||||
use MailAccountAdmin\Repositories\DomainRepository;
|
use MailAccountAdmin\Repositories\DomainRepository;
|
||||||
use PDO;
|
use PDO;
|
||||||
use Psr\Container\ContainerInterface;
|
use Psr\Container\ContainerInterface;
|
||||||
|
|
@ -71,11 +70,6 @@ class Dependencies
|
||||||
$c->get(self::DATABASE),
|
$c->get(self::DATABASE),
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
$container->set(AliasRepository::class, function (ContainerInterface $c) {
|
|
||||||
return new AliasRepository(
|
|
||||||
$c->get(self::DATABASE),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
// Helper classes
|
// Helper classes
|
||||||
$container->set(UserHelper::class, function (ContainerInterface $c) {
|
$container->set(UserHelper::class, function (ContainerInterface $c) {
|
||||||
|
|
@ -110,7 +104,6 @@ class Dependencies
|
||||||
$c->get(self::TWIG),
|
$c->get(self::TWIG),
|
||||||
$c->get(UserHelper::class),
|
$c->get(UserHelper::class),
|
||||||
$c->get(AccountRepository::class),
|
$c->get(AccountRepository::class),
|
||||||
$c->get(AliasRepository::class),
|
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,8 +0,0 @@
|
||||||
<?php
|
|
||||||
declare(strict_types=1);
|
|
||||||
|
|
||||||
namespace MailAccountAdmin\Exceptions;
|
|
||||||
|
|
||||||
class AccountNotFoundException extends AppException
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
@ -6,7 +6,6 @@ namespace MailAccountAdmin\Frontend\Accounts;
|
||||||
use MailAccountAdmin\Common\UserHelper;
|
use MailAccountAdmin\Common\UserHelper;
|
||||||
use MailAccountAdmin\Frontend\BaseController;
|
use MailAccountAdmin\Frontend\BaseController;
|
||||||
use MailAccountAdmin\Repositories\AccountRepository;
|
use MailAccountAdmin\Repositories\AccountRepository;
|
||||||
use MailAccountAdmin\Repositories\AliasRepository;
|
|
||||||
use Psr\Http\Message\ResponseInterface as Response;
|
use Psr\Http\Message\ResponseInterface as Response;
|
||||||
use Psr\Http\Message\ServerRequestInterface as Request;
|
use Psr\Http\Message\ServerRequestInterface as Request;
|
||||||
use Slim\Views\Twig;
|
use Slim\Views\Twig;
|
||||||
|
|
@ -15,14 +14,11 @@ class AccountController extends BaseController
|
||||||
{
|
{
|
||||||
/** @var AccountRepository */
|
/** @var AccountRepository */
|
||||||
private $accountRepository;
|
private $accountRepository;
|
||||||
/** @var AliasRepository */
|
|
||||||
private $aliasRepository;
|
|
||||||
|
|
||||||
public function __construct(Twig $view, UserHelper $userHelper, AccountRepository $accountRepository, AliasRepository $aliasRepository)
|
public function __construct(Twig $view, UserHelper $userHelper, AccountRepository $accountRepository)
|
||||||
{
|
{
|
||||||
parent::__construct($view, $userHelper);
|
parent::__construct($view, $userHelper);
|
||||||
$this->accountRepository = $accountRepository;
|
$this->accountRepository = $accountRepository;
|
||||||
$this->aliasRepository = $aliasRepository;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function showAccounts(Request $request, Response $response): Response
|
public function showAccounts(Request $request, Response $response): Response
|
||||||
|
|
@ -38,90 +34,4 @@ class AccountController extends BaseController
|
||||||
|
|
||||||
return $this->view->render($response, 'accounts.html.twig', $renderData);
|
return $this->view->render($response, 'accounts.html.twig', $renderData);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function showAccountDetails(Request $request, Response $response, array $args): Response
|
|
||||||
{
|
|
||||||
// Parse URL arguments
|
|
||||||
$accountId = (int)$args['id'];
|
|
||||||
|
|
||||||
// Get account data from database
|
|
||||||
$accountData = $this->accountRepository->fetchAccountById($accountId);
|
|
||||||
$accountUsername = $accountData['username'];
|
|
||||||
$accountData['domain'] = explode('@', $accountUsername, 2)[1];
|
|
||||||
|
|
||||||
// Don't display the password hash, but at least the type of hash (used hash algorithm)
|
|
||||||
if ($accountData['password'] === '') {
|
|
||||||
$passwordHashType = 'empty';
|
|
||||||
} else {
|
|
||||||
$passwordHashInfo = password_get_info($accountData['password']);
|
|
||||||
$passwordHashType = $passwordHashInfo['algoName'] ?? 'unknown';
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get list of aliases for this account
|
|
||||||
$aliases = $this->aliasRepository->fetchAliasesForUserId($accountId);
|
|
||||||
|
|
||||||
$renderData = [
|
|
||||||
'id' => $accountId,
|
|
||||||
'accountUsername' => $accountUsername,
|
|
||||||
'accountData' => $accountData,
|
|
||||||
'passwordHashType' => $passwordHashType,
|
|
||||||
'aliases' => $aliases,
|
|
||||||
];
|
|
||||||
|
|
||||||
return $this->view->render($response, 'account_details.html.twig', $renderData);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function showAccountCreate(Request $request, Response $response): Response
|
|
||||||
{
|
|
||||||
return $this->showAccounts($request, $response);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function showAccountEdit(Request $request, Response $response, array $args): Response
|
|
||||||
{
|
|
||||||
// Parse URL arguments
|
|
||||||
$accountId = (int)$args['id'];
|
|
||||||
|
|
||||||
// Get account data from database
|
|
||||||
$accountData = $this->accountRepository->fetchAccountById($accountId);
|
|
||||||
|
|
||||||
$renderData = [
|
|
||||||
'id' => $accountId,
|
|
||||||
'accountUsername' => $accountData['username'],
|
|
||||||
'accountData' => $accountData,
|
|
||||||
];
|
|
||||||
|
|
||||||
return $this->view->render($response, 'account_edit.html.twig', $renderData);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function editAccount(Request $request, Response $response, array $args): Response
|
|
||||||
{
|
|
||||||
// TODO: just a placeholder
|
|
||||||
$this->view->getEnvironment()->addGlobal('error', 'Not implemented yet!');
|
|
||||||
return $this->showAccountEdit($request, $response, $args);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function showAccountDelete(Request $request, Response $response, array $args): Response
|
|
||||||
{
|
|
||||||
// Parse URL arguments
|
|
||||||
$accountId = (int)$args['id'];
|
|
||||||
|
|
||||||
// Get account data and list of aliases from database
|
|
||||||
$accountData = $this->accountRepository->fetchAccountById($accountId);
|
|
||||||
$aliases = $this->aliasRepository->fetchAliasesForUserId($accountId);
|
|
||||||
|
|
||||||
$renderData = [
|
|
||||||
'id' => $accountId,
|
|
||||||
'accountUsername' => $accountData['username'],
|
|
||||||
'aliases' => $aliases,
|
|
||||||
];
|
|
||||||
|
|
||||||
return $this->view->render($response, 'account_delete.html.twig', $renderData);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function deleteAccount(Request $request, Response $response, array $args): Response
|
|
||||||
{
|
|
||||||
// TODO: just a placeholder
|
|
||||||
$this->view->getEnvironment()->addGlobal('error', 'Not implemented yet!');
|
|
||||||
return $this->showAccountDelete($request, $response, $args);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,6 @@ declare(strict_types=1);
|
||||||
|
|
||||||
namespace MailAccountAdmin\Repositories;
|
namespace MailAccountAdmin\Repositories;
|
||||||
|
|
||||||
use MailAccountAdmin\Exceptions\AccountNotFoundException;
|
|
||||||
use PDO;
|
use PDO;
|
||||||
|
|
||||||
class AccountRepository extends BaseRepository
|
class AccountRepository extends BaseRepository
|
||||||
|
|
@ -33,16 +32,4 @@ class AccountRepository extends BaseRepository
|
||||||
$statement->execute($queryParams);
|
$statement->execute($queryParams);
|
||||||
return $statement->fetchAll(PDO::FETCH_ASSOC);
|
return $statement->fetchAll(PDO::FETCH_ASSOC);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function fetchAccountById(int $accountId): array
|
|
||||||
{
|
|
||||||
$statement = $this->pdo->prepare('SELECT * FROM mail_users WHERE user_id = :user_id LIMIT 1');
|
|
||||||
$statement->execute(['user_id' => $accountId]);
|
|
||||||
|
|
||||||
if ($statement->rowCount() < 1) {
|
|
||||||
throw new AccountNotFoundException("Account with user ID '$accountId' was not found.");
|
|
||||||
}
|
|
||||||
|
|
||||||
return $statement->fetch(PDO::FETCH_ASSOC);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,16 +0,0 @@
|
||||||
<?php
|
|
||||||
declare(strict_types=1);
|
|
||||||
|
|
||||||
namespace MailAccountAdmin\Repositories;
|
|
||||||
|
|
||||||
use PDO;
|
|
||||||
|
|
||||||
class AliasRepository extends BaseRepository
|
|
||||||
{
|
|
||||||
public function fetchAliasesForUserId(int $userId): array
|
|
||||||
{
|
|
||||||
$statement = $this->pdo->prepare('SELECT * FROM mail_aliases WHERE user_id = :user_id ORDER BY mail_address');
|
|
||||||
$statement->execute(['user_id' => $userId]);
|
|
||||||
return $statement->fetchAll(PDO::FETCH_ASSOC);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -23,14 +23,10 @@ class Routes
|
||||||
|
|
||||||
// Domains
|
// Domains
|
||||||
$app->get('/domains', DomainController::class . ':showDomains');
|
$app->get('/domains', DomainController::class . ':showDomains');
|
||||||
|
$app->get('/domains/{foo}', DomainController::class . ':showDomains');
|
||||||
|
|
||||||
// Accounts
|
// Accounts
|
||||||
$app->get('/accounts', AccountController::class . ':showAccounts');
|
$app->get('/accounts', AccountController::class . ':showAccounts');
|
||||||
$app->get('/accounts/new', AccountController::class . ':showAccountCreate');
|
$app->get('/accounts/{foo}', AccountController::class . ':showAccounts');
|
||||||
$app->get('/accounts/{id:[1-9][0-9]*}', AccountController::class . ':showAccountDetails');
|
|
||||||
$app->get('/accounts/{id:[1-9][0-9]*}/edit', AccountController::class . ':showAccountEdit');
|
|
||||||
$app->post('/accounts/{id:[1-9][0-9]*}/edit', AccountController::class . ':editAccount');
|
|
||||||
$app->get('/accounts/{id:[1-9][0-9]*}/delete', AccountController::class . ':showAccountDelete');
|
|
||||||
$app->post('/accounts/{id:[1-9][0-9]*}/delete', AccountController::class . ':deleteAccount');
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,44 +0,0 @@
|
||||||
{% extends "base.html.twig" %}
|
|
||||||
|
|
||||||
{% block title %}Delete account{% endblock %}
|
|
||||||
|
|
||||||
{% block content %}
|
|
||||||
<h2>Account: {{ accountUsername }}</h2>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
<b>Actions:</b>
|
|
||||||
<a href="/accounts/{{ id }}">View</a> |
|
|
||||||
<a href="/accounts/{{ id }}/edit">Edit</a> |
|
|
||||||
<span>Delete</span> |
|
|
||||||
<a href="mailto:{{ accountUsername }}">Send mail</a>
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<h3>Delete account</h3>
|
|
||||||
|
|
||||||
<p>You are about to delete the mail account "{{ accountUsername }}" including the following aliases:</p>
|
|
||||||
<ul>
|
|
||||||
{% for alias in aliases %}
|
|
||||||
<li>{{ alias['mail_address'] }}</li>
|
|
||||||
{% endfor %}
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<p><b>Note:</b> This will only delete the user entry from the database. Mail data will not be deleted!</p>
|
|
||||||
|
|
||||||
{% if error is defined %}
|
|
||||||
<div class="error_box">
|
|
||||||
<h4>Error:</h4>
|
|
||||||
{{ error }}
|
|
||||||
</div>
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
<div class="confirmation_box">
|
|
||||||
<p><b>Please confirm that you want to delete this account by entering your password.</b></p>
|
|
||||||
<form action="/accounts/{{ id }}/delete" method="POST">
|
|
||||||
<p>
|
|
||||||
<label for="admin_password">Your password:</label>
|
|
||||||
<input type="password" id="admin_password" name="admin_password"/>
|
|
||||||
</p>
|
|
||||||
<button type="submit">Delete account</button>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
{% endblock %}
|
|
||||||
|
|
@ -1,85 +0,0 @@
|
||||||
{% extends "base.html.twig" %}
|
|
||||||
|
|
||||||
{% block title %}View account{% endblock %}
|
|
||||||
|
|
||||||
{% block content %}
|
|
||||||
<h2>Account: {{ accountUsername }}</h2>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
<b>Actions:</b>
|
|
||||||
<span>View</span> |
|
|
||||||
<a href="/accounts/{{ id }}/edit">Edit</a> |
|
|
||||||
<a href="/accounts/{{ id }}/delete">Delete</a> |
|
|
||||||
<a href="mailto:{{ accountUsername }}">Send mail</a>
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<h3>View account details</h3>
|
|
||||||
|
|
||||||
<table class="bordered_table vertical_table_headers">
|
|
||||||
<tr>
|
|
||||||
<th style="min-width: 10em">User ID</th>
|
|
||||||
<td style="min-width: 20em">{{ accountData['user_id'] }}</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th>Username</th>
|
|
||||||
<td>{{ accountData['username'] }}</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th>Domain</th>
|
|
||||||
<td><a href="/accounts?domain={{ accountData['domain'] | escape('url') }}">{{ accountData['domain'] }}</a></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th>Password</th>
|
|
||||||
<td>
|
|
||||||
{% if passwordHashType == 'empty' %}
|
|
||||||
<span class="red">[No password set]</span>
|
|
||||||
{% elseif passwordHashType == 'unknown' %}
|
|
||||||
<span class="red">[Not hashed / unknown hash algorithm]</span>
|
|
||||||
{% else %}
|
|
||||||
<span class="gray">[{{ passwordHashType }} hash]</span>
|
|
||||||
{% endif %}
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th>Status</th>
|
|
||||||
<td>{{ accountData['is_active'] == '1' ? '<span class="green">Active</span>' : '<span class="red">Inactive</span>' }}</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th>Home directory</th>
|
|
||||||
<td><span class="gray">/srv/vmail/</span>{{ accountData['home_dir'] }}</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th>Admin memo</th>
|
|
||||||
<td>{{ accountData['memo'] | nl2br }}</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th>Created at</th>
|
|
||||||
<td>{{ accountData['created_at'] }}</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th>Last modified at</th>
|
|
||||||
<td>{{ accountData['modified_at'] }}</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
|
|
||||||
<h3>Aliases</h3>
|
|
||||||
|
|
||||||
{% if aliases %}
|
|
||||||
<table class="bordered_table">
|
|
||||||
<tr>
|
|
||||||
<th>Address</th>
|
|
||||||
<th>Created at</th>
|
|
||||||
<th>Actions</th>
|
|
||||||
</tr>
|
|
||||||
{% for alias in aliases %}
|
|
||||||
<tr>
|
|
||||||
<td>{{ alias['mail_address'] }}</td>
|
|
||||||
<td>{{ alias['created_at'] }}</td>
|
|
||||||
<td><a href="#">Delete</a></td> {# TODO #}
|
|
||||||
</tr>
|
|
||||||
{% endfor %}
|
|
||||||
</table>
|
|
||||||
{% else %}
|
|
||||||
<p>No aliases.</p>
|
|
||||||
{% endif %}
|
|
||||||
{% endblock %}
|
|
||||||
|
|
@ -1,115 +0,0 @@
|
||||||
{% extends "base.html.twig" %}
|
|
||||||
|
|
||||||
{% block title %}Edit account{% endblock %}
|
|
||||||
|
|
||||||
{% block content %}
|
|
||||||
<h2>Account: {{ accountUsername }}</h2>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
<b>Actions:</b>
|
|
||||||
<a href="/accounts/{{ id }}">View</a> |
|
|
||||||
<span>Edit</span> |
|
|
||||||
<a href="/accounts/{{ id }}/delete">Delete</a> |
|
|
||||||
<a href="mailto:{{ accountUsername }}">Send mail</a>
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<h3>Edit account data</h3>
|
|
||||||
|
|
||||||
<form action="/accounts/{{ id }}/edit" method="POST">
|
|
||||||
{% if error is defined %}
|
|
||||||
<div class="error_box">
|
|
||||||
<h4>Error</h4>
|
|
||||||
{{ error }}
|
|
||||||
</div>
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
<div class="edit_box">
|
|
||||||
<h4>Username</h4>
|
|
||||||
<table>
|
|
||||||
<tr>
|
|
||||||
<td>Current username:</td>
|
|
||||||
<td>{{ accountData['username'] }}</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td><label for="edit_username">New username:</label></td>
|
|
||||||
<td><input id="edit_username" name="username"/></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td colspan="2">
|
|
||||||
<label><input type="checkbox" name="username_create_alias"> Create alias for old username</label>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td colspan="2">
|
|
||||||
<label><input type="checkbox" name="username_replace_alias"> Replace existing alias</label>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="edit_box">
|
|
||||||
<h4>Password</h4>
|
|
||||||
<p>The new password will be hashed using the current default hash algorithm.</p>
|
|
||||||
<table>
|
|
||||||
<tr>
|
|
||||||
<td><label for="edit_password">New password:</label></td>
|
|
||||||
<td><input type="password" id="edit_password" name="password"/></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td><label for="edit_password_repeat">Repeat password:</label></td>
|
|
||||||
<td><input type="password" id="edit_password_repeat" name="password_repeat"/></td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="edit_box">
|
|
||||||
<h4>Account status</h4>
|
|
||||||
<table>
|
|
||||||
<tr>
|
|
||||||
<td>Current status:</td>
|
|
||||||
<td>{{ accountData['is_active'] == '1' ? '<span class="green">Active</span>' : '<span class="red">Inactive</span>' }}</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>New status:</td>
|
|
||||||
<td>
|
|
||||||
<label>
|
|
||||||
<input type="checkbox" name="is_active" {{ accountData['is_active'] == '1' ? 'checked' : '' }}/> Active
|
|
||||||
</label>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="edit_box">
|
|
||||||
<h4>Home directory</h4>
|
|
||||||
<p><b>Important:</b> Changing the home directory here will <b>NOT</b> move any existing mail data, this needs to be done
|
|
||||||
manually!</p>
|
|
||||||
<table>
|
|
||||||
<tr>
|
|
||||||
<td>Current home directory:</td>
|
|
||||||
<td><span class="gray">/srv/vmail/</span>{{ accountData['home_dir'] }}</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td><label for="edit_home_dir">New home directory:</label></td>
|
|
||||||
<td>
|
|
||||||
<span class="gray">/srv/vmail/</span><input id="edit_home_dir" name="home_dir"/>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="edit_box">
|
|
||||||
<h4><label for="edit_memo">Admin memo</label></h4>
|
|
||||||
<p>This field is only readable by admins.</p>
|
|
||||||
<table>
|
|
||||||
<tr>
|
|
||||||
<td><label for="edit_memo">Admin memo:</label></td>
|
|
||||||
<td><textarea id="edit_memo" name="memo" style="min-width: 40em;">{{ accountData['memo'] }}</textarea></td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<button type="submit">Save changes</button>
|
|
||||||
<button type="reset">Reset form</button>
|
|
||||||
</form>
|
|
||||||
{% endblock %}
|
|
||||||
|
|
@ -5,12 +5,7 @@
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<h2>Accounts</h2>
|
<h2>Accounts</h2>
|
||||||
|
|
||||||
<p>
|
<p>List of all mail accounts.</p>
|
||||||
<b>Actions:</b>
|
|
||||||
<a href="/accounts/new">Create account</a>
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<h3>List of accounts</h3>
|
|
||||||
|
|
||||||
<div class="filter_options">
|
<div class="filter_options">
|
||||||
<form action="/accounts" method="GET">
|
<form action="/accounts" method="GET">
|
||||||
|
|
@ -24,7 +19,7 @@
|
||||||
|
|
||||||
<input type="checkbox" id="show_details_checkbox"><label for="show_details_checkbox"> Show detail columns</label>
|
<input type="checkbox" id="show_details_checkbox"><label for="show_details_checkbox"> Show detail columns</label>
|
||||||
|
|
||||||
<table class="bordered_table">
|
<table>
|
||||||
<tr>
|
<tr>
|
||||||
<th style="min-width: 15em">Username</th>
|
<th style="min-width: 15em">Username</th>
|
||||||
<th style="min-width: 10em">Domain</th>
|
<th style="min-width: 10em">Domain</th>
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@
|
||||||
|
|
||||||
<p>This is a list of all domains auto-generated from the existing mail accounts and aliases. As such it is read-only.</p>
|
<p>This is a list of all domains auto-generated from the existing mail accounts and aliases. As such it is read-only.</p>
|
||||||
|
|
||||||
<table class="bordered_table">
|
<table>
|
||||||
<tr>
|
<tr>
|
||||||
<th style="min-width: 12em">Domain</th>
|
<th style="min-width: 12em">Domain</th>
|
||||||
<th>Accounts</th>
|
<th>Accounts</th>
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,7 @@
|
||||||
|
|
||||||
<form action="/login" method="POST">
|
<form action="/login" method="POST">
|
||||||
{% if error is defined %}
|
{% if error is defined %}
|
||||||
<div class="error_box">{{ error }}</div>
|
<div class="error">{{ error }}</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
<table>
|
<table>
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue