first
This commit is contained in:
commit
5aa7d034f7
3292 changed files with 465160 additions and 0 deletions
72
data/web/templates/admin.twig
Executable file
72
data/web/templates/admin.twig
Executable file
|
|
@ -0,0 +1,72 @@
|
|||
{% extends 'base.twig' %}
|
||||
|
||||
{% block content %}
|
||||
<div id="admin-content" class="responsive-tabs">
|
||||
<ul class="nav nav-tabs" role="tablist">
|
||||
<li class="nav-item dropdown">
|
||||
<a class="nav-link dropdown-toggle active" data-bs-toggle="dropdown" href="#" role="button" aria-expanded="false">{{ lang.admin.access }}</a>
|
||||
<ul class="dropdown-menu">
|
||||
<li><button class="dropdown-item active" data-bs-target="#tab-config-admins" aria-selected="false" aria-controls="tab-config-admins" role="tab" data-bs-toggle="tab">{{ lang.admin.admins }}</button></li>
|
||||
<!-- <li><button class="dropdown-item" data-bs-target="#tab-config-ldap-admins" aria-controls="tab-config-ldap-admins" role="tab" data-bs-toggle="tab">{{ lang.admin.admins_ldap }}</button></li> -->
|
||||
<li><button class="dropdown-item" data-bs-target="#tab-config-oauth2" aria-selected="false" aria-controls="tab-config-oauth2" role="tab" data-bs-toggle="tab">{{ lang.admin.oauth2_apps }}</button></li>
|
||||
<li><button class="dropdown-item" data-bs-target="#tab-config-rspamd" aria-selected="false" aria-controls="tab-config-rspamd" role="tab" data-bs-toggle="tab">Rspamd UI</button></li>
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
<li class="nav-item dropdown">
|
||||
<a class="nav-link dropdown-toggle" data-bs-toggle="dropdown" href="#" role="button" aria-expanded="false">{{ lang.admin.options }}</a>
|
||||
<ul class="dropdown-menu">
|
||||
<li><button class="dropdown-item" data-bs-target="#tab-config-dkim" aria-selected="false" aria-controls="tab-config-dkim" role="tab" data-bs-toggle="tab">{{ lang.admin.dkim_keys }}</button></li>
|
||||
<li><button class="dropdown-item" data-bs-target="#tab-config-fwdhosts" aria-selected="false" aria-controls="tab-config-fwdhosts" role="tab" data-bs-toggle="tab">{{ lang.admin.forwarding_hosts }}</button></li>
|
||||
<li><button class="dropdown-item" data-bs-target="#tab-config-f2b" aria-selected="false" aria-controls="tab-config-f2b" role="tab" data-bs-toggle="tab">{{ lang.admin.f2b_parameters }}</button></li>
|
||||
<li><button class="dropdown-item" data-bs-target="#tab-config-quarantine" aria-selected="false" aria-controls="tab-config-quarantine" role="tab" data-bs-toggle="tab">{{ lang.admin.quarantine }}</button></li>
|
||||
<li><button class="dropdown-item" data-bs-target="#tab-config-quota" aria-selected="false" aria-controls="tab-config-quota" role="tab" data-bs-toggle="tab">{{ lang.admin.quota_notifications }}</button></li>
|
||||
<li><button class="dropdown-item" data-bs-target="#tab-config-rsettings" aria-selected="false" aria-controls="tab-config-rsettings" role="tab" data-bs-toggle="tab">{{ lang.admin.rspamd_settings_map }}</button></li>
|
||||
<li><button class="dropdown-item" data-bs-target="#tab-config-password-settings" aria-selected="false" aria-controls="tab-config-password-settings" role="tab" data-bs-toggle="tab">{{ lang.admin.password_settings }}</button></li>
|
||||
<li><button class="dropdown-item" data-bs-target="#tab-config-customize" aria-selected="false" aria-controls="tab-config-customize" role="tab" data-bs-toggle="tab">{{ lang.admin.customize }}</button></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li role="presentation" class="nav-item"><button class="nav-link" data-bs-target="#tab-routing" aria-selected="false" aria-controls="tab-routing" role="tab" data-bs-toggle="tab">{{ lang.admin.routing }}</button></li>
|
||||
<li role="presentation" class="nav-item"><button class="nav-link" data-bs-target="#tab-sys-mails" aria-selected="false" aria-controls="tab-sys-mails" role="tab" data-bs-toggle="tab">{{ lang.admin.sys_mails }}</button></li>
|
||||
<li class="nav-item dropdown">
|
||||
<a class="nav-link dropdown-toggle" data-bs-toggle="dropdown" href="#" role="button" aria-expanded="false">{{ lang.admin.rspamd_global_filters }}</a>
|
||||
<ul class="dropdown-menu">
|
||||
<li><button class="dropdown-item" data-bs-target="#tab-globalfilter-regex" aria-selected="false" aria-controls="tab-globalfilter-regex" role="tab" data-bs-toggle="tab">{{ lang.admin.regex_maps }}</button></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<div class="tab-content" style="padding-top:20px">
|
||||
{% include 'admin/tab-config-admins.twig' %}
|
||||
{# {% include 'admin/tab-ldap.twig' %} #}
|
||||
{% include 'admin/tab-config-oauth2.twig' %}
|
||||
{% include 'admin/tab-config-rspamd.twig' %}
|
||||
{% include 'admin/tab-routing.twig' %}
|
||||
{% include 'admin/tab-config-dkim.twig' %}
|
||||
{% include 'admin/tab-config-fwdhosts.twig' %}
|
||||
{% include 'admin/tab-config-f2b.twig' %}
|
||||
{% include 'admin/tab-config-quarantine.twig' %}
|
||||
{% include 'admin/tab-config-quota.twig' %}
|
||||
{% include 'admin/tab-config-rsettings.twig' %}
|
||||
{% include 'admin/tab-config-customize.twig' %}
|
||||
{% include 'admin/tab-config-password-settings.twig' %}
|
||||
{% include 'admin/tab-sys-mails.twig' %}
|
||||
{% include 'admin/tab-globalfilter-regex.twig' %}
|
||||
</div>
|
||||
</div> <!-- /col-md-12 -->
|
||||
</div> <!-- /row -->
|
||||
</div>
|
||||
|
||||
{% include 'modals/admin.twig' %}
|
||||
|
||||
<script type='text/javascript'>
|
||||
var lang = {{ lang_admin|raw }};
|
||||
var lang_datatables = {{ lang_datatables|raw }};
|
||||
var admin_username = '{{ mailcow_cc_username }}';
|
||||
var csrf_token = '{{ csrf_token }}';
|
||||
var pagination_size = Math.trunc('{{ pagination_size }}');
|
||||
var log_pagination_size = Math.trunc('{{ log_pagination_size }}');
|
||||
</script>
|
||||
{% endblock %}
|
||||
9
data/web/templates/admin/customize/logo.twig
Executable file
9
data/web/templates/admin/customize/logo.twig
Executable file
|
|
@ -0,0 +1,9 @@
|
|||
<div class="thumbnail mb-4">
|
||||
<img class="img-thumbnail mb-4{% if dark %} bg-black{% endif %}" src="{{ logo }}" alt="mailcow logo">
|
||||
<div class="caption">
|
||||
<span class="badge fs-5 bg-info">{{ logo_specs.geometry.width }}x{{ logo_specs.geometry.height }} px</span>
|
||||
<span class="badge fs-5 bg-info">{{ logo_specs.mimetype }}</span>
|
||||
<span class="badge fs-5 bg-info">{{ logo_specs.fileSize }}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
254
data/web/templates/admin/tab-config-admins.twig
Executable file
254
data/web/templates/admin/tab-config-admins.twig
Executable file
|
|
@ -0,0 +1,254 @@
|
|||
<div class="tab-pane fade show active" id="tab-config-admins" role="tabpanel" aria-labelledby="tab-config-admins">
|
||||
<div class="card mb-4">
|
||||
<div class="card-header bg-danger text-white d-flex fs-5">
|
||||
<button class="btn d-md-none text-white flex-grow-1 text-start" data-bs-target="#collapse-tab-config-admins" data-bs-toggle="collapse" aria-controls="collapse-tab-config-admins">
|
||||
{{ lang.admin.admin_details }}
|
||||
</button>
|
||||
<span class="d-none d-md-block">{{ lang.admin.admin_details }}</span>
|
||||
</div>
|
||||
<div id="collapse-tab-config-admins" class="card-body collapse show" data-bs-parent="#admin-content">
|
||||
<table id="adminstable" class="table table-striped dt-responsive w-100"></table>
|
||||
<div class="mass-actions-admin mb-4">
|
||||
<div class="btn-group">
|
||||
<a class="btn btn-sm btn-xs-half d-block d-sm-inline btn-secondary" id="toggle_multi_select_all" data-id="admins" href="#"><i class="bi bi-check-all"></i> {{ lang.mailbox.toggle_all }}</a>
|
||||
<a class="btn btn-sm btn-xs-half d-block d-sm-inline btn-secondary dropdown-toggle" data-bs-toggle="dropdown" href="#">{{ lang.mailbox.quick_actions }}</a>
|
||||
<ul class="dropdown-menu">
|
||||
<li><a class="dropdown-item" data-action="edit_selected" data-id="admins" data-api-url='edit/admin' data-api-attr='{"active":"1"}' href="#">{{ lang.mailbox.activate }}</a></li>
|
||||
<li><a class="dropdown-item" data-action="edit_selected" data-id="admins" data-api-url='edit/admin' data-api-attr='{"active":"0"}' href="#">{{ lang.mailbox.deactivate }}</a></li>
|
||||
<li><hr class="dropdown-divider"></li>
|
||||
<li><a class="dropdown-item" data-action="edit_selected" data-id="admins" data-api-url='edit/admin' data-api-attr='{"disable_tfa":"1"}' href="#">{{ lang.tfa.disable_tfa }}</a></li>
|
||||
<li><hr class="dropdown-divider"></li>
|
||||
<li><a class="dropdown-item" data-action="delete_selected" data-id="admins" data-api-url='delete/admin' href="#">{{ lang.mailbox.remove }}</a></li>
|
||||
</ul>
|
||||
<a class="btn btn-sm d-block d-sm-inline btn-success" data-id="add_admin" data-bs-toggle="modal" data-bs-target="#addAdminModal" href="#"><i class="bi bi-person-plus-fill"></i> {{ lang.admin.add_admin }}</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{# TFA #}
|
||||
<legend style="margin-top:20px">
|
||||
{{ lang.tfa.tfa }}
|
||||
</legend>
|
||||
<hr />
|
||||
<div class="row">
|
||||
<div class="col-sm-3 col-5 text-end">{{ lang.tfa.tfa }}:</div>
|
||||
<div class="col-sm-9 col-7">
|
||||
{% include 'tfa_keys.twig' %}
|
||||
<br>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-3">
|
||||
<div class="col-sm-3 col-5 text-end">{{ lang.tfa.set_tfa }}:</div>
|
||||
<div class="col-sm-9 col-7">
|
||||
<select data-style="btn btn-sm dropdown-toggle bs-placeholder btn-secondary" data-width="fit" id="selectTFA" class="selectpicker" title="{{ lang.tfa.select }}">
|
||||
<option value="yubi_otp">{{ lang.tfa.yubi_otp }}</option>
|
||||
<option value="webauthn">{{ lang.tfa.webauthn }}</option>
|
||||
<option value="totp">{{ lang.tfa.totp }}</option>
|
||||
<option value="none">{{ lang.tfa.none }}</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{# FIDO2 #}
|
||||
<legend style="margin-top:20px">
|
||||
<i class="bi bi-shield-fill-check"></i>
|
||||
{{ lang.fido2.fido2_auth }}</legend><hr />
|
||||
<div class="row mb-3">
|
||||
<div class="col-sm-3 col-12 text-sm-end text-start mb-4">{{ lang.fido2.known_ids }}:</div>
|
||||
<div class="col-sm-9 col-12">
|
||||
<div class="table-responsive">
|
||||
<table class="table table-striped table-hover table-condensed" id="fido2_keys">
|
||||
<tr>
|
||||
<th>ID</th>
|
||||
<th style="min-width:240px;text-align: right">{{ lang.admin.action }}</th>
|
||||
</tr>
|
||||
{% include 'fido2.twig' %}
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<br>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="offset-sm-3 col-sm-9">
|
||||
<div class="btn-group nowrap mass-actions-admin">
|
||||
<button class="btn btn-sm btn-primary d-block d-sm-inline" id="register-fido2">{{ lang.fido2.set_fido2 }}</button>
|
||||
<button type="button" class="btn btn-sm btn-xs-lg btn-primary dropdown-toggle" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false"></button>
|
||||
<ul class="dropdown-menu">
|
||||
<li><a class="dropdown-item" href="#" id="register-fido2-touchid"><i class="bi bi-apple"></i> {{ lang.fido2.set_fido2_touchid }}</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mb-3" id="status-fido2">
|
||||
<div class="col-sm-3 col-5 text-end">{{ lang.fido2.register_status }}:</div>
|
||||
<div class="col-sm-9 col-7">
|
||||
<div id="fido2-alerts">-</div>
|
||||
</div>
|
||||
<br>
|
||||
</div>
|
||||
|
||||
<legend style="cursor:pointer;margin-top:20px" data-bs-target="#admin_api" unselectable="on" data-bs-toggle="collapse">
|
||||
<i style="font-size:10pt;" class="bi bi-plus-square"></i> API
|
||||
</legend>
|
||||
<hr />
|
||||
<div id="admin_api" class="collapse">
|
||||
<div class="row">
|
||||
<div class="col-lg-12">
|
||||
<p class="text-muted">{{ lang.admin.api_info|raw }}</p>
|
||||
</div>
|
||||
<div class="col-lg-12">
|
||||
<div class="card mb-3">
|
||||
<div class="card-header">
|
||||
<h4 class="card-title"><i class="bi bi-file-earmark-arrow-down"></i> {{ lang.admin.cors_settings }}</h4>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<form class="form-horizontal" autocapitalize="none" autocorrect="off" role="form" data-id="editcors" method="post">
|
||||
<div class="row mb-4">
|
||||
<label class="control-label col-sm-2 mb-4" for="allowed_origins">{{ lang.admin.allowed_origins }}</label>
|
||||
<div class="col-sm-9 mb-4">
|
||||
<textarea class="form-control textarea-code" rows="7" name="allowed_origins" id="allowed_origins">{{ cors_settings.allowed_origins }}</textarea>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-4">
|
||||
<label class="control-label col-sm-2" for="allowed_methods">{{ lang.admin.allowed_methods }}</label>
|
||||
<div class="col-sm-9">
|
||||
<select name="allowed_methods" id="allowed_methods" multiple class="form-control">
|
||||
<option value="POST"{% if "POST" in cors_settings.allowed_methods %} selected{% endif %}>POST</option>
|
||||
<option value="GET"{% if "GET" in cors_settings.allowed_methods %} selected{% endif %}>GET</option>
|
||||
<option value="DELETE"{% if "DELETE" in cors_settings.allowed_methods %} selected{% endif %}>DELETE</option>
|
||||
<option value="PUT"{% if "PUT" in cors_settings.allowed_methods %} selected{% endif %}>PUT</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-4">
|
||||
<div class="offset-sm-2 col-sm-9 d-grid d-sm-block">
|
||||
<button class="btn btn-sm btn-xs-lg btn-success" data-item="cors" data-api-url="edit/cors" data-id="editcors" data-action="edit_selected" href="#"><i class="bi bi-check-lg"></i> {{ lang.admin.save }}</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-lg-6">
|
||||
<div class="card mb-3">
|
||||
<div class="card-header">
|
||||
<h4 class="card-title"><i class="bi bi-file-earmark-arrow-down"></i> {{ lang.admin.api_read_only }}</h4>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<form class="form-horizontal" autocapitalize="none" autocorrect="off" role="form" method="post">
|
||||
<div class="row mb-4">
|
||||
<label class="control-label col-sm-3" for="allow_from_ro">{{ lang.admin.api_allow_from }}:</label>
|
||||
<div class="col-sm-9">
|
||||
<textarea class="form-control textarea-code" rows="7" name="allow_from" id="allow_from_ro" {% if api.ro.skip_ip_check %}disabled{% endif %} required>{{ api.ro.allow_from }}</textarea>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-2">
|
||||
<div class="offset-sm-3 col-sm-9">
|
||||
<label>
|
||||
<input type="checkbox" class="form-check-input" name="skip_ip_check" id="skip_ip_check_ro" {% if api.ro.skip_ip_check %}checked{% endif %}> {{ lang.admin.api_skip_ip_check }}
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-4">
|
||||
<label class="control-label col-sm-3">{{ lang.admin.api_key }}:</label>
|
||||
<div class="col-sm-9">
|
||||
<input type="text" class="form-control" value="{{ api.ro.api_key|default('-') }}" readonly />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-2">
|
||||
<div class="offset-sm-3 col-sm-9">
|
||||
<label>
|
||||
<input type="checkbox" class="form-check-input" name="active" {% if api.ro.active %}checked{% endif %}> {{ lang.admin.activate_api }}
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-2">
|
||||
<div class="offset-sm-3 col-sm-9">
|
||||
<div class="btn-group">
|
||||
<button class="btn btn-sm btn-xs-lg btn-xs-half d-block d-sm-inline btn-success" name="admin_api[ro]" type="submit" href="#"><i class="bi bi-check-lg"></i> {{ lang.admin.save }}</button>
|
||||
<button class="btn btn-sm btn-xs-lg btn-xs-half d-block d-sm-inline btn-secondary admin-ays-dialog" name="admin_api_regen_key[ro]" type="submit" href="#" {% if not api.ro.api_key %}disabled{% endif %}>{{ lang.admin.regen_api_key }}</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-lg-6">
|
||||
<div class="card mb-3">
|
||||
<div class="card-header">
|
||||
<h4 class="card-title"><i class="bi bi-file-earmark-diff"></i> {{ lang.admin.api_read_write }}</h4>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<form class="form-horizontal" autocapitalize="none" autocorrect="off" role="form" method="post">
|
||||
<div class="row mb-4">
|
||||
<label class="control-label col-sm-3" for="allow_from_rw">{{ lang.admin.api_allow_from }}:</label>
|
||||
<div class="col-sm-9">
|
||||
<textarea class="form-control textarea-code" rows="7" name="allow_from" id="allow_from_rw" {% if api.rw.skip_ip_check %}disabled{% endif %} required>{{ api.rw.allow_from }}</textarea>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-2">
|
||||
<div class="offset-sm-3 col-sm-9">
|
||||
<label>
|
||||
<input type="checkbox" class="form-check-input" name="skip_ip_check" id="skip_ip_check_rw" {% if api.rw.skip_ip_check %}checked{% endif %}> {{ lang.admin.api_skip_ip_check }}
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-4">
|
||||
<label class="control-label col-sm-3" for="admin_api_key">{{ lang.admin.api_key }}:</label>
|
||||
<div class="col-sm-9">
|
||||
<input type="text" class="form-control" value="{{ api.rw.api_key|default('-') }}" readonly />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-2">
|
||||
<div class="offset-sm-3 col-sm-9">
|
||||
<label>
|
||||
<input type="checkbox" class="form-check-input" name="active" {% if api.rw.active %}checked{% endif %}> {{ lang.admin.activate_api }}
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-2">
|
||||
<div class="offset-sm-3 col-sm-9">
|
||||
<div class="btn-group">
|
||||
<button class="btn btn-sm btn-xs-half d-block d-sm-inline btn-success" name="admin_api[rw]" type="submit" href="#"><i class="bi bi-check-lg"></i> {{ lang.admin.save }}</button>
|
||||
<button class="btn btn-sm btn-xs-half d-block d-sm-inline btn-secondary admin-ays-dialog" name="admin_api_regen_key[rw]" type="submit" {% if not api.rw.api_key %}disabled{% endif %} href="#">{{ lang.admin.regen_api_key }}</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card mb-4">
|
||||
<div class="card-header d-flex fs-5">
|
||||
<button class="btn d-md-none flex-grow-1 text-start" data-bs-target="#collapse-tab-config-dadmins" data-bs-toggle="collapse" aria-controls="collapse-tab-config-dadmins">
|
||||
{{ lang.admin.domain_admins }}
|
||||
</button>
|
||||
<span class="d-none d-md-block">{{ lang.admin.domain_admins }}</span>
|
||||
</div>
|
||||
<div id="collapse-tab-config-dadmins" class="card-body collapse" data-bs-parent="#admin-content">
|
||||
<table id="domainadminstable" class="table table-striped dt-responsive w-100"></table>
|
||||
<div class="mass-actions-admin">
|
||||
<div class="btn-group">
|
||||
<a class="btn btn-sm btn-xs-half d-block d-sm-inline btn-secondary" id="toggle_multi_select_all" data-id="domain_admins" href="#"><i class="bi bi-check-all"></i> {{ lang.mailbox.toggle_all }}</a>
|
||||
<a class="btn btn-sm btn-xs-half d-block d-sm-inline btn-secondary dropdown-toggle" data-bs-toggle="dropdown" href="#">{{ lang.mailbox.quick_actions }}</a>
|
||||
<ul class="dropdown-menu">
|
||||
<li><a class="dropdown-item" data-action="edit_selected" data-id="domain_admins" data-api-url='edit/domain-admin' data-api-attr='{"active":"1"}' href="#">{{ lang.mailbox.activate }}</a></li>
|
||||
<li><a class="dropdown-item" data-action="edit_selected" data-id="domain_admins" data-api-url='edit/domain-admin' data-api-attr='{"active":"0"}' href="#">{{ lang.mailbox.deactivate }}</a></li>
|
||||
<li><hr class="dropdown-divider"></li>
|
||||
<li><a class="dropdown-item" data-action="edit_selected" data-id="domain_admins" data-api-url='edit/domain-admin' data-api-attr='{"disable_tfa":"1"}' href="#">{{ lang.tfa.disable_tfa }}</a></li>
|
||||
<li><hr class="dropdown-divider"></li>
|
||||
<li><a class="dropdown-item" data-action="delete_selected" data-id="domain_admins" data-api-url='delete/domain-admin' href="#">{{ lang.mailbox.remove }}</a></li>
|
||||
</ul>
|
||||
<a class="btn btn-sm d-block d-sm-inline btn-success" data-id="add_domain_admin" data-bs-toggle="modal" data-bs-target="#addDomainAdminModal" href="#"><i class="bi bi-person-plus-fill"></i> {{ lang.admin.add_domain_admin }}</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
134
data/web/templates/admin/tab-config-customize.twig
Executable file
134
data/web/templates/admin/tab-config-customize.twig
Executable file
|
|
@ -0,0 +1,134 @@
|
|||
<div class="tab-pane fade" id="tab-config-customize" role="tabpanel" aria-labelledby="tab-config-customize">
|
||||
<div class="card mb-4">
|
||||
<div class="card-header d-flex fs-5">
|
||||
<button class="btn d-md-none flex-grow-1 text-start" data-bs-target="#collapse-tab-config-customize" data-bs-toggle="collapse" aria-controls="collapse-tab-config-customize">
|
||||
{{ lang.admin.customize }}
|
||||
</button>
|
||||
<span class="d-none d-md-block">{{ lang.admin.customize }}</span>
|
||||
</div>
|
||||
<div id="collapse-tab-config-customize" class="card-body collapse" data-bs-parent="#admin-content">
|
||||
<legend><i class="bi bi-file-image"></i> {{ lang.admin.change_logo }}</legend><hr />
|
||||
<p class="text-muted">{{ lang.admin.logo_info }}</p>
|
||||
<form class="form-inline" role="form" method="post" enctype="multipart/form-data">
|
||||
<div class="mb-4">
|
||||
<label for="main_logo_input" class="form-label">{{ lang.admin.logo_normal_label }}</label>
|
||||
<input class="form-control" id="main_logo_input" type="file" name="main_logo" accept="image/gif, image/jpeg, image/pjpeg, image/x-png, image/png, image/svg+xml">
|
||||
</div>
|
||||
<div class="mb-4">
|
||||
<label for="main_logo_dark_input" class="form-label">{{ lang.admin.logo_dark_label }}</label>
|
||||
<input class="form-control" id="main_logo_dark_input" type="file" name="main_logo_dark" accept="image/gif, image/jpeg, image/pjpeg, image/x-png, image/png, image/svg+xml">
|
||||
</div>
|
||||
|
||||
<button name="submit_main_logo" type="submit" class="btn btn-sm d-block d-sm-inline btn-secondary"><i class="bi bi-upload"></i> {{ lang.admin.upload }}</button>
|
||||
</form>
|
||||
{% if logo or logo_dark %}
|
||||
<div class="row mt-4">
|
||||
<div class="col-sm-4">
|
||||
{% if logo %}
|
||||
{% include 'admin/customize/logo.twig' %}
|
||||
{% endif %}
|
||||
{% if logo_dark %}
|
||||
{% include 'admin/customize/logo.twig' with {'logo': logo_dark, 'logo_specs': logo_dark_specs, 'dark': 1} %}
|
||||
{% endif %}
|
||||
<hr>
|
||||
<form class="form-inline" role="form" method="post">
|
||||
<p><button name="reset_main_logo" type="submit" class="btn btn-sm d-block d-sm-inline btn-secondary">{{ lang.admin.reset_default }}</button></p>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
<legend style="padding-top:20px" unselectable="on">{{ lang.admin.ip_check }}</legend><hr />
|
||||
<div id="ip_check">
|
||||
<form class="form" data-id="ip_check" role="form" method="post">
|
||||
<div class="mb-4">
|
||||
<input class="form-check-input" type="checkbox" value="1" name="ip_check_opt_in" id="ip_check_opt_in" {% if ip_check == 1 %}checked{% endif %}>
|
||||
<label class="form-check-label" for="ip_check_opt_in">
|
||||
{{ lang.admin.ip_check_opt_in|raw }}
|
||||
</label>
|
||||
</div>
|
||||
<p><div class="btn-group">
|
||||
<button class="btn btn-sm btn-xs-half d-block d-sm-inline btn-success" data-action="edit_selected" data-item="admin" data-id="ip_check" data-reload="no" data-api-url='edit/ip_check' data-api-attr='{}' href="#"><i class="bi bi-check-lg"></i> {{ lang.admin.save }}</button>
|
||||
</div></p>
|
||||
</form>
|
||||
</div>
|
||||
<legend>{{ lang.admin.app_links }}</legend><hr />
|
||||
<p class="text-muted">{{ lang.admin.merged_vars_hint|raw }}</p>
|
||||
<form class="form-inline" data-id="app_links" role="form" method="post">
|
||||
<table class="table table-condensed" style="white-space: nowrap;" id="app_link_table">
|
||||
<tr>
|
||||
<th>{{ lang.admin.app_name }}</th>
|
||||
<th>{{ lang.admin.link }}</th>
|
||||
<th style="width:100px;"> </th>
|
||||
</tr>
|
||||
{% for row in app_links %}
|
||||
{% for key, val in row %}
|
||||
<tr>
|
||||
<td><input class="input-sm input-xs-lg form-control" data-id="app_links" type="text" name="app" required value="{{ key }}"></td>
|
||||
<td><input class="input-sm input-xs-lg form-control" data-id="app_links" type="text" name="href" required value="{{ val }}"></td>
|
||||
<td><a href="#" role="button" class="btn btn-sm btn-xs-lg btn-secondary h-100 w-100" type="button">{{ lang.admin.remove_row }}</a></td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
{% endfor %}
|
||||
{% for app in mailcow_apps %}
|
||||
<tr>
|
||||
<td><input class="input-sm input-xs-lg form-control" value="{{ app.name }}" disabled></td>
|
||||
<td><input class="input-sm input-xs-lg form-control" value="{{ app.link }}" disabled></td>
|
||||
<td><a href="#" role="button" class="btn btn-sm btn-xs-lg btn-secondary h-100 w-100 disabled" type="button">{{ lang.admin.remove_row }}</a></td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
<p><div class="btn-group">
|
||||
<button class="btn btn-sm btn-xs-half d-block d-sm-inline btn-success" data-action="edit_selected" data-item="admin" data-id="app_links" data-reload="no" data-api-url='edit/app_links' data-api-attr='{}' href="#"><i class="bi bi-check-lg"></i> {{ lang.admin.save }}</button>
|
||||
<button class="btn btn-sm btn-xs-half d-block d-sm-inline btn-secondary" type="button" id="add_app_link_row">{{ lang.admin.add_row }}</button>
|
||||
</div></p>
|
||||
</form>
|
||||
<legend data-bs-target="#ui_texts" style="padding-top:20px" unselectable="on">{{ lang.admin.ui_texts }}</legend><hr />
|
||||
<div id="ui_texts">
|
||||
<form class="form" data-id="uitexts" role="form" method="post">
|
||||
<div class="mb-2">
|
||||
<label for="uitests_title_name">{{ lang.admin.title_name }}:</label>
|
||||
<input type="text" class="form-control" id="uitests_title_name" name="title_name" placeholder="mailcow UI" value="{{ ui_texts.title_name|raw }}">
|
||||
</div>
|
||||
<div class="mb-2">
|
||||
<label for="uitests_main_name">{{ lang.admin.main_name }}:</label>
|
||||
<input type="text" class="form-control" id="uitests_main_name" name="main_name" placeholder="mailcow UI" value="{{ ui_texts.main_name|raw }}">
|
||||
</div>
|
||||
<div class="mb-2">
|
||||
<label for="uitests_apps_name">{{ lang.admin.apps_name }}:</label>
|
||||
<input type="text" class="form-control" id="uitests_apps_name" name="apps_name" placeholder="{{ lang.header.apps }}" value="{{ ui_texts.apps_name|raw }}">
|
||||
</div>
|
||||
<div class="mb-4">
|
||||
<label for="help_text">{{ lang.admin.help_text }}:</label>
|
||||
<textarea class="form-control" id="help_text" name="help_text" rows="7">{{ ui_texts.help_text|raw }}</textarea>
|
||||
</div>
|
||||
<hr>
|
||||
<div>
|
||||
<p class="text-muted">{{ lang.admin.ui_header_announcement_help }}</p>
|
||||
<label for="ui_announcement_type">{{ lang.admin.ui_header_announcement }}:</label>
|
||||
<div class="row">
|
||||
<div class="col-12 col-md-6 col-lg-4 col-xl-3">
|
||||
<p><select multiple data-width="100%" id="ui_announcement_type" name="ui_announcement_type" class="selectpicker show-tick" data-max-options="1" title="{{ lang.admin.ui_header_announcement_select }}">
|
||||
<option {% if ui_texts.ui_announcement_type == 'info' %}selected{% endif %} value="info">{{ lang.admin.ui_header_announcement_type_info }}</option>
|
||||
<option {% if ui_texts.ui_announcement_type == 'warning' %}selected{% endif %} value="warning">{{ lang.admin.ui_header_announcement_type_warning }}</option>
|
||||
<option {% if ui_texts.ui_announcement_type == 'danger' %}selected{% endif %} value="danger">{{ lang.admin.ui_header_announcement_type_danger }}</option>
|
||||
</select></p>
|
||||
</div>
|
||||
</div>
|
||||
<p><textarea class="form-control" id="ui_announcement_text" name="ui_announcement_text" rows="7">{{ ui_texts.ui_announcement_text }}</textarea></p>
|
||||
<div class="form-check">
|
||||
<label>
|
||||
<input type="checkbox" name="ui_announcement_active" class="form-check-input" {% if ui_texts.ui_announcement_active == 1 %}checked{% endif %}> {{ lang.admin.ui_header_announcement_active }}
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<hr>
|
||||
<div class="mb-4">
|
||||
<label for="ui_footer">{{ lang.admin.ui_footer }}:</label>
|
||||
<textarea class="form-control" id="ui_footer" name="ui_footer" rows="7">{{ ui_texts.ui_footer }}</textarea>
|
||||
</div>
|
||||
<button class="btn btn-sm d-block d-sm-inline btn-success" data-action="edit_selected" data-item="ui" data-id="uitexts" data-api-url='edit/ui_texts' data-api-attr='{}' href="#"><i class="bi bi-check-lg"></i> {{ lang.admin.save }}</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
193
data/web/templates/admin/tab-config-dkim.twig
Executable file
193
data/web/templates/admin/tab-config-dkim.twig
Executable file
|
|
@ -0,0 +1,193 @@
|
|||
<div class="tab-pane fade" id="tab-config-dkim" role="tabpanel" aria-labelledby="tab-config-dkim">
|
||||
<div class="card mb-4">
|
||||
<div class="card-header d-flex fs-5">
|
||||
<button class="btn d-md-none flex-grow-1 text-start" data-bs-target="#collapse-tab-config-dkim" data-bs-toggle="collapse" aria-controls="collapse-tab-config-dkim">
|
||||
{{ lang.admin.dkim_keys }}
|
||||
</button>
|
||||
<span class="d-none d-md-block">{{ lang.admin.dkim_keys }}</span>
|
||||
</div>
|
||||
<div id="collapse-tab-config-dkim" class="card-body collapse" data-bs-parent="#admin-content">
|
||||
<div class="btn-group my-4" role="group">
|
||||
<input type="checkbox" id="check-dkim_key_valid" class="btn-check" autocomplete="off" data-bs-toggle="collapse" data-bs-target=".dkim_key_valid" checked>
|
||||
<label class="btn btn-outline-secondary btn-check-label" for="check-dkim_key_valid">{{ lang.admin.dkim_key_valid }}</label>
|
||||
|
||||
<input type="checkbox" id="check-dkim_key_unused" class="btn-check" autocomplete="off" data-bs-toggle="collapse" data-bs-target=".dkim_key_unused" checked>
|
||||
<label class="btn btn-outline-secondary btn-check-label" for="check-dkim_key_unused">{{ lang.admin.dkim_key_unused }}</label>
|
||||
|
||||
<input type="checkbox" id="check-dkim_key_missing" class="btn-check" autocomplete="off" data-bs-toggle="collapse" data-bs-target=".dkim_key_missing" checked>
|
||||
<label class="btn btn-outline-secondary btn-check-label" for="check-dkim_key_missing">{{ lang.admin.dkim_key_missing }}</label>
|
||||
</div>
|
||||
{% for domain, domain_data in dkim_domains %}
|
||||
{% if domain_data.dkim %}
|
||||
<div class="row collapse show dkim_key_valid">
|
||||
<div class="col-md-1"><input type="checkbox" class="form-check-input" data-id="dkim" name="multi_select" value="{{ domain }}"></div>
|
||||
<div class="col-md-3">
|
||||
<p>{{ lang.admin.domain }}: <strong>{{ domain }}</strong>
|
||||
<p class="dkim-label"><span class="badge fs-6 bg-success">{{ lang.admin.dkim_key_valid }}</span></p>
|
||||
<p class="dkim-label"><span class="badge fs-6 bg-primary">{{ lang.admin.dkim_domains_selector }} '{{ domain_data.dkim.dkim_selector }}'</span></p>
|
||||
<p class="dkim-label"><span class="badge fs-6 bg-info">{{ domain_data.dkim.length }} bit</span></p>
|
||||
</p>
|
||||
</div>
|
||||
<div class="col-md-8">
|
||||
<textarea class="form-control" rows="6" readonly>{{ domain_data.dkim.dkim_txt }}</textarea>
|
||||
<small>
|
||||
<i class="bi bi-arrow-return-right"></i>
|
||||
<a href="#" data-bs-toggle="modal" data-bs-target="#showDKIMprivKey" id="dkim_priv" data-priv-key="{{ domain_data.dkim.privkey }}"> {{ lang.admin.dkim_private_key }}</a>
|
||||
</small>
|
||||
</div>
|
||||
<hr class="d-block d-md-none">
|
||||
</div>
|
||||
{% else %}
|
||||
<div class="row collapse in dkim_key_missing">
|
||||
<div class="col-md-1"><input class="dkim_missing" type="checkbox" data-id="dkim" name="multi_select" value="{{ domain }}" disabled></div>
|
||||
<div class="col-md-3">
|
||||
<p>{{ lang.admin.domain }}: <strong>{{ domain }}</strong><br><span class="badge fs-6 bg-danger">{{ lang.admin.dkim_key_missing }}</span></p>
|
||||
</div>
|
||||
<div class="col-md-8"><pre>-</pre></div>
|
||||
<hr class="d-block d-md-none">
|
||||
</div>
|
||||
{% endif %}
|
||||
{% for alias_domain, alias_domain_data in domain_data.alias_domains %}
|
||||
{% if alias_domain_data.dkim %}
|
||||
<div class="row collapse in dkim_key_valid">
|
||||
<div class="col-md-1"><input type="checkbox" class="form-check-input" data-id="dkim" name="multi_select" value="{{ alias_domain }}"></div>
|
||||
<div class="col-md-2 offset-md-1">
|
||||
<p><small>↳ Alias-Domain: <strong>{{ alias_domain }}</strong></small>
|
||||
<p class="dkim-label"><span class="badge fs-6 bg-success">{{ lang.admin.dkim_key_valid }}</span></p>
|
||||
<p class="dkim-label"><span class="badge fs-6 bg-primary">Selector '{{ alias_domain_data.dkim.dkim_selector }}'</span></p>
|
||||
<p class="dkim-label"><span class="badge fs-6 bg-info">{{ alias_domain_data.dkim.length }} bit</span></p>
|
||||
</p>
|
||||
</div>
|
||||
<div class="col-md-8">
|
||||
<pre>{{ alias_domain_data.dkim.dkim_txt }}</pre>
|
||||
<p data-bs-toggle="modal" data-bs-target="#showDKIMprivKey" id="dkim_priv" style="cursor:pointer;margin-top:-8pt" data-priv-key="{{ alias_domain_data.dkim.privkey }}"><small><i class="bi bi-arrow-return-right"></i> Private key</small></p>
|
||||
</div>
|
||||
<hr class="d-block d-md-none">
|
||||
</div>
|
||||
{% else %}
|
||||
<div class="row collapse in dkim_key_missing">
|
||||
<div class="col-md-1"><input class="dkim_missing" type="checkbox" data-id="dkim" name="multi_select" value="{{ alias_domain }}" disabled></div>
|
||||
<div class="col-md-2 offset-md-1">
|
||||
<p><small>↳ Alias-Domain: <strong>{{ alias_domain }}</strong><br></small><span class="badge fs-6 bg-danger">{{ lang.admin.dkim_key_missing }}</span></p>
|
||||
</div>
|
||||
<div class="col-md-8"><pre>-</pre></div>
|
||||
<hr class="d-block d-md-none">
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% endfor %}
|
||||
{% for blind, data in dkim_blind_domains|filter(data => data.dkim is not null) %}
|
||||
<div class="row collapse in dkim_key_unused">
|
||||
<div class="col-md-1"><input type="checkbox" class="form-check-input" data-id="dkim" name="multi_select" value="{{ blind }}"></div>
|
||||
<div class="col-md-3">
|
||||
<p>{{ lang.admin.domain }}: <strong>{{ blind }}</strong>
|
||||
<p class="dkim-label"><span class="badge fs-6 bg-warning">{{ lang.admin.dkim_key_unused }}</span></p>
|
||||
<p class="dkim-label"><span class="badge fs-6 bg-primary">Selector '{{ data.dkim.dkim_selector }}'</span></p>
|
||||
<p class="dkim-label"><span class="badge fs-6 bg-info">{{ data.dkim.length }} bit</span></p>
|
||||
</p>
|
||||
</div>
|
||||
<div class="col-md-8">
|
||||
<pre>{{ data.dkim.dkim_txt }}</pre>
|
||||
<p data-bs-toggle="modal" data-bs-target="#showDKIMprivKey" id="dkim_priv" style="cursor:pointer;margin-top:-8pt" data-priv-key="{{ data.dkim.privkey }}"><small><i class="bi bi-arrow-return-right"></i> Private key</small></p>
|
||||
</div>
|
||||
<hr class="d-block d-md-none">
|
||||
</div>
|
||||
{% endfor %}
|
||||
|
||||
<div class="mass-actions-admin">
|
||||
<div class="btn-group btn-group-sm">
|
||||
<button type="button" id="toggle_multi_select_all" data-id="dkim" class="btn btn-sm btn-xs-half d-block d-sm-inline btn-secondary"><i class="bi bi-check-all"></i> {{ lang.mailbox.toggle_all }}</button>
|
||||
<button type="button" data-action="delete_selected" name="delete_selected" data-id="dkim" data-api-url="delete/dkim" class="btn btn-sm btn-xs-half d-block d-sm-inline btn-danger"><i class="bi bi-trash"></i> {{ lang.admin.remove }}</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<legend style="margin-top:40px">{{ lang.admin.dkim_add_key }}</legend><hr />
|
||||
<form class="form" data-id="dkim" role="form" method="post">
|
||||
<div class="mb-4">
|
||||
<label for="dkim_add_domains">{{ lang.admin.domain_s }}</label>
|
||||
<input class="form-control input-sm" id="dkim_add_domains" name="domains" placeholder="example.org, example.com" required>
|
||||
<small><i class="bi bi-arrow-return-right"></i> <a href="#" id="dkim_missing_keys">{{ lang.admin.dkim_domains_wo_keys }}</a></small>
|
||||
</div>
|
||||
<div class="mb-2">
|
||||
<label for="dkim_selector">{{ lang.admin.dkim_domains_selector }}</label>
|
||||
<input class="form-control input-sm" id="dkim_selector" name="dkim_selector" value="dkim" required>
|
||||
</div>
|
||||
<div class="row mb-4">
|
||||
<div class="col-12 col-md-6 col-lg-4 col-xl-3">
|
||||
<select data-style="btn btn-light btn-sm" class="form-control" id="key_size" name="key_size" title="{{ lang.admin.dkim_key_length }}" required>
|
||||
<option data-subtext="bits">1024</option>
|
||||
<option data-subtext="bits">2048</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<button class="btn btn-sm d-block d-sm-inline btn-success" data-action="add_item" data-id="dkim" data-api-url='add/dkim' data-api-attr='{}' href="#"><i class="bi bi-plus-lg"></i> {{ lang.admin.add }}</button>
|
||||
</form>
|
||||
|
||||
<legend data-bs-target="#import_dkim" style="margin-top:40px;cursor:pointer" unselectable="on" data-bs-toggle="collapse">
|
||||
<i style="font-size:10pt;" class="bi bi-plus-square"></i> {{ lang.admin.import_private_key }}
|
||||
</legend>
|
||||
<hr />
|
||||
<div id="import_dkim" class="collapse">
|
||||
<form class="form" data-id="dkim_import" role="form" method="post">
|
||||
<div class="mb-2">
|
||||
<label for="dkim_import_domain">{{ lang.admin.domain }}:</label>
|
||||
<input class="form-control input-sm" id="dkim_import_domain" name="domain" placeholder="example.org" required>
|
||||
</div>
|
||||
<div class="mb-2">
|
||||
<label for="dkim_import_selector">{{ lang.admin.dkim_domains_selector }}:</label>
|
||||
<input class="form-control input-sm" id="dkim_import_selector" name="dkim_selector" value="dkim" required>
|
||||
</div>
|
||||
<div class="mb-4">
|
||||
<label for="private_key_file">{{ lang.admin.private_key }}: (RSA PKCS#8)</label>
|
||||
<textarea class="form-control input-sm" rows="10" name="private_key_file" id="private_key_file" required placeholder="-----BEGIN RSA KEY-----"></textarea>
|
||||
</div>
|
||||
<div class="mb-2">
|
||||
<label>
|
||||
<input type="checkbox" class="form-check-input" name="overwrite_existing" value="1"> {{ lang.admin.dkim_overwrite_key }}
|
||||
</label>
|
||||
</div>
|
||||
<button class="btn btn-sm d-block d-sm-inline btn-secondary" data-action="add_item" data-id="dkim_import" data-api-url='add/dkim_import' data-api-attr='{}' href="#"><i class="bi bi-plus-lg"></i> {{ lang.admin.import }}</button>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<legend data-bs-target="#duplicate_dkim" style="margin-top:40px;cursor:pointer" unselectable="on" data-bs-toggle="collapse">
|
||||
<i style="font-size:10pt;" class="bi bi-plus-square"></i> {{ lang.admin.duplicate_dkim }}
|
||||
</legend>
|
||||
<hr />
|
||||
<div id="duplicate_dkim" class="collapse">
|
||||
<form class="form-horizontal" data-id="dkim_duplicate" role="form" method="post">
|
||||
<div class="row mb-2">
|
||||
<label class="control-label col-sm-2 text-sm-end" for="from_domain">{{ lang.admin.dkim_from }}:</label>
|
||||
<div class="col-sm-10 col-md-6 col-lg-4 col-xl-3">
|
||||
<select data-style="btn btn-light btn-sm"
|
||||
data-live-search="true"
|
||||
data-id="dkim_duplicate"
|
||||
title="{{ lang.admin.dkim_from_title }}"
|
||||
name="from_domain" id="from_domain" class="full-width-select form-control" required>
|
||||
{% for dkim_domain in dkim_domains_with_keys %}
|
||||
<option value="{{ dkim_domain }}">{{ dkim_domain }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-4">
|
||||
<label class="control-label col-sm-2 text-sm-end" for="to_domain">{{ lang.admin.dkim_to }}:</label>
|
||||
<div class="col-sm-10 col-md-6 col-lg-4 col-xl-3">
|
||||
<select
|
||||
data-live-search="true"
|
||||
data-style="btn btn-light btn-sm"
|
||||
data-id="dkim_duplicate"
|
||||
title="{{ lang.admin.dkim_to_title }}"
|
||||
name="to_domain" id="to_domain" class="full-width-select form-control" multiple required>
|
||||
{% for domain in all_domains %}
|
||||
<option value="{{ domain }}">{{ domain }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<button class="btn btn-sm d-block d-sm-inline btn-secondary" data-action="add_item" data-id="dkim_duplicate" data-api-url='add/dkim_duplicate' data-api-attr='{}' href="#"><i class="bi bi-clipboard-plus"></i> {{ lang.admin.duplicate }}</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
141
data/web/templates/admin/tab-config-f2b.twig
Executable file
141
data/web/templates/admin/tab-config-f2b.twig
Executable file
|
|
@ -0,0 +1,141 @@
|
|||
<div class="tab-pane fade" id="tab-config-f2b" role="tabpanel" aria-labelledby="tab-config-f2b">
|
||||
<div class="card mb-4">
|
||||
<div class="card-header d-flex fs-5">
|
||||
<button class="btn d-md-none flex-grow-1 text-start" data-bs-target="#collapse-tab-config-f2b" data-bs-toggle="collapse" aria-controls="collapse-tab-config-f2b">
|
||||
{{ lang.admin.f2b_parameters }}
|
||||
</button>
|
||||
<span class="d-none d-md-block">{{ lang.admin.f2b_parameters }}</span>
|
||||
</div>
|
||||
<div id="collapse-tab-config-f2b" class="card-body collapse" data-bs-parent="#admin-content">
|
||||
<form class="form" data-id="f2b" role="form" method="post">
|
||||
<div class="mb-4">
|
||||
<label for="f2b_ban_time">{{ lang.admin.f2b_ban_time }}:</label>
|
||||
<input type="number" class="form-control" id="f2b_ban_time" name="ban_time" value="{{ f2b_data.ban_time }}" required>
|
||||
</div>
|
||||
<div class="mb-4">
|
||||
<label for="f2b_max_ban_time">{{ lang.admin.f2b_max_ban_time }}:</label>
|
||||
<input type="number" class="form-control" id="f2b_max_ban_time" name="max_ban_time" value="{{ f2b_data.max_ban_time }}" required>
|
||||
</div>
|
||||
<div class="mb-4">
|
||||
<input class="form-check-input" type="checkbox" value="1" name="ban_time_increment" id="f2b_ban_time_increment" {% if f2b_data.ban_time_increment == 1 %}checked{% endif %}>
|
||||
<label class="form-check-label" for="f2b_ban_time_increment">{{ lang.admin.f2b_ban_time_increment }}</label>
|
||||
</div>
|
||||
<div class="mb-4">
|
||||
<label for="f2b_max_attempts">{{ lang.admin.f2b_max_attempts }}:</label>
|
||||
<input type="number" class="form-control" id="f2b_max_attempts" name="max_attempts" value="{{ f2b_data.max_attempts }}" required>
|
||||
</div>
|
||||
<div class="mb-4">
|
||||
<label for="f2b_retry_window">{{ lang.admin.f2b_retry_window }}:</label>
|
||||
<input type="number" class="form-control" id="f2b_retry_window" name="retry_window" value="{{ f2b_data.retry_window }}" required>
|
||||
</div>
|
||||
<div class="mb-4">
|
||||
<label for="f2b_netban_ipv4">{{ lang.admin.f2b_netban_ipv4 }}:</label>
|
||||
<div class="input-group">
|
||||
<span class="input-group-text">/</span>
|
||||
<input type="number" class="form-control" id="f2b_netban_ipv4" name="netban_ipv4" value="{{ f2b_data.netban_ipv4 }}" required>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mb-4">
|
||||
<label for="f2b_netban_ipv6">{{ lang.admin.f2b_netban_ipv6 }}:</label>
|
||||
<div class="input-group">
|
||||
<span class="input-group-text">/</span>
|
||||
<input type="number" class="form-control" id="f2b_netban_ipv6" name="netban_ipv6" value="{{ f2b_data.netban_ipv6 }}" required>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mb-4">
|
||||
<div class="form-check form-switch">
|
||||
<input class="form-check-input" type="checkbox" id="f2b_manage_external" value="1" name="manage_external" {% if f2b_data.manage_external == 1 %}checked{% endif %}>
|
||||
<label class="form-check-label" for="f2b_manage_external">{{ lang.admin.f2b_manage_external }}</label>
|
||||
</div>
|
||||
<p class="text-muted">{{ lang.admin.f2b_manage_external_info }}</p>
|
||||
</div>
|
||||
<hr>
|
||||
<p class="text-muted">{{ lang.admin.f2b_list_info|raw }}</p>
|
||||
<div class="mb-2">
|
||||
<label for="f2b_whitelist">{{ lang.admin.f2b_whitelist }}:</label>
|
||||
<textarea class="form-control" id="f2b_whitelist" name="whitelist" rows="5">{{ f2b_data.whitelist }}</textarea>
|
||||
</div>
|
||||
<div class="mb-4">
|
||||
<label for="f2b_blacklist">{{ lang.admin.f2b_blacklist }}:</label>
|
||||
<textarea class="form-control" id="f2b_blacklist" name="blacklist" rows="5">{{ f2b_data.blacklist }}</textarea>
|
||||
</div>
|
||||
<div class="btn-group">
|
||||
<button class="btn btn-sm btn-xs-half d-block d-sm-inline btn-success" data-action="edit_selected" data-item="self" data-id="f2b" data-api-url='edit/fail2ban' data-api-attr='{}' href="#"><i class="bi bi-check-lg"></i> {{ lang.admin.save }}</button>
|
||||
<a href="#" role="button" class="btn btn-sm btn-xs-half d-block d-sm-inline btn-secondary" data-bs-toggle="modal" data-container="netfilter-mailcow" data-bs-target="#RestartContainer"><i class="bi bi-arrow-repeat"></i> {{ lang.header.restart_netfilter }}</a>
|
||||
</div>
|
||||
</form>
|
||||
<legend data-bs-target="#f2b_regex_filters" style="margin-top:40px;cursor:pointer" unselectable="on" data-bs-toggle="collapse">
|
||||
<i style="font-size:10pt;" class="bi bi-plus-square"></i> {{ lang.admin.f2b_filter }}
|
||||
</legend>
|
||||
<hr />
|
||||
<div id="f2b_regex_filters" class="collapse">
|
||||
<p class="text-muted">{{ lang.admin.f2b_regex_info }}</p>
|
||||
<form class="form-inline" data-id="f2b_regex" role="form" method="post">
|
||||
<table class="table table-condensed" id="f2b_regex_table">
|
||||
<tr>
|
||||
<th width="50px">ID</th>
|
||||
<th>RegExp</th>
|
||||
<th width="100px"> </th>
|
||||
</tr>
|
||||
{% for regex_id, regex_val in f2b_data.regex %}
|
||||
<tr>
|
||||
<td><input disabled class="input-sm input-xs-lg form-control" style="text-align:center" data-id="f2b_regex" type="text" name="app" required value="{{ regex_id }}"></td>
|
||||
<td><input class="input-sm input-xs-lg form-control regex-input" data-id="f2b_regex" type="text" name="regex" required value="{{ regex_val }}"></td>
|
||||
<td><a href="#" role="button" class="btn btn-sm btn-xs-lg btn-secondary h-100 w-100" type="button">{{ lang.admin.remove_row }}</a></td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
<p><div class="btn-group">
|
||||
<button class="btn btn-sm btn-xs-half d-block d-sm-inline btn-success" data-action="edit_selected" data-item="admin" data-id="f2b_regex" data-reload="no" data-api-url='edit/fail2ban' data-api-attr='{"action":"edit-regex"}' href="#"><i class="bi bi-check-lg"></i> {{ lang.admin.save }}</button>
|
||||
<button class="btn btn-sm btn-xs-half d-block d-sm-inline btn-secondary admin-ays-dialog" data-action="edit_selected" data-item="self" data-id="f2b-quick" data-api-url='edit/fail2ban' data-api-attr='{"action":"reset-regex"}' href="#">{{ lang.admin.reset_default }}</button>
|
||||
<button class="btn btn-sm d-block d-sm-inline btn-secondary" type="button" id="add_f2b_regex_row"><i class="bi bi-plus-lg"></i> {{ lang.admin.add_row }}</button>
|
||||
</div></p>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<p class="text-muted">{{ lang.admin.ban_list_info|raw }}</p>
|
||||
{% if not f2b_data.active_bans and not f2b_data.perm_bans %}
|
||||
<i>{{ lang.admin.no_active_bans }}</i>
|
||||
{% endif %}
|
||||
<form class="form-inline" data-id="f2b_banlist" role="form" method="post">
|
||||
<div class="input-group mb-3">
|
||||
<input type="text" class="form-control" aria-label="Banlist url" value="{{ f2b_banlist_url}}" id="banlist_url">
|
||||
{% if is_https %}
|
||||
<button class="btn btn-secondary" type="button" onclick="copyToClipboard('banlist_url')"><i class="bi bi-clipboard"></i></button>
|
||||
{% endif %}
|
||||
<button class="btn btn-secondary" type="button" data-action="edit_selected" data-item="{{ f2b_data.banlist_id }}" data-id="f2b_banlist" data-api-url='edit/fail2ban/banlist' data-api-attr='{}'><i class="bi bi-arrow-clockwise"></i></button>
|
||||
</div>
|
||||
</form>
|
||||
{% for active_ban in f2b_data.active_bans %}
|
||||
<p>
|
||||
<span class="badge fs-7 bg-info d-block d-sm-inline-block">
|
||||
<i class="bi bi-funnel-fill"></i>
|
||||
<a href="https://bgp.he.net/ip/{{ active_ban.ip }}" target="_blank">
|
||||
{{ active_ban.network }}
|
||||
</a>
|
||||
({{ active_ban.banned_until }})
|
||||
</span>
|
||||
<span class="d-none d-sm-inline"> - </span>
|
||||
{% if active_ban.queued_for_unban == 0 %}
|
||||
<a data-action="edit_selected" data-item="{{ active_ban.network }}" data-id="f2b-quick" data-api-url='edit/fail2ban' data-api-attr='{"action":"unban"}' href="#">[{{ lang.admin.queue_unban }}]</a>
|
||||
<a data-action="edit_selected" data-item="{{ active_ban.network }}" data-id="f2b-quick" data-api-url='edit/fail2ban' data-api-attr='{"action":"whitelist"}' href="#">[whitelist]</a>
|
||||
<a data-action="edit_selected" data-item="{{ active_ban.network }}" data-id="f2b-quick" data-api-url='edit/fail2ban' data-api-attr='{"action":"blacklist"}' href="#">[blacklist (<b>needs restart</b>)]</a>
|
||||
{% else %}
|
||||
<i>{{ lang.admin.unban_pending }}</i>
|
||||
{% endif %}
|
||||
</p>
|
||||
{% endfor %}
|
||||
<hr>
|
||||
{% for perm_ban in f2b_data.perm_bans %}
|
||||
<p>
|
||||
<span class="badge fs-7 bg-danger d-block d-sm-inline-block">
|
||||
<i class="bi bi-funnel-fill"></i>
|
||||
<a href="https://bgp.he.net/ip/{{ perm_ban.ip }}" target="_blank">
|
||||
{{ perm_ban.network }}
|
||||
</a>
|
||||
</span>
|
||||
</p>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
41
data/web/templates/admin/tab-config-fwdhosts.twig
Executable file
41
data/web/templates/admin/tab-config-fwdhosts.twig
Executable file
|
|
@ -0,0 +1,41 @@
|
|||
<div class="tab-pane fade" id="tab-config-fwdhosts" role="tabpanel" aria-labelledby="tab-config-fwdhosts">
|
||||
<div class="card mb-4">
|
||||
<div class="card-header d-flex fs-5">
|
||||
<button class="btn d-md-none flex-grow-1 text-start" data-bs-target="#collapse-tab-config-fwdhosts" data-bs-toggle="collapse" aria-controls="collapse-tab-config-fwdhosts">
|
||||
{{ lang.admin.forwarding_hosts }}
|
||||
</button>
|
||||
<span class="d-none d-md-block">{{ lang.admin.forwarding_hosts }}</span>
|
||||
</div>
|
||||
<div id="collapse-tab-config-fwdhosts" class="card-body collapse" data-bs-parent="#admin-content">
|
||||
<p style="margin-bottom:40px">{{ lang.admin.forwarding_hosts_hint }}</p>
|
||||
<table id="forwardinghoststable" class="table table-striped dt-responsive w-100"></table>
|
||||
<div class="mass-actions-admin mb-4">
|
||||
<div class="btn-group btn-group-sm">
|
||||
<button type="button" id="toggle_multi_select_all" data-id="fwdhosts" class="btn btn-sm btn-xs-half d-block d-sm-inline btn-secondary">{{ lang.mailbox.toggle_all }}</button>
|
||||
<a class="btn btn-sm btn-xs-half d-block d-sm-inline btn-secondary dropdown-toggle" data-bs-toggle="dropdown" href="#">{{ lang.mailbox.quick_actions }}</a>
|
||||
<ul class="dropdown-menu top100">
|
||||
<li><a class="dropdown-item" data-action="edit_selected" data-id="fwdhosts" data-api-url='edit/fwdhost' data-api-attr='{"keep_spam":"0"}' href="#">Enable spam filter</a></li>
|
||||
<li><a class="dropdown-item" data-action="edit_selected" data-id="fwdhosts" data-api-url='edit/fwdhost' data-api-attr='{"keep_spam":"1"}' href="#">Disable spam filter</a></li>
|
||||
<li><hr class="dropdown-divider"></li>
|
||||
<li><a class="dropdown-item" data-action="delete_selected" data-id="fwdhosts" data-api-url='delete/fwdhost' href="#">{{ lang.admin.remove }}</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<legend>{{ lang.admin.add_forwarding_host }}</legend><hr />
|
||||
<p class="text-muted">{{ lang.admin.forwarding_hosts_add_hint }}</p>
|
||||
<form class="form" data-id="fwdhost" role="form" method="post">
|
||||
<div class="mb-2">
|
||||
<label for="fwdhost_hostname">{{ lang.admin.host }}</label>
|
||||
<input class="form-control" id="fwdhost_hostname" name="hostname" placeholder="example.org" required>
|
||||
</div>
|
||||
<div class="mb-4">
|
||||
<select data-width="200px" class="form-control" id="filter_spam" name="filter_spam" title="{{ lang.user.spamfilter }}" required>
|
||||
<option value="1">{{ lang.admin.active }}</option>
|
||||
<option value="0">{{ lang.admin.inactive }}</option>
|
||||
</select>
|
||||
</div>
|
||||
<button class="btn btn-sm d-block d-sm-inline btn-success" data-action="add_item" data-id="fwdhost" data-api-url='add/fwdhost' data-api-attr='{}' href="#"><i class="bi bi-plus-lg"></i> {{ lang.admin.add }}</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
28
data/web/templates/admin/tab-config-oauth2.twig
Executable file
28
data/web/templates/admin/tab-config-oauth2.twig
Executable file
|
|
@ -0,0 +1,28 @@
|
|||
<div class="tab-pane fade" id="tab-config-oauth2" role="tabpanel" aria-labelledby="tab-config-oauth2">
|
||||
<div class="card mb-4">
|
||||
<div class="card-header d-flex fs-5">
|
||||
<button class="btn d-md-none flex-grow-1 text-start" data-bs-target="#collapse-tab-config-oauth2" data-bs-toggle="collapse" aria-controls="collapse-tab-config-oauth2">
|
||||
{{ lang.admin.oauth2_apps }}
|
||||
</button>
|
||||
<span class="d-none d-md-block">{{ lang.admin.oauth2_apps }}</span>
|
||||
</div>
|
||||
<div id="collapse-tab-config-oauth2" class="card-body collapse" data-bs-parent="#admin-content">
|
||||
<p>{{ lang.admin.oauth2_info|raw }}</p>
|
||||
<table id="oauth2clientstable" class="table table-striped dt-responsive w-100"></table>
|
||||
<div class="mass-actions-admin">
|
||||
<div class="btn-group">
|
||||
<a class="btn btn-sm btn-xs-half d-block d-sm-inline btn-secondary" id="toggle_multi_select_all" data-id="oauth2_clients" href="#"><i class="bi bi-check-all"></i> {{ lang.mailbox.toggle_all }}</a>
|
||||
<a class="btn btn-sm btn-xs-half d-block d-sm-inline btn-secondary dropdown-toggle" data-bs-toggle="dropdown" href="#">{{ lang.mailbox.quick_actions }}</a>
|
||||
<ul class="dropdown-menu">
|
||||
<li><a class="dropdown-item" data-action="delete_selected" data-id="oauth2_clients" data-api-url='delete/oauth2-client' href="#">{{ lang.mailbox.remove }}</a></li>
|
||||
<li><hr class="dropdown-divider"></li>
|
||||
<li><a class="dropdown-item" data-action="edit_selected" data-id="oauth2_clients" data-api-url='edit/oauth2-client' data-api-attr='{"revoke_tokens":"1"}' href="#">{{ lang.admin.oauth2_revoke_tokens }}</a></li>
|
||||
<li><hr class="dropdown-divider"></li>
|
||||
<li><a class="dropdown-item" data-action="edit_selected" data-id="oauth2_clients" data-api-url='edit/oauth2-client' data-api-attr='{"renew_secret":"1"}' href="#">{{ lang.admin.oauth2_renew_secret }}</a></li>
|
||||
</ul>
|
||||
<a class="btn btn-sm d-block d-sm-inline btn-success" data-id="add_oauth2_client" data-bs-toggle="modal" data-bs-target="#addOAuth2ClientModal" href="#"><i class="bi bi-plus-lg"></i> {{ lang.admin.oauth2_add_client }}</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
102
data/web/templates/admin/tab-config-password-settings.twig
Executable file
102
data/web/templates/admin/tab-config-password-settings.twig
Executable file
|
|
@ -0,0 +1,102 @@
|
|||
<div class="tab-pane fade" id="tab-config-password-settings" role="tabpanel" aria-labelledby="tab-config-password-settings">
|
||||
<div class="card mb-4">
|
||||
<div class="card-header d-flex fs-5">
|
||||
<button class="btn d-md-none flex-grow-1 text-start" data-bs-target="#collapse-tab-config-password-settings" data-bs-toggle="collapse" aria-controls="collapse-tab-config-password-settings">
|
||||
{{ lang.admin.password_settings }}
|
||||
</button>
|
||||
<span class="d-none d-md-block">{{ lang.admin.password_settings }}</span>
|
||||
</div>
|
||||
<div id="collapse-tab-config-password-settings" class="card-body collapse" data-bs-parent="#admin-content">
|
||||
<form class="form-horizontal" data-id="passwordpolicy" role="form" method="post">
|
||||
<div class="row">
|
||||
<div class="col-sm-12">
|
||||
<legend>
|
||||
{{ lang.admin.password_policy }}
|
||||
</legend>
|
||||
<hr />
|
||||
</div>
|
||||
</div>
|
||||
{% for name, value in password_complexity %}
|
||||
{% if name == 'length' %}
|
||||
<div class="row mb-4">
|
||||
<label class="control-label col-sm-3 text-sm-end" for="length">{{ lang.admin.password_length }}:</label>
|
||||
<div class="col-sm-2">
|
||||
<input type="number" class="form-control" min="3" max="64" name="length" id="length" value="{{ value }}" required>
|
||||
</div>
|
||||
</div>
|
||||
{% else %}
|
||||
<input type="hidden" name="{{ name }}" value="0">
|
||||
<div class="row mb-2">
|
||||
<div class="offset-sm-3 col-sm-9">
|
||||
<label>
|
||||
<input type="checkbox" class="form-check-input" name="{{ name }}" id="{{ name }}" value="1" {% if value == 1 %}checked{% endif %}> {{ lang.admin['password_policy_'~name] }}
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
<div class="row mt-4 mb-2">
|
||||
<div class="offset-sm-3 col-sm-9">
|
||||
<div class="btn-group">
|
||||
<button class="btn btn-sm d-block d-sm-inline btn-success" data-item="passwordpolicy" data-action="edit_selected" data-id="passwordpolicy" data-api-url='edit/passwordpolicy' data-api-attr='{}' href="#"><i class="bi bi-check-lg"></i> {{ lang.admin.save }}</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<form class="form" role="form" data-id="pw_reset_notification" method="post" style="margin-top: 50px;">
|
||||
<div class="row">
|
||||
<div class="col-sm-12">
|
||||
<legend>
|
||||
{{ lang.admin.password_reset_settings }}
|
||||
</legend>
|
||||
<hr />
|
||||
<small>{{ lang.admin.reset_password_vars|raw }}</small><br><br>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-4">
|
||||
<div class="col-sm-6">
|
||||
<div>
|
||||
<label for="pw_reset_from">{{ lang.admin.quota_notification_sender }}:</label>
|
||||
<input type="email" class="form-control" id="pw_reset_from" name="from" value="{{ pw_reset_data.from }}">
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-6">
|
||||
<div>
|
||||
<label for="pw_reset_subject">{{ lang.admin.quota_notification_subject }}:</label>
|
||||
<input type="text" class="form-control" id="pw_reset_subject" name="subject" value="{{ pw_reset_data.subject }}">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-12" data-bs-target="#text_template" style="cursor:pointer" unselectable="on" data-bs-toggle="collapse">
|
||||
<span class="d-block"><i style="font-size:10pt;" class="bi bi-plus-square"></i> {{ lang.admin.password_reset_tmpl_text }}</span>
|
||||
<small>{{ lang.admin.restore_template }}</small>
|
||||
</div>
|
||||
<div id="text_template" class="col-12 collapse">
|
||||
<textarea autocorrect="off" spellcheck="false" autocapitalize="none" class="form-control textarea-code mb-2" rows="20" name="text_tmpl">{{ pw_reset_data.text_tmpl|raw }}</textarea>
|
||||
</div>
|
||||
<div class="col-12 mt-3" data-bs-target="#html_template" style="cursor:pointer" unselectable="on" data-bs-toggle="collapse">
|
||||
<span class="d-block"><i style="font-size:10pt;" class="bi bi-plus-square"></i> {{ lang.admin.password_reset_tmpl_html }}</span>
|
||||
<small>{{ lang.admin.restore_template }}</small>
|
||||
</div>
|
||||
<div id="html_template" class="col-12 collapse">
|
||||
<textarea autocorrect="off" spellcheck="false" autocapitalize="none" class="form-control textarea-code" rows="20" name="html_tmpl">{{ pw_reset_data.html_tmpl|raw }}</textarea>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-sm-10">
|
||||
<div>
|
||||
<br>
|
||||
<a type="button" class="btn btn-sm d-block d-sm-inline btn-success" data-action="edit_selected"
|
||||
data-item="pw_reset_notification"
|
||||
data-id="pw_reset_notification"
|
||||
data-api-url='edit/reset-password-notification'
|
||||
data-api-attr='{}'><i class="bi bi-check-lg"></i> {{ lang.user.save_changes }}</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
96
data/web/templates/admin/tab-config-quarantine.twig
Executable file
96
data/web/templates/admin/tab-config-quarantine.twig
Executable file
|
|
@ -0,0 +1,96 @@
|
|||
<div class="tab-pane fade" id="tab-config-quarantine" role="tabpanel" aria-labelledby="tab-config-quarantine">
|
||||
<div class="card mb-4">
|
||||
<div class="card-header d-flex fs-5">
|
||||
<button class="btn d-md-none flex-grow-1 text-start" data-bs-target="#collapse-tab-config-quarantine" data-bs-toggle="collapse" aria-controls="collapse-tab-config-quarantine">
|
||||
{{ lang.admin.quarantine }}
|
||||
</button>
|
||||
<span class="d-none d-md-block">{{ lang.admin.quarantine }}</span>
|
||||
</div>
|
||||
<div id="collapse-tab-config-quarantine" class="card-body collapse" data-bs-parent="#admin-content">
|
||||
{% if not q_data.retention_size or not q_data.max_size %}
|
||||
<div class="alert alert-info">{{ lang.quarantine.disabled_by_config }}</div>
|
||||
{% endif %}
|
||||
<form class="form-horizontal" data-id="quarantine" role="form" method="post">
|
||||
<div class="row mb-4">
|
||||
<label class="col-sm-4 control-label text-sm-end" for="quarantine_retention_size">{{ lang.admin.quarantine_retention_size|raw }}</label>
|
||||
<div class="col-sm-8">
|
||||
<input type="number" class="form-control" id="quarantine_retention_size" name="retention_size" value="{{ q_data.retention_size }}" placeholder="0" required>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-4">
|
||||
<label class="col-sm-4 control-label text-sm-end" for="quarantine_max_size">{{ lang.admin.quarantine_max_size|raw }}</label>
|
||||
<div class="col-sm-8">
|
||||
<input type="number" class="form-control" id="quarantine_max_size" name="max_size" value="{{ q_data.max_size }}" placeholder="0" required>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-4">
|
||||
<label class="col-sm-4 control-label text-sm-end" for="quarantine_max_score">{{ lang.admin.quarantine_max_score|raw }}</label>
|
||||
<div class="col-sm-8">
|
||||
<input type="number" class="form-control" id="quarantine_max_score" name="max_score" value="{{ q_data.max_score }}" placeholder="9999.0">
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-4">
|
||||
<label class="col-sm-4 control-label text-sm-end" for="quarantine_max_age">{{ lang.admin.quarantine_max_age|raw }}</label>
|
||||
<div class="col-sm-8">
|
||||
<input type="number" class="form-control" id="quarantine_max_age" name="max_age" value="{{ q_data.max_age }}" min="1" required>
|
||||
</div>
|
||||
</div>
|
||||
<hr>
|
||||
<div class="row mb-4">
|
||||
<label class="col-sm-4 control-label text-sm-end" for="quarantine_redirect"><i class="bi bi-box-arrow-right"></i> {{ lang.admin.quarantine_redirect|raw }}</label>
|
||||
<div class="col-sm-8">
|
||||
<input type="email" class="form-control" id="quarantine_redirect" name="redirect" value="{{ q_data.redirect }}" placeholder="">
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-4">
|
||||
<label class="col-sm-4 control-label text-sm-end" for="quarantine_bcc"><i class="bi bi-files"></i> {{ lang.admin.quarantine_bcc|raw }}</label>
|
||||
<div class="col-sm-8">
|
||||
<input type="email" class="form-control" id="quarantine_bcc" name="bcc" value="{{ q_data.bcc }}" placeholder="">
|
||||
</div>
|
||||
</div>
|
||||
<hr>
|
||||
<div class="row mb-2">
|
||||
<label class="col-sm-4 control-label text-sm-end" for="quarantine_sender">{{ lang.admin.quarantine_notification_sender }}:</label>
|
||||
<div class="col-sm-8">
|
||||
<input type="email" class="form-control" id="quarantine_sender" name="sender" value="{{ q_data.sender }}" placeholder="quarantine@localhost">
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-4">
|
||||
<label class="col-sm-4 control-label text-sm-end" for="quarantine_subject">{{ lang.admin.quarantine_notification_subject }}:</label>
|
||||
<div class="col-sm-8">
|
||||
<input type="text" class="form-control" id="quarantine_subject" name="subject" value="{{ q_data.subject }}" placeholder="Spam Quarantine Notification">
|
||||
</div>
|
||||
</div>
|
||||
<hr>
|
||||
<div class="row mb-2">
|
||||
<label class="col-sm-4 control-label text-sm-end" for="quarantine_release_format">{{ lang.admin.quarantine_release_format }}:</label>
|
||||
<div class="col-sm-8 col-md-6 col-lg-4 col-xl-3">
|
||||
<select data-width="100%" id="quarantine_release_format" name="release_format" class="selectpicker" title="{{ lang.tfa.select }}">
|
||||
<option {% if q_data.release_format == 'raw' %}selected{% endif %} value="raw">{{ lang.admin.quarantine_release_format_raw }}</option>
|
||||
<option {% if q_data.release_format == 'attachment' %}selected{% endif %} value="attachment">{{ lang.admin.quarantine_release_format_att }}</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-4">
|
||||
<label class="col-sm-4 control-label text-sm-end" for="exclude_domains">{{ lang.admin.quarantine_exclude_domains }}:</label>
|
||||
<div class="col-sm-8 col-md-6 col-lg-4 col-xl-3">
|
||||
<select data-width="100%" name="exclude_domains" class="selectpicker" title="{{ lang.tfa.select }}" multiple>
|
||||
{% for domain in all_domains %}
|
||||
<option {% if domain in q_data.exclude_domains %}selected{% endif %}>{{ domain }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<hr>
|
||||
<legend data-bs-target="#quarantine_template" style="cursor:pointer" unselectable="on" data-bs-toggle="collapse">
|
||||
<i style="font-size:10pt;" class="bi bi-plus-square"></i> {{ lang.admin.quarantine_notification_html|raw }}
|
||||
</legend>
|
||||
<hr />
|
||||
<div id="quarantine_template" class="collapse" >
|
||||
<textarea autocorrect="off" spellcheck="false" autocapitalize="none" class="form-control textarea-code" rows="40" name="html_tmpl">{{ q_data.html_tmpl|raw }}</textarea>
|
||||
</div>
|
||||
<button class="btn btn-sm d-block d-sm-inline btn-success" data-action="edit_selected" data-item="self" data-id="quarantine" data-api-url='edit/quarantine' data-api-attr='{"action":"settings"}' href="#"><i class="bi bi-check-lg"></i> {{ lang.admin.save }}</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
53
data/web/templates/admin/tab-config-quota.twig
Executable file
53
data/web/templates/admin/tab-config-quota.twig
Executable file
|
|
@ -0,0 +1,53 @@
|
|||
<div class="tab-pane fade" id="tab-config-quota" role="tabpanel" aria-labelledby="tab-config-quota">
|
||||
<div class="card mb-4">
|
||||
<div class="card-header d-flex fs-5">
|
||||
<button class="btn d-md-none flex-grow-1 text-start" data-bs-target="#collapse-tab-config-quota" data-bs-toggle="collapse" aria-controls="collapse-tab-config-quota">
|
||||
{{ lang.admin.quota_notifications }}
|
||||
</button>
|
||||
<span class="d-none d-md-block">{{ lang.admin.quota_notifications }}</span>
|
||||
</div>
|
||||
<div id="collapse-tab-config-quota" class="card-body collapse" data-bs-parent="#admin-content">
|
||||
<p>{{ lang.admin.quota_notifications_info }}</p>
|
||||
<form class="form" role="form" data-id="quota_notification" method="post">
|
||||
<div class="row mb-4">
|
||||
<div class="col-sm-6">
|
||||
<div>
|
||||
<label for="quota_notification_sender">{{ lang.admin.quota_notification_sender }}:</label>
|
||||
<input type="email" class="form-control" id="quota_notification_sender" name="sender" value="{{ qn_data.sender }}" placeholder="quota-warning@localhost">
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-6">
|
||||
<div>
|
||||
<label for="quota_notification_subject">{{ lang.admin.quota_notification_subject }}:</label>
|
||||
<input type="text" class="form-control" id="quota_notification_subject" name="subject" value="{{ qn_data.subject }}" placeholder="Quota warning">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-sm-12">
|
||||
<legend data-bs-target="#quota_template" style="cursor:pointer" unselectable="on" data-bs-toggle="collapse">
|
||||
<i style="font-size:10pt;" class="bi bi-plus-square"></i> {{ lang.admin.quarantine_notification_html|raw }}
|
||||
</legend>
|
||||
<hr />
|
||||
<div id="quota_template" class="collapse">
|
||||
<!-- <small>{{ lang.admin.quota_notifications_vars }}</small><br><br>-->
|
||||
<textarea autocorrect="off" spellcheck="false" autocapitalize="none" class="form-control textarea-code" rows="20" name="html_tmpl">{{ qn_data.html_tmpl|raw }}</textarea>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-sm-10">
|
||||
<div>
|
||||
<br>
|
||||
<a type="button" class="btn btn-sm d-block d-sm-inline btn-success" data-action="edit_selected"
|
||||
data-item="quota_notification"
|
||||
data-id="quota_notification"
|
||||
data-api-url='edit/quota_notification'
|
||||
data-api-attr='{}'><i class="bi bi-check-lg"></i> {{ lang.user.save_changes }}</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
77
data/web/templates/admin/tab-config-rsettings.twig
Executable file
77
data/web/templates/admin/tab-config-rsettings.twig
Executable file
|
|
@ -0,0 +1,77 @@
|
|||
<div class="tab-pane fade" id="tab-config-rsettings" role="tabpanel" aria-labelledby="tab-config-rsettings">
|
||||
<div class="card mb-4">
|
||||
<div class="card-header d-flex fs-5">
|
||||
<button class="btn d-md-none flex-grow-1 text-start" data-bs-target="#collapse-tab-config-rsettings" data-bs-toggle="collapse" aria-controls="collapse-tab-config-rsettings">
|
||||
{{ lang.admin.rspamd_settings_map }}
|
||||
</button>
|
||||
<span class="d-none d-md-block">{{ lang.admin.rspamd_settings_map }}</span>
|
||||
</div>
|
||||
<div id="collapse-tab-config-rsettings" class="card-body collapse" data-bs-parent="#admin-content">
|
||||
<legend data-bs-target="#active_settings_map" style="cursor:pointer" unselectable="on" data-bs-toggle="collapse">
|
||||
<i style="font-size:10pt;" class="bi bi-plus-square"></i> {{ lang.admin.active_rspamd_settings_map }}
|
||||
</legend>
|
||||
<hr />
|
||||
<div id="active_settings_map" class="collapse" >
|
||||
<textarea autocorrect="off" spellcheck="false" autocapitalize="none" class="form-control textarea-code" rows="20" name="settings_map" readonly>{{ rsettings_map }}</textarea>
|
||||
</div>
|
||||
<br>
|
||||
<form class="form" data-id="rsettings" role="form" method="post">
|
||||
<div class="row">
|
||||
<div class="col-sm-3">
|
||||
<div class="list-group">
|
||||
{% if not rsettings %}
|
||||
|
||||
{% endif %}
|
||||
{% for rsetting in rsettings %}
|
||||
<a href="#" class="list-group-item list-group-item-{% if rsetting.details.active %}success{% endif %}" data-dont-remember="1" data-bs-target="#settings_tab{{ rsetting.details.id }}" data-bs-toggle="tab">{{ rsetting.details.desc }} (ID #{{ rsetting.id }})</a>
|
||||
{% else %}
|
||||
<span class="list-group-item"><em>{{ lang.admin.rsetting_none }}</em></span>
|
||||
{% endfor %}
|
||||
<a href="#" class="list-group-item list-group-item-default"
|
||||
data-bs-toggle="modal"
|
||||
data-dont-remember="1"
|
||||
data-bs-target="#addRsettingModal">{{ lang.admin.rsetting_add_rule }}</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-9">
|
||||
<div class="tab-content">
|
||||
{% if not rsettings %}
|
||||
<div id="none" class="tab-pane active">
|
||||
<p class="text-muted">{{ lang.admin.rsetting_none }}</p>
|
||||
</div>
|
||||
{% else %}
|
||||
<div id="none" class="tab-pane active">
|
||||
<p class="text-muted">{{ lang.admin.rsetting_no_selection }}</p>
|
||||
</div>
|
||||
{% for rsetting in rsettings %}
|
||||
<div id="settings_tab{{ rsetting.details.id }}" class="tab-pane rsettings">
|
||||
<form class="form" data-id="rsettings" role="form" method="post">
|
||||
<input type="hidden" name="active" value="0">
|
||||
<div>
|
||||
<label for="rsettings_desc">{{ lang.admin.rsetting_desc }}:</label>
|
||||
<input type="text" class="form-control" id="rsettings_desc" name="desc" value="{{ rsetting.details.desc }}">
|
||||
</div>
|
||||
<div class="mt-4">
|
||||
<label for="rsettings_content">{{ lang.admin.rsetting_content }}:</label>
|
||||
<textarea class="form-control" id="rsettings_content" name="content" rows="10">{{ rsetting.details.content }}</textarea>
|
||||
</div>
|
||||
<div class="mt-4 mb-2">
|
||||
<label>
|
||||
<input type="checkbox" class="form-check-input" name="active" value="1" {% if rsetting.details.active %}checked{% endif %}> {{ lang.admin.active }}
|
||||
</label>
|
||||
</div>
|
||||
<div class="btn-group">
|
||||
<button class="btn btn-sm btn-xs-lg btn-success" data-action="edit_selected" data-item="{{ rsetting.details.id }}" data-id="rsettings" data-api-url='edit/rsetting' data-api-attr='{}' href="#"><i class="bi bi-check-lg"></i> {{ lang.admin.save }}</button>
|
||||
<button class="btn btn-sm btn-xs-lg btn-danger" data-action="delete_selected" data-item="{{ rsetting.details.id }}" data-id="rsettings" data-api-url="delete/rsetting" data-api-attr='{}' href="#">{{ lang.admin.remove }}</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
48
data/web/templates/admin/tab-config-rspamd.twig
Executable file
48
data/web/templates/admin/tab-config-rspamd.twig
Executable file
|
|
@ -0,0 +1,48 @@
|
|||
<div class="tab-pane fade" id="tab-config-rspamd" role="tabpanel" aria-labelledby="tab-config-rspamd">
|
||||
<div class="card mb-4">
|
||||
<div class="card-header d-flex fs-5">
|
||||
<button class="btn d-md-none flex-grow-1 text-start" data-bs-target="#collapse-tab-config-rspamd" data-bs-toggle="collapse" aria-controls="collapse-tab-config-rspamd">
|
||||
Rspamd UI
|
||||
</button>
|
||||
<span class="d-none d-md-block">Rspamd UI</span>
|
||||
</div>
|
||||
<div id="collapse-tab-config-rspamd" class="card-body collapse" data-bs-parent="#admin-content">
|
||||
<div class="row">
|
||||
<div class="col-12 d-flex d-sm-none mb-4">
|
||||
<img id="rspamd_logo_sm" class="img-responsive mx-auto" src="/img/rspamd_logo_dark.png" alt="Rspamd UI">
|
||||
</div>
|
||||
<div class="col-sm-9 col-12">
|
||||
<form class="form-horizontal" autocapitalize="none" data-id="admin" autocorrect="off" role="form" method="post">
|
||||
<div class="row mb-4">
|
||||
<div class="offset-sm-3 col-sm-9">
|
||||
<label>
|
||||
<a href="/rspamd/" target="_blank"><i class="bi bi-window"></i> Rspamd UI</a>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-2">
|
||||
<label class="control-label col-sm-3 text-sm-end" for="rspamd_ui_pass">{{ lang.admin.password }}:</label>
|
||||
<div class="col-sm-9">
|
||||
<input type="password" class="form-control" id="rspamd_ui_pass" name="rspamd_ui_pass" autocomplete="new-password" required>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-4">
|
||||
<label class="control-label col-sm-3 text-sm-end" for="rspamd_ui_pass2">{{ lang.admin.password_repeat }}:</label>
|
||||
<div class="col-sm-9">
|
||||
<input type="password" class="form-control" id="rspamd_ui_pass2" name="rspamd_ui_pass2" autocomplete="new-password" required>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-4">
|
||||
<div class="offset-sm-3 col-sm-9">
|
||||
<button type="submit" class="btn btn-sm d-block d-sm-inline btn-success" id="rspamd_ui" name="rspamd_ui" href="#"><i class="bi bi-check-lg"></i> {{ lang.admin.save }}</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div class="col-sm-3 d-none d-sm-block">
|
||||
<img id="rspamd_logo" class="img-responsive" src="/img/rspamd_logo_dark.png" alt="Rspamd UI">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
53
data/web/templates/admin/tab-globalfilter-regex.twig
Executable file
53
data/web/templates/admin/tab-globalfilter-regex.twig
Executable file
|
|
@ -0,0 +1,53 @@
|
|||
<div class="tab-pane fade" id="tab-globalfilter-regex" role="tabpanel" aria-labelledby="tab-globalfilter-regex">
|
||||
<div class="card mb-4">
|
||||
<div class="card-header d-flex fs-5">
|
||||
<button class="btn d-md-none flex-grow-1 text-start" data-bs-target="#collapse-tab-config-regex" data-bs-toggle="collapse" aria-controls="collapse-tab-config-regex">
|
||||
{{ lang.admin.rspamd_global_filters }}
|
||||
</button>
|
||||
<span class="d-none d-md-block">{{ lang.admin.rspamd_global_filters }}</span>
|
||||
</div>
|
||||
<div id="collapse-tab-config-regex" class="card-body collapse" data-bs-parent="#admin-content">
|
||||
<p>{{ lang.admin.rspamd_global_filters_info }}</p>
|
||||
<div id="confirm_show_rspamd_global_filters"{% if show_rspamd_global_filters %} class="d-none"{% endif %}>
|
||||
<div class="row">
|
||||
<div class="offset-sm-2 col-sm-10">
|
||||
<label>
|
||||
<input type="checkbox" class="form-check-input" id="show_rspamd_global_filters"> {{ lang.admin.rspamd_global_filters_agree }}
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="rspamd_global_filters"{% if show_rspamd_global_filters != true %} class="d-none"{% endif %}>
|
||||
<hr>
|
||||
<span class="anchor" id="regexmaps"></span>
|
||||
<h4>{{ lang.admin.regex_maps }}</h4>
|
||||
<p>{{ lang.admin.rspamd_global_filters_regex|raw }}</p>
|
||||
<ul>
|
||||
{% for rspamd_regex_desc, rspamd_regex_map in rspamd_regex_maps %}
|
||||
<li><a href="#{{ rspamd_regex_map.map }}">{{ rspamd_regex_desc }}</a> (<small>{{ rspamd_regex_map.map }}</small>)</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% for rspamd_regex_desc, rspamd_regex_map in rspamd_regex_maps %}
|
||||
<hr>
|
||||
<span class="anchor" id="{{ rspamd_regex_map.map }}"></span>
|
||||
<form class="form-horizontal" data-cached-form="false" data-id="{{ rspamd_regex_map.map }}" role="form" method="post">
|
||||
<div class="row">
|
||||
<label class="control-label col-sm-3" for="{{ rspamd_regex_map.map }}">{{ rspamd_regex_desc }}<br><small>{{ rspamd_regex_map.map }}</small></label>
|
||||
<div class="col-sm-9">
|
||||
<textarea id="{{ rspamd_regex_map.map }}" spellcheck="false" autocorrect="off" autocapitalize="none" class="form-control textarea-code" rows="10" name="rspamd_map_data" required>{{ rspamd_regex_map.data }}</textarea>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="offset-sm-3 col-sm-9">
|
||||
<div class="btn-group mt-2">
|
||||
<button class="btn btn-sm btn-xs-half d-block d-sm-inline btn-secondary validate_rspamd_regex" data-regex-map="{{ rspamd_regex_map.map }}" href="#">{{ lang.add.validate }}</button>
|
||||
<button class="btn btn-sm btn-xs-half d-block d-sm-inline btn-success submit_rspamd_regex" data-action="edit_selected" data-id="{{ rspamd_regex_map.map }}" data-item="{{ rspamd_regex_map.map }}" data-api-url='edit/rspamd-map' data-api-attr='{}' href="#" disabled>{{ lang.edit.save }}</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
12
data/web/templates/admin/tab-ldap.twig
Executable file
12
data/web/templates/admin/tab-ldap.twig
Executable file
|
|
@ -0,0 +1,12 @@
|
|||
<div class="tab-pane fade" id="tab-config-ldap-admins" role="tabpanel" aria-labelledby="tab-config-ldap-admins">
|
||||
<div class="card mb-4">
|
||||
<div class="card-header d-flex fs-5">
|
||||
<button class="btn d-md-none flex-grow-1 text-start" data-bs-target="#collapse-tab-config-ldap-admins" data-bs-toggle="collapse" aria-controls="collapse-tab-config-ldap-admins">
|
||||
{{ lang.admin.admins_ldap }}
|
||||
</button>
|
||||
<span class="d-none d-md-block">{{ lang.admin.admins_ldap }}</span>
|
||||
</div>
|
||||
<div id="collapse-tab-config-ldap-admins" class="card-body collapse" data-bs-parent="#admin-content">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
108
data/web/templates/admin/tab-routing.twig
Executable file
108
data/web/templates/admin/tab-routing.twig
Executable file
|
|
@ -0,0 +1,108 @@
|
|||
<div class="tab-pane fade" id="tab-routing" role="tabpanel" aria-labelledby="tab-routing">
|
||||
<div class="card mb-4">
|
||||
<div class="card-header d-flex fs-5">
|
||||
<button class="btn d-md-none flex-grow-1 text-start" data-bs-target="#collapse-tab-routing" data-bs-toggle="collapse" aria-controls="collapse-tab-routing">
|
||||
{{ lang.admin.relayhosts }}
|
||||
</button>
|
||||
<span class="d-none d-md-block">{{ lang.admin.relayhosts }}</span>
|
||||
</div>
|
||||
<div id="collapse-tab-routing" class="card-body collapse" data-bs-parent="#admin-content">
|
||||
<p class="mb-4">{{ lang.admin.relayhosts_hint|raw }}</p>
|
||||
<table id="relayhoststable" class="table table-striped dt-responsive w-100"></table>
|
||||
<div class="mass-actions-admin mb-4">
|
||||
<div class="btn-group btn-group-sm">
|
||||
<button type="button" id="toggle_multi_select_all" data-id="rlyhosts" class="btn btn-sm btn-xs-half d-block d-sm-inline btn-secondary">{{ lang.mailbox.toggle_all }}</button>
|
||||
<a class="btn btn-sm btn-xs-half d-block d-sm-inline btn-secondary dropdown-toggle" data-bs-toggle="dropdown" href="#">{{ lang.mailbox.quick_actions }}</a>
|
||||
<ul class="dropdown-menu top100">
|
||||
<li><a class="dropdown-item" data-action="edit_selected" data-id="rlyhosts" data-api-url='edit/relayhost' data-api-attr='{"active":"1"}' href="#">{{ lang.mailbox.activate }}</a></li>
|
||||
<li><a class="dropdown-item" data-action="edit_selected" data-id="rlyhosts" data-api-url='edit/relayhost' data-api-attr='{"active":"0"}' href="#">{{ lang.mailbox.deactivate }}</a></li>
|
||||
<li><hr class="dropdown-divider"></li>
|
||||
<li><a class="dropdown-item" data-action="delete_selected" data-id="rlyhosts" data-api-url='delete/relayhost' href="#">{{ lang.admin.remove }}</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<legend>{{ lang.admin.add_relayhost }}</legend><hr />
|
||||
<p class="text-muted">{{ lang.admin.add_relayhost_hint|raw }}</p>
|
||||
<div class="row">
|
||||
<div class="col-md-8">
|
||||
<form class="form" data-id="rlyhost" role="form" method="post">
|
||||
<div class="mb-2">
|
||||
<label for="rlyhost_hostname">{{ lang.admin.host }}</label>
|
||||
<input class="form-control" id="rlyhost_hostname" name="hostname" placeholder='[0.0.0.0], [0.0.0.0]:25, host:25, host, [host]:25' required>
|
||||
</div>
|
||||
<div class="mb-2">
|
||||
<label for="rlyhost_username">{{ lang.admin.username }}</label>
|
||||
<input class="form-control" id="rlyhost_username" name="username">
|
||||
</div>
|
||||
<div class="mb-4">
|
||||
<label for="rlyhost_password">{{ lang.admin.password }}</label>
|
||||
<input class="form-control" id="rlyhost_password" name="password" type="password">
|
||||
</div>
|
||||
<button class="btn btn-sm d-block d-sm-inline btn-success" data-action="add_item" data-id="rlyhost" data-api-url='add/relayhost' data-api-attr='{}' href="#"><i class="bi bi-plus-lg"></i> {{ lang.admin.add }}</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card mb-4">
|
||||
<div class="card-header d-flex">
|
||||
<button class="btn d-md-none flex-grow-1 text-start" data-bs-target="#collapse-tab-maps" data-bs-toggle="collapse" aria-controls="collapse-tab-maps">
|
||||
{{ lang.admin.transport_maps }}
|
||||
</button>
|
||||
<span class="d-none d-md-block">{{ lang.admin.transport_maps }}</span>
|
||||
</div>
|
||||
<div id="collapse-tab-maps" class="card-body collapse" data-bs-parent="#admin-content">
|
||||
<p style="margin-bottom:40px">{{ lang.admin.transports_hint|raw }}</p>
|
||||
<table id="transportstable" class="table table-striped dt-responsive w-100"></table>
|
||||
<div class="mass-actions-admin mb-4">
|
||||
<div class="btn-group btn-group-sm">
|
||||
<button type="button" id="toggle_multi_select_all" data-id="transports" class="btn btn-sm btn-xs-half d-block d-sm-inline btn-secondary">{{ lang.mailbox.toggle_all }}</button>
|
||||
<a class="btn btn-sm btn-xs-half d-block d-sm-inline btn-secondary dropdown-toggle" data-bs-toggle="dropdown" href="#">{{ lang.mailbox.quick_actions }}</a>
|
||||
<ul class="dropdown-menu top100">
|
||||
<li><a class="dropdown-item" data-action="edit_selected" data-id="transports" data-api-url='edit/transport' data-api-attr='{"active":"1"}' href="#">{{ lang.mailbox.activate }}</a></li>
|
||||
<li><a class="dropdown-item" data-action="edit_selected" data-id="transports" data-api-url='edit/transport' data-api-attr='{"active":"0"}' href="#">{{ lang.mailbox.deactivate }}</a></li>
|
||||
<li><hr class="dropdown-divider"></li>
|
||||
<li><a class="dropdown-item" data-action="delete_selected" data-id="transports" data-api-url='delete/transport' href="#">{{ lang.admin.remove }}</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<legend>{{ lang.admin.add_transport }}</legend><hr />
|
||||
<p class="text-muted">{{ lang.admin.add_transports_hint|raw }}</p>
|
||||
<div class="row">
|
||||
<div class="col-md-8">
|
||||
<form class="form" data-id="transport" role="form" method="post">
|
||||
<div class="mb-2">
|
||||
<label for="transport_destination">{{ lang.admin.destination }}</label>
|
||||
<input class="form-control" id="transport_destination" name="destination" placeholder='{{ lang.admin.transport_dest_format }}' required>
|
||||
</div>
|
||||
<div class="mb-2">
|
||||
<label for="transport_nexthop">{{ lang.admin.nexthop }}</label>
|
||||
<input class="form-control" id="transport_nexthop" name="nexthop" placeholder='host:25, host, [host]:25, [0.0.0.0]:25' required>
|
||||
</div>
|
||||
<div class="mb-2">
|
||||
<label for="transport_username">{{ lang.admin.username }}</label>
|
||||
<input class="form-control" id="transport_username" name="username">
|
||||
</div>
|
||||
<div class="mb-4">
|
||||
<label for="transport_password">{{ lang.admin.password }}</label>
|
||||
<input class="form-control" id="transport_password" name="password" type="password">
|
||||
</div>
|
||||
<div class="mb-2">
|
||||
<label>
|
||||
<input type="checkbox" class="form-check-input" name="is_mx_based" value="1"> {{ lang.admin.lookup_mx|raw }}
|
||||
</label>
|
||||
</div>
|
||||
<div class="mb-4">
|
||||
<label>
|
||||
<input type="checkbox" class="form-check-input" name="active" value="1"> {{ lang.admin.active }}
|
||||
</label>
|
||||
</div>
|
||||
<p class="text-muted">{{ lang.admin.credentials_transport_warning|raw }}</p>
|
||||
<button class="btn btn-sm d-block d-sm-inline btn-success" data-action="add_item" data-id="transport" data-api-url='add/transport' data-api-attr='{}' href="#"><i class="bi bi-plus-lg"></i> {{ lang.admin.add }}</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
75
data/web/templates/admin/tab-sys-mails.twig
Executable file
75
data/web/templates/admin/tab-sys-mails.twig
Executable file
|
|
@ -0,0 +1,75 @@
|
|||
<div class="tab-pane fade" id="tab-sys-mails" role="tabpanel" aria-labelledby="tab-sys-mails">
|
||||
<div class="card mb-4">
|
||||
<div class="card-header d-flex fs-5">
|
||||
<button class="btn d-md-none flex-grow-1 text-start" data-bs-target="#collapse-tab-sys-mails" data-bs-toggle="collapse" aria-controls="collapse-tab-sys-mails">
|
||||
{{ lang.admin.sys_mails }}
|
||||
</button>
|
||||
<span class="d-none d-md-block">{{ lang.admin.sys_mails }}</span>
|
||||
</div>
|
||||
<div id="collapse-tab-sys-mails" class="card-body collapse" data-bs-parent="#admin-content">
|
||||
<form class="form-horizontal" autocapitalize="none" data-id="admin" autocorrect="off" role="form" method="post">
|
||||
<div class="row mb-2">
|
||||
<label class="control-label col-sm-2 text-sm-end" for="admin_mass_from">{{ lang.admin.from }}:</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="email" class="form-control" id="admin_mass_from" name="mass_from" value="noreply@{{ mailcow_hostname }}" required>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-4">
|
||||
<label class="control-label col-sm-2 text-sm-end" for="admin_mass_subject">{{ lang.admin.subject }}:</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="text" class="form-control" id="admin_mass_subject" name="mass_subject" required>
|
||||
</div>
|
||||
</div>
|
||||
{% for domain in all_domains %}
|
||||
|
||||
{% endfor %}
|
||||
<div class="row mb-4">
|
||||
<label class="control-label col-sm-2 text-sm-end" for="mass_subject">{{ lang.admin.include_exclude }}:
|
||||
<p class="text-muted">{{ lang.admin.include_exclude_info|raw }}</p>
|
||||
</label>
|
||||
<div class="col-sm-5">
|
||||
<label class="d-block" for="mass_exclude">{{ lang.admin.excludes }}:</label>
|
||||
<select id="mass_exclude" name="mass_exclude[]" data-live-search="true" data-width="100%" size="30" multiple>
|
||||
{% for mailbox in mailboxes %}
|
||||
<option>{{ mailbox }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-sm-5">
|
||||
<label class="d-block" for="mass_include">{{ lang.admin.includes }}:</label>
|
||||
<select id="mass_include" name="mass_include[]" data-live-search="true" data-width="100%" size="30" multiple>
|
||||
{% for mailbox in mailboxes %}
|
||||
<option>{{ mailbox }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-2">
|
||||
<label class="control-label col-sm-2 text-sm-end" for="mass_text">{{ lang.admin.text }}:</label>
|
||||
<div class="col-sm-10">
|
||||
<textarea class="form-control" rows="10" name="mass_text" id="mass_text" required></textarea>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-4">
|
||||
<label class="control-label col-sm-2 text-sm-end" for="mass_html">{{ lang.admin.html }} ({{ lang.admin.optional }}):</label>
|
||||
<div class="col-sm-10">
|
||||
<textarea class="form-control" rows="10" name="mass_html" id="mass_html"></textarea>
|
||||
<p class="small"><i class="bi bi-arrow-return-right"></i> <a target="_blank" href="https://templates.mailchimp.com/resources/html-to-text/">{{ lang.admin.convert_html_to_text }}</a></p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-2">
|
||||
<div class="offset-sm-2 col-sm-10">
|
||||
<label>
|
||||
<input type="checkbox" class="form-check-input" id="mass_disarm"> {{ lang.admin.activate_send }}
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-2">
|
||||
<div class="offset-sm-2 col-sm-10">
|
||||
<button class="btn btn-sm d-block d-sm-inline btn-success" type="submit" id="mass_send" name="mass_send" disabled><i class="bi bi-envelope-fill"></i> {{ lang.admin.send }}</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
554
data/web/templates/base.twig
Executable file
554
data/web/templates/base.twig
Executable file
|
|
@ -0,0 +1,554 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="{{ mailcow_locale|default('en') }}">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=0">
|
||||
<meta name="theme-color" content="#F5D76E"/>
|
||||
<meta http-equiv="Referrer-Policy" content="same-origin">
|
||||
<title>{{ ui_texts.title_name|raw }}</title>
|
||||
|
||||
<link rel="stylesheet" href="{{ css_path }}">
|
||||
<script>
|
||||
// check if darkmode is preferred by OS or set by localStorage
|
||||
if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches && localStorage.getItem("theme") !== "light" ||
|
||||
localStorage.getItem("theme") === "dark") {
|
||||
var head = document.getElementsByTagName('head')[0];
|
||||
var link = document.createElement('link');
|
||||
link.id = 'dark-mode-theme';
|
||||
link.rel = 'stylesheet';
|
||||
link.type = 'text/css';
|
||||
link.href = '/css/themes/mailcow-darkmode.css';
|
||||
head.appendChild(link);
|
||||
}
|
||||
</script>
|
||||
|
||||
<link rel="shortcut icon" href="/favicon.png" type="image/png">
|
||||
<link rel="icon" href="/favicon.png" type="image/png">
|
||||
</head>
|
||||
<body>
|
||||
<div class="overlay"></div>
|
||||
{% block navbar %}
|
||||
<nav class="navbar navbar-expand-lg navbar-light bg-light navbar-fixed-top p-0">
|
||||
<div class="container-fluid">
|
||||
<a class="navbar-brand" href="/">
|
||||
<img class="main-logo" alt="mailcow-logo" src="{{ logo|default('/img/cow_mailcow.svg') }}">
|
||||
<img class="main-logo-dark" alt="mailcow-logo-dark" src="{{ logo_dark|default('/img/cow_mailcow.svg') }}">
|
||||
</a>
|
||||
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbar" aria-controls="navbar" aria-expanded="false" aria-label="Toggle navigation">
|
||||
<i class="bi bi-list fs-3"></i>
|
||||
</button>
|
||||
<div id="navbar" class="navbar-collapse collapse">
|
||||
<ul class="navbar-nav ms-auto">
|
||||
<li class="nav-item">
|
||||
<div class="nav-link form-check form-switch my-auto d-flex align-items-center">
|
||||
<label class="form-check-label"><i class="bi bi-moon-fill"></i></label>
|
||||
<input class="form-check-input ms-2" type="checkbox" id="dark-mode-toggle">
|
||||
</div>
|
||||
</li>
|
||||
{% if mailcow_locale %}
|
||||
<li class="nav-item dropdown{% if available_languages|length == 1 %}lang-link-disabled{% endif %}">
|
||||
<a href="#" class="nav-link dropdown-toggle" data-bs-toggle="dropdown" role="button" aria-expanded="false"><span class="flag-icon flag-icon-{{ mailcow_locale[-2:] }}"></span></a>
|
||||
<ul class="dropdown-menu" role="menu "aria-labelledby="languageDropdown">
|
||||
{% for key, val in available_languages %}
|
||||
<li>
|
||||
<a class="dropdown-item {% if mailcow_locale == key %}active{% endif %}" href="?{{ query_string({'lang': key}) }}">
|
||||
<span class="flag-icon flag-icon-{{ key[-2:] }}"></span>{{ val }}
|
||||
</a>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</li>
|
||||
{% endif %}
|
||||
{% if mailcow_cc_role %}
|
||||
<li class="nav-item dropdown">
|
||||
<a href="#" class="nav-link dropdown-toggle" data-bs-toggle="dropdown" role="button" aria-expanded="false">{{ lang.header.mailcow_system }}</a>
|
||||
<ul class="dropdown-menu">
|
||||
{% if mailcow_cc_role == 'admin' %}
|
||||
<li><a href="/debug" class="dropdown-item {% if is_uri('debug') %}active{% endif %}">{{ lang.header.debug }}</a></li>
|
||||
<li><a href="/admin" class="dropdown-item {% if is_uri('admin') %}active{% endif %}">{{ lang.header.mailcow_config }}</a></li>
|
||||
{% endif %}
|
||||
{% if mailcow_cc_role != 'admin' %}
|
||||
<li><a href="/user" class="dropdown-item {% if is_uri('user') %}active{% endif %}">{{ lang.header.user_settings }}</a></li>
|
||||
{% endif %}
|
||||
</ul>
|
||||
</li>
|
||||
<li class="nav-item dropdown">
|
||||
<a href="#" class="nav-link dropdown-toggle" data-bs-toggle="dropdown" role="button" aria-expanded="false">{{ lang.header.email }}</a>
|
||||
<ul class="dropdown-menu">
|
||||
{% if mailcow_cc_role == 'admin' or mailcow_cc_role == 'domainadmin' %}
|
||||
<li><a href="/mailbox" class="dropdown-item {% if is_uri('mailbox') %}active{% endif %}">{{ lang.header.mailcow_config }}</a></li>
|
||||
{% endif %}
|
||||
<li><a href="/quarantine" class="dropdown-item {% if is_uri('quarantine') %}active{% endif %}">{{ lang.header.quarantine }}</a></li>
|
||||
{% if mailcow_cc_role == 'admin' %}
|
||||
<li><a href="/queue" class="dropdown-item {% if is_uri('queue') %}active{% endif %}">{{ lang.queue.queue_manager }}</a></li>
|
||||
{% endif %}
|
||||
{% if mailcow_cc_role == 'admin' %}
|
||||
<li><a href="#" class="dropdown-item" data-bs-toggle="modal" data-container="sogo-mailcow" data-bs-target="#RestartContainer">{{ lang.header.restart_sogo }}</a></li>
|
||||
{% endif %}
|
||||
</ul>
|
||||
</li>
|
||||
{% endif %}
|
||||
{% if mailcow_apps or app_links %}
|
||||
<li class="nav-item dropdown">
|
||||
<a href="#" class="nav-link dropdown-toggle" data-bs-toggle="dropdown" role="button" aria-expanded="false"><i class="bi bi-link-45deg me-2"></i> {{ ui_texts.apps_name|raw }}</a>
|
||||
<ul class="dropdown-menu">
|
||||
{% for app in mailcow_apps %}
|
||||
{% if not skip_sogo or not is_uri('SOGo', app.link) %}
|
||||
<li {% if app.description %}title="{{ app.description }}"{% endif %}>
|
||||
<a href="{{ app.link }}" class="dropdown-item">{{ app.name }}</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% for row in app_links %}
|
||||
{% for key, val in row %}
|
||||
<li><a href="{{ val }}" class="dropdown-item">{{ key }}</a></li>
|
||||
{% endfor %}
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</li>
|
||||
{% endif %}
|
||||
{% if not dual_login and mailcow_cc_username %}
|
||||
<li class="logged-in-as nav-item"><a href="#" onclick="logout.submit()" class="nav-link"><b class="username-lia">{{ mailcow_cc_username }}</b> <i class="bi bi-power ms-2"></i></a></li>
|
||||
{% elseif dual_login %}
|
||||
<li class="logged-in-as nav-item"><a href="#" onclick="logout.submit()" class="nav-link"><b class="username-lia">{{ mailcow_cc_username }} <span class="text-info">({{ dual_login.username }})</span> </b><i class="bi bi-power ms-2"></i></a></li>
|
||||
{% endif %}
|
||||
{% if not is_master %}
|
||||
<div class="nav-link form-check form-switch my-auto d-flex align-items-center">
|
||||
<li class="slave-info">[ slave ]</li>
|
||||
</div>
|
||||
{% endif %}
|
||||
</ul>
|
||||
</div><!--/.nav-collapse -->
|
||||
</div><!--/.container-fluid -->
|
||||
</nav>
|
||||
{% endblock navbar %}
|
||||
|
||||
<form action="/" method="post" id="logout"><input type="hidden" name="logout"></form>
|
||||
|
||||
{% if ui_texts.ui_announcement_text and ui_texts.ui_announcement_active and not is_root_uri %}
|
||||
<div class="container mt-4">
|
||||
<div class="alert alert-{{ ui_texts.ui_announcement_type }}">{{ ui_texts.ui_announcement_text }}</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<div class="container my-4">
|
||||
{% block content %}{% endblock %}
|
||||
</div>
|
||||
|
||||
{% include 'modals/footer.twig' %}
|
||||
|
||||
<script src="{{ js_path }}"></script>
|
||||
<script>
|
||||
var lang_footer = {{ lang_footer|raw }};
|
||||
var lang_acl = {{ lang_acl|raw }};
|
||||
var lang_tfa = {{ lang_tfa|raw }};
|
||||
var lang_fido2 = {{ lang_fido2|raw }};
|
||||
var docker_timeout = {{ docker_timeout|raw }} * 1000;
|
||||
var mailcow_cc_role = '{{ mailcow_cc_role }}';
|
||||
var mailcow_info = {
|
||||
version_tag: '{{ mailcow_info.version_tag }}',
|
||||
last_version_tag: '{{ mailcow_info.last_version_tag }}',
|
||||
updatedAt: '{{ mailcow_info.updated_at }}',
|
||||
project_url: '{{ mailcow_info.git_project_url }}',
|
||||
project_owner: '{{ mailcow_info.git_owner }}',
|
||||
project_repo: '{{ mailcow_info.git_repo }}',
|
||||
branch: '{{ mailcow_info.mailcow_branch }}'
|
||||
};
|
||||
|
||||
$(window).scroll(function() {
|
||||
sessionStorage.scrollTop = $(this).scrollTop();
|
||||
});
|
||||
// Select language and reopen active URL without POST
|
||||
function setLang(sel) {
|
||||
$.post( '{{ uri }}', {lang: sel} );
|
||||
window.location.href = window.location.pathname + window.location.search;
|
||||
}
|
||||
// FIDO2 functions
|
||||
function arrayBufferToBase64(buffer) {
|
||||
let binary = '';
|
||||
let bytes = new Uint8Array(buffer);
|
||||
let len = bytes.byteLength;
|
||||
for (let i = 0; i < len; i++) {
|
||||
binary += String.fromCharCode( bytes[ i ] );
|
||||
}
|
||||
return window.btoa(binary);
|
||||
}
|
||||
function recursiveBase64StrToArrayBuffer(obj) {
|
||||
let prefix = '=?BINARY?B?';
|
||||
let suffix = '?=';
|
||||
if (typeof obj === 'object') {
|
||||
for (let key in obj) {
|
||||
if (typeof obj[key] === 'string') {
|
||||
let str = obj[key];
|
||||
if (str.substring(0, prefix.length) === prefix && str.substring(str.length - suffix.length) === suffix) {
|
||||
str = str.substring(prefix.length, str.length - suffix.length);
|
||||
let binary_string = window.atob(str);
|
||||
let len = binary_string.length;
|
||||
let bytes = new Uint8Array(len);
|
||||
for (let i = 0; i < len; i++) {
|
||||
bytes[i] = binary_string.charCodeAt(i);
|
||||
}
|
||||
obj[key] = bytes.buffer;
|
||||
}
|
||||
} else {
|
||||
recursiveBase64StrToArrayBuffer(obj[key]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
$(window).on('load', function() {
|
||||
$(".overlay").hide();
|
||||
});
|
||||
$(document).ready(function() {
|
||||
$(document).on('shown.bs.modal', function(e) {
|
||||
modal_id = $(e.relatedTarget).data('target');
|
||||
$(modal_id).attr("aria-hidden","false");
|
||||
});
|
||||
// TFA, CSRF, Alerts in footer.inc.php
|
||||
// Other general functions in mailcow.js
|
||||
{% for alert_type, alert_msg in alerts %}
|
||||
mailcow_alert_box('{{ alert_msg|raw|e("js") }}', '{{ alert_type }}');
|
||||
{% endfor %}
|
||||
|
||||
// Confirm TFA modal
|
||||
{% if pending_tfa_methods %}
|
||||
new bootstrap.Modal(document.getElementById("ConfirmTFAModal"), {
|
||||
backdrop: 'static',
|
||||
keyboard: false
|
||||
}).show();
|
||||
|
||||
|
||||
// validate Time based OTP tfa
|
||||
$("#pending_tfa_tab_totp").click(function(){
|
||||
$(".webauthn-authenticator-selection").removeClass("active");
|
||||
$("#collapseWebAuthnTFA").collapse('hide');
|
||||
|
||||
// select default if only one authenticator exists
|
||||
if ($('.totp-authenticator-selection').length == 1){
|
||||
$('.totp-authenticator-selection').addClass("active");
|
||||
var id = $('.totp-authenticator-selection').children('input').first().val();
|
||||
$("#totp_selected_id").val(id);
|
||||
$("#collapseTotpTFA").collapse('show');
|
||||
}
|
||||
});
|
||||
$(".totp-authenticator-selection").click(function(){
|
||||
$(".totp-authenticator-selection").removeClass("active");
|
||||
$(this).addClass("active");
|
||||
|
||||
var id = $(this).children('input').first().val();
|
||||
$("#totp_selected_id").val(id);
|
||||
|
||||
$("#collapseTotpTFA").collapse('show');
|
||||
});
|
||||
if ($('.totp-authenticator-selection').length == 1 &&
|
||||
$('#pending_tfa_tab_yubi_otp').length == 0 &&
|
||||
$('.webauthn-authenticator-selection').length == 0){
|
||||
|
||||
// select default if only one authenticator exists
|
||||
$('.totp-authenticator-selection').addClass("active");
|
||||
|
||||
var id = $('.totp-authenticator-selection').children('input').first().val();
|
||||
$("#totp_selected_id").val(id);
|
||||
|
||||
$("#collapseTotpTFA").collapse('show');
|
||||
setTimeout(function() { $("#collapseTotpTFA").find('input[name="token"]').focus(); }, 1000);
|
||||
}
|
||||
$('#pending_tfa_tab_totp').on('shown.bs.tab', function() {
|
||||
// autofocus
|
||||
setTimeout(function() { $("#collapseTotpTFA").find('input[name="token"]').focus(); }, 200);
|
||||
});
|
||||
// validate Yubi OTP tfa
|
||||
if ($('.webauthn-authenticator-selection').length == 0){
|
||||
// autofocus
|
||||
setTimeout(function() { $("#collapseYubiTFA").find('input[name="token"]').focus(); }, 1000);
|
||||
}
|
||||
$('#pending_tfa_tab_yubi_otp').on('shown.bs.tab', function() {
|
||||
// autofocus
|
||||
$("#collapseYubiTFA").find('input[name="token"]').focus();
|
||||
});
|
||||
// validate WebAuthn tfa
|
||||
$("#pending_tfa_tab_webauthn").click(function(){
|
||||
$(".totp-authenticator-selection").removeClass("active");
|
||||
|
||||
$("#collapseTotpTFA").collapse('hide');
|
||||
});
|
||||
$(".webauthn-authenticator-selection").click(function(){
|
||||
$(".webauthn-authenticator-selection").removeClass("active");
|
||||
$(this).addClass("active");
|
||||
|
||||
var id = $(this).children('input').first().val();
|
||||
$("#webauthn_selected_id").val(id);
|
||||
|
||||
var webauthn_status_auth = document.getElementById('webauthn_status_auth');
|
||||
webauthn_status_auth.style.setProperty('display', 'flex', 'important');
|
||||
var webauthn_return_code = document.getElementById('webauthn_return_code');
|
||||
webauthn_return_code.style.setProperty('display', 'none', 'important');
|
||||
|
||||
$("#collapseWebAuthnTFA").collapse('show');
|
||||
|
||||
$(this).find('input[name=token]').focus();
|
||||
if(document.getElementById("webauthn_auth_data") !== null) {
|
||||
// Check Browser support
|
||||
if (!window.fetch || !navigator.credentials || !navigator.credentials.create) {
|
||||
window.alert('Browser not supported for WebAuthn.');
|
||||
return;
|
||||
}
|
||||
|
||||
// fetch webauthn auth args
|
||||
window.fetch("/api/v1/get/webauthn-tfa-get-args", {method:'GET',cache:'no-cache'}).then(response => {
|
||||
return response.json();
|
||||
}).then(json => {
|
||||
console.log(json);
|
||||
if (json.success === false) throw new Error();
|
||||
if (json.type === "error") throw new Error(json.msg);
|
||||
|
||||
recursiveBase64StrToArrayBuffer(json);
|
||||
return json;
|
||||
}).then(getCredentialArgs => {
|
||||
// get credentials
|
||||
return navigator.credentials.get(getCredentialArgs);
|
||||
}).then(cred => {
|
||||
return {
|
||||
id: cred.rawId ? arrayBufferToBase64(cred.rawId) : null,
|
||||
clientDataJSON: cred.response.clientDataJSON ? arrayBufferToBase64(cred.response.clientDataJSON) : null,
|
||||
authenticatorData: cred.response.authenticatorData ? arrayBufferToBase64(cred.response.authenticatorData) : null,
|
||||
signature : cred.response.signature ? arrayBufferToBase64(cred.response.signature) : null
|
||||
};
|
||||
}).then(JSON.stringify).then(function(AuthenticatorAttestationResponse) {
|
||||
// send request by submit
|
||||
var form = document.getElementById('webauthn_auth_form');
|
||||
var auth = document.getElementById('webauthn_auth_data');
|
||||
auth.value = AuthenticatorAttestationResponse;
|
||||
form.submit();
|
||||
}).catch(function(err) {
|
||||
var webauthn_status_auth = document.getElementById('webauthn_status_auth');
|
||||
webauthn_status_auth.style.setProperty('display', 'none', 'important');
|
||||
|
||||
var webauthn_return_code = document.getElementById('webauthn_return_code');
|
||||
webauthn_return_code.style.setProperty('display', 'block', 'important');
|
||||
webauthn_return_code.innerHTML = lang_tfa.error_code + ': ' + err + ' ' + lang_tfa.reload_retry;
|
||||
});
|
||||
}
|
||||
});
|
||||
$('#ConfirmTFAModal').on('hidden.bs.modal', function(){
|
||||
// cancel pending login
|
||||
$.ajax({
|
||||
type: "GET",
|
||||
cache: false,
|
||||
dataType: 'script',
|
||||
url: '/inc/ajax/destroy_tfa_auth.php',
|
||||
complete: function(data){
|
||||
window.location = window.location.href.split("#")[0];
|
||||
}
|
||||
});
|
||||
});
|
||||
{% endif %}
|
||||
|
||||
|
||||
// Validate FIDO2
|
||||
$("#fido2-login").click(function(){
|
||||
$('#fido2-alerts').html();
|
||||
if (!window.fetch || !navigator.credentials || !navigator.credentials.create) {
|
||||
window.alert('Browser not supported.');
|
||||
return;
|
||||
}
|
||||
window.fetch("/api/v1/get/fido2-get-args", {method:'GET',cache:'no-cache'}).then(function(response) {
|
||||
return response.json();
|
||||
}).then(function(json) {
|
||||
if (json.success === false) {
|
||||
throw new Error();
|
||||
}
|
||||
recursiveBase64StrToArrayBuffer(json);
|
||||
return json;
|
||||
}).then(function(getCredentialArgs) {
|
||||
return navigator.credentials.get(getCredentialArgs);
|
||||
}).then(function(cred) {
|
||||
return {
|
||||
id: cred.rawId ? arrayBufferToBase64(cred.rawId) : null,
|
||||
clientDataJSON: cred.response.clientDataJSON ? arrayBufferToBase64(cred.response.clientDataJSON) : null,
|
||||
authenticatorData: cred.response.authenticatorData ? arrayBufferToBase64(cred.response.authenticatorData) : null,
|
||||
signature : cred.response.signature ? arrayBufferToBase64(cred.response.signature) : null
|
||||
};
|
||||
}).then(JSON.stringify).then(function(AuthenticatorAttestationResponse) {
|
||||
return window.fetch("/api/v1/process/fido2-args", {method:'POST', body: AuthenticatorAttestationResponse, cache:'no-cache'});
|
||||
}).then(function(response) {
|
||||
return response.json();
|
||||
}).then(function(json) {
|
||||
if (json.success) {
|
||||
window.location = window.location.href.split("#")[0];
|
||||
} else {
|
||||
throw new Error();
|
||||
}
|
||||
}).catch(function(err) {
|
||||
if (typeof err.message === 'undefined') {
|
||||
mailcow_alert_box(lang_fido2.fido2_validation_failed, "danger");
|
||||
} else {
|
||||
mailcow_alert_box(lang_fido2.fido2_validation_failed + ":<br><i>" + err.message + "</i>", "danger");
|
||||
}
|
||||
});
|
||||
});
|
||||
// Set TFA/FIDO2
|
||||
$("#register-fido2, #register-fido2-touchid").click(function(){
|
||||
let t = $(this);
|
||||
|
||||
$("option:selected").prop("selected", false);
|
||||
if (!window.fetch || !navigator.credentials || !navigator.credentials.create) {
|
||||
window.alert('Browser not supported.');
|
||||
return;
|
||||
}
|
||||
|
||||
window.fetch("/api/v1/get/fido2-registration/{{ mailcow_cc_username|url_encode(true)|default('null') }}", {method:'GET',cache:'no-cache'}).then(function(response) {
|
||||
return response.json();
|
||||
}).then(function(json) {
|
||||
if (json.success === false) {
|
||||
throw new Error(json.msg);
|
||||
}
|
||||
recursiveBase64StrToArrayBuffer(json);
|
||||
|
||||
// set attestation to node if we are registering apple touch id
|
||||
if(t.attr('id') === 'register-fido2-touchid') {
|
||||
json.publicKey.attestation = 'none';
|
||||
json.publicKey.authenticatorSelection.authenticatorAttachment = "platform";
|
||||
}
|
||||
|
||||
return json;
|
||||
}).then(function(createCredentialArgs) {
|
||||
console.log(createCredentialArgs);
|
||||
return navigator.credentials.create(createCredentialArgs);
|
||||
}).then(function(cred) {
|
||||
return {
|
||||
clientDataJSON: cred.response.clientDataJSON ? arrayBufferToBase64(cred.response.clientDataJSON) : null,
|
||||
attestationObject: cred.response.attestationObject ? arrayBufferToBase64(cred.response.attestationObject) : null
|
||||
};
|
||||
}).then(JSON.stringify).then(function(AuthenticatorAttestationResponse) {
|
||||
return window.fetch("/api/v1/add/fido2-registration", {method:'POST', body: AuthenticatorAttestationResponse, cache:'no-cache'});
|
||||
}).then(function(response) {
|
||||
return response.json();
|
||||
}).then(function(json) {
|
||||
if (json.success) {
|
||||
window.location = window.location.href.split("#")[0];
|
||||
} else {
|
||||
throw new Error(json.msg);
|
||||
}
|
||||
}).catch(function(err) {
|
||||
$('#fido2-alerts').html('<span class="text-danger"><b>' + err.message + '</b></span>');
|
||||
});
|
||||
});
|
||||
$('#selectTFA').change(function () {
|
||||
if ($(this).val() == "yubi_otp") {
|
||||
$('#YubiOTPModal').modal('show');
|
||||
$("option:selected").prop("selected", false);
|
||||
}
|
||||
if ($(this).val() == "totp") {
|
||||
$('#TOTPModal').modal('show');
|
||||
request_token = $('#tfa-qr-img').data('totp-secret');
|
||||
$.ajax({
|
||||
url: '/inc/ajax/qr_gen.php',
|
||||
data: {
|
||||
token: request_token,
|
||||
},
|
||||
}).done(function (result) {
|
||||
$("#tfa-qr-img").attr("src", result);
|
||||
});
|
||||
$("option:selected").prop("selected", false);
|
||||
}
|
||||
if ($(this).val() == "webauthn") {
|
||||
// check if Browser is supported
|
||||
if (!window.fetch || !navigator.credentials || !navigator.credentials.create) {
|
||||
window.alert('Browser not supported.');
|
||||
return;
|
||||
}
|
||||
|
||||
// show modal
|
||||
$('#WebAuthnModal').modal('show');
|
||||
$("option:selected").prop("selected", false);
|
||||
|
||||
$("#start_webauthn_register").click(() => {
|
||||
var key_id = document.getElementsByName('key_id')[1].value;
|
||||
var confirm_password = document.getElementsByName('confirm_password')[1].value;
|
||||
|
||||
// fetch WebAuthn create args
|
||||
window.fetch("/api/v1/get/webauthn-tfa-registration/{{ mailcow_cc_username|url_encode(true)|default('null') }}", {method:'GET',cache:'no-cache'}).then(response => {
|
||||
return response.json();
|
||||
}).then(json => {
|
||||
console.log(json);
|
||||
if (json.success === false) throw new Error(json.msg);
|
||||
recursiveBase64StrToArrayBuffer(json);
|
||||
|
||||
return json;
|
||||
}).then(createCredentialArgs => {
|
||||
// create credentials
|
||||
return navigator.credentials.create(createCredentialArgs);
|
||||
}).then(cred => {
|
||||
return {
|
||||
clientDataJSON: cred.response.clientDataJSON ? arrayBufferToBase64(cred.response.clientDataJSON) : null,
|
||||
attestationObject: cred.response.attestationObject ? arrayBufferToBase64(cred.response.attestationObject) : null,
|
||||
key_id: key_id,
|
||||
tfa_method: "webauthn",
|
||||
confirm_password: confirm_password
|
||||
};
|
||||
}).then(JSON.stringify).then(AuthenticatorAttestationResponse => {
|
||||
// send request
|
||||
return window.fetch("/api/v1/add/webauthn-tfa-registration", {method:'POST', body: AuthenticatorAttestationResponse, cache:'no-cache'});
|
||||
}).then(response => {
|
||||
return response.json();
|
||||
}).then(json => {
|
||||
if (json.success) {
|
||||
// reload on success
|
||||
window.location = window.location.href.split("#")[0];
|
||||
} else {
|
||||
throw new Error(json.msg);
|
||||
}
|
||||
}).catch(function(err) {
|
||||
console.log(err);
|
||||
var webauthn_return_code = document.getElementById('webauthn_return_code');
|
||||
webauthn_return_code.style.display = webauthn_return_code.style.display === 'none' ? '' : null;
|
||||
webauthn_return_code.innerHTML = lang_tfa.error_code + ': ' + err + ' ' + lang_tfa.reload_retry;
|
||||
});
|
||||
});
|
||||
}
|
||||
if ($(this).val() == "none") {
|
||||
$('#DisableTFAModal').modal('show');
|
||||
$("option:selected").prop("selected", false);
|
||||
}
|
||||
});
|
||||
|
||||
{% if mailcow_cc_username %}
|
||||
// Reload after session timeout
|
||||
var session_lifetime = {{ (session_lifetime * 1000) + 15000 }};
|
||||
setTimeout(function() {
|
||||
location.reload();
|
||||
}, session_lifetime);
|
||||
{% endif %}
|
||||
|
||||
// CSRF
|
||||
$('<input type="hidden" value="{{ csrf_token }}">').attr('name', 'csrf_token').appendTo('form');
|
||||
if (sessionStorage.scrollTop != "undefined") {
|
||||
$(window).scrollTop(sessionStorage.scrollTop);
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<div class="container footer">
|
||||
{% if ui_texts.ui_footer %}
|
||||
<hr><span class="rot-enc">{{ ui_texts.ui_footer|rot13|raw }}</span>
|
||||
{% endif %}
|
||||
{% if mailcow_cc_username and mailcow_info.mailcow_branch|lower == "master" and mailcow_info.version_tag|default %}
|
||||
<span class="version">
|
||||
🐮 + 🐋 = 💕
|
||||
Version: <a href="{{ mailcow_info.git_project_url }}/releases/tag/{{ mailcow_info.version_tag }}" target="_blank">{{ mailcow_info.version_tag }}
|
||||
</a>
|
||||
</span>
|
||||
{% endif %}
|
||||
{% if mailcow_cc_username and mailcow_info.mailcow_branch|lower == "nightly" and mailcow_info.version_tag|default %}
|
||||
<span class="version">
|
||||
🛠️🐮 + 🐋 = 💕
|
||||
Nightly: <a href="{{ mailcow_info.git_project_url }}/commit/{{ mailcow_info.git_commit }}" target="_blank">{{ mailcow_info.version_tag }}
|
||||
</a><br>
|
||||
<span style="text-align:right;display:block;">Build: {{ mailcow_info.git_commit_date }}</span>
|
||||
</span>
|
||||
{% endif %}
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
0
data/web/templates/cache/.gitkeep
vendored
Executable file
0
data/web/templates/cache/.gitkeep
vendored
Executable file
639
data/web/templates/debug.twig
Executable file
639
data/web/templates/debug.twig
Executable file
File diff suppressed because one or more lines are too long
82
data/web/templates/domainadmin.twig
Executable file
82
data/web/templates/domainadmin.twig
Executable file
|
|
@ -0,0 +1,82 @@
|
|||
{% extends 'base.twig' %}
|
||||
|
||||
{% block content %}
|
||||
<h3>{{ lang.user.user_settings }}</h3>
|
||||
<div class="card">
|
||||
<div class="card-header">{{ lang.user.user_settings }}</div>
|
||||
<div class="card-body">
|
||||
<div class="row">
|
||||
<div class="offset-sm-3 col-sm-9">
|
||||
<p><a href="#pwChangeModal" data-bs-toggle="modal">[{{ lang.user.change_password }}]</a></p>
|
||||
<div class="last-login"></div>
|
||||
<span class="clear-last-logins">{{ lang.user.clear_recent_successful_connections }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<hr>
|
||||
|
||||
{# TFA #}
|
||||
<div class="row">
|
||||
<div class="col-sm-3 col-5 text-end">{{ lang.tfa.tfa }}</div>
|
||||
<div class="col-sm-9 col-7">
|
||||
<p id="tfa_pretty">{{ tfa_data.pretty }}</p>
|
||||
{% include 'tfa_keys.twig' %}
|
||||
<br>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-sm-3 col-5 text-end">{{ lang.tfa.set_tfa }}</div>
|
||||
<div class="col-sm-9 col-7">
|
||||
<select id="selectTFA" class="selectpicker" title="{{ lang.tfa.select }}">
|
||||
<option value="yubi_otp">{{ lang.tfa.yubi_otp }}</option>
|
||||
<option value="webauthn">{{ lang.tfa.webauthn }}</option>
|
||||
<option value="totp">{{ lang.tfa.totp }}</option>
|
||||
<option value="none">{{ lang.tfa.none }}</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<hr>
|
||||
{# FIDO2 #}
|
||||
<div class="row">
|
||||
<div class="col-sm-3 col-5 text-end">
|
||||
<p><i class="bi bi-shield-fill-check"></i> {{ lang.fido2.fido2_auth }}</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-sm-3 col-5 text-end">{{ lang.fido2.known_ids }}:</div>
|
||||
<div class="col-sm-9 col-7">
|
||||
<div class="table-responsive">
|
||||
<table class="table table-striped table-hover table-condensed w-100" id="fido2_keys">
|
||||
<tr>
|
||||
<th>ID</th>
|
||||
<th style="min-width:240px;text-align: right">{{ lang.admin.action }}</th>
|
||||
</tr>
|
||||
{% include 'fido2.twig' %}
|
||||
</table>
|
||||
</div>
|
||||
<br>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="offset-sm-3 col-sm-9">
|
||||
<div class="btn-group">
|
||||
<button class="btn btn-sm btn-primary" id="register-fido2">{{ lang.fido2.set_fido2 }}</button>
|
||||
<button type="button" class="btn btn-sm btn-xs-lg btn-primary dropdown-toggle" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false"></button>
|
||||
<ul class="dropdown-menu">
|
||||
<li><a class="dropdown-item" href="#" id="register-fido2-touchid"><i class="bi bi-shield-fill-check"></i> {{ lang.fido2.set_fido2_touchid }}</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<br>
|
||||
<div class="row" id="status-fido2">
|
||||
<div class="col-sm-3 col-5 text-end">{{ lang.fido2.register_status }}:</div>
|
||||
<div class="col-sm-9 col-7">
|
||||
<div id="fido2-alerts">-</div>
|
||||
</div>
|
||||
<br>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% include 'user_domainadmin_common.twig' %}
|
||||
{% endblock %}
|
||||
33
data/web/templates/edit.twig
Executable file
33
data/web/templates/edit.twig
Executable file
|
|
@ -0,0 +1,33 @@
|
|||
{% extends 'base.twig' %}
|
||||
|
||||
{% block content %}
|
||||
<a href="{{ return_to }}">← {{ lang.edit.previous }}</a>
|
||||
<div class="row my-4">
|
||||
<div class="col-md-12">
|
||||
<div class="card">
|
||||
<div class="card-header fs-5">
|
||||
<span>{{ lang.edit.title }}</span>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
{% block inner_content %}
|
||||
{% if access_denied %}
|
||||
<div class="alert alert-danger" role="alert">{{ lang.danger.access_denied }}</div>
|
||||
{% else %}
|
||||
<div class="alert alert-info" role="alert">{{ lang.info.no_action }}</div>
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<a href="{{ return_to }}">← {{ lang.edit.previous }}</a>
|
||||
|
||||
<script type='text/javascript'>
|
||||
var lang_user = {{ lang_user|raw }};
|
||||
var lang_admin = {{ lang_admin|raw }};
|
||||
var lang_datatables = {{ lang_datatables|raw }};
|
||||
var csrf_token = '{{ csrf_token }}';
|
||||
var pagination_size = Math.trunc('{{ pagination_size }}');
|
||||
var table_for_domain = '{{ domain }}';
|
||||
</script>
|
||||
{% endblock %}
|
||||
51
data/web/templates/edit/admin.twig
Executable file
51
data/web/templates/edit/admin.twig
Executable file
|
|
@ -0,0 +1,51 @@
|
|||
{% extends 'edit.twig' %}
|
||||
|
||||
{% block inner_content %}
|
||||
{% if result %}
|
||||
<h4>{{ lang.edit.admin }}</h4>
|
||||
<br>
|
||||
<form class="form-horizontal" data-id="editadmin" role="form" method="post" autocomplete="off">
|
||||
<input type="hidden" value="0" name="active">
|
||||
<div class="row mb-4">
|
||||
<label class="control-label col-sm-2" for="username_new">{{ lang.edit.username }}</label>
|
||||
<div class="col-sm-10">
|
||||
<input class="form-control" type="text" name="username_new" onkeyup="this.value = this.value.toLowerCase();" required value="{{ admin }}" />
|
||||
↳ <kbd>a-z - _ .</kbd>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-2">
|
||||
<label class="control-label col-sm-2" for="password">{{ lang.edit.password }} (<a href="#" class="generate_password">{{ lang.edit.generate }}</a>)</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="password" data-pwgen-field="true" data-hibp="true" class="form-control" name="password" placeholder="" autocomplete="new-password">
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-4">
|
||||
<label class="control-label col-sm-2" for="password2">{{ lang.edit.password_repeat }}</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="password" data-pwgen-field="true" class="form-control" name="password2" autocomplete="new-password">
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-2">
|
||||
<div class="offset-sm-2 col-sm-10">
|
||||
<div class="form-check">
|
||||
<label><input type="checkbox" class="form-check-input" value="1" name="active"{% if result.active == '1' %} checked{% endif %}> {{ lang.edit.active }}</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-2">
|
||||
<div class="offset-sm-2 col-sm-10">
|
||||
<div class="form-check">
|
||||
<label><input type="checkbox" class="form-check-input" value="1" name="disable_tfa"> {{ lang.tfa.disable_tfa }}</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="offset-sm-2 col-sm-10">
|
||||
<button class="btn btn-xs-lg d-block d-sm-inline btn-success" data-action="edit_selected" data-api-reload-location="/admin" data-id="editadmin" data-item="{{ admin }}" data-api-url='edit/admin' data-api-attr='{}' href="#">{{ lang.edit.save }}</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
{% else %}
|
||||
{{ parent() }}
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
70
data/web/templates/edit/alias.twig
Executable file
70
data/web/templates/edit/alias.twig
Executable file
|
|
@ -0,0 +1,70 @@
|
|||
{% extends 'edit.twig' %}
|
||||
|
||||
{% block inner_content %}
|
||||
{% if result %}
|
||||
<h4>{{ lang.edit.alias }}</h4>
|
||||
<br>
|
||||
<form class="form-horizontal" data-id="editalias" role="form" method="post">
|
||||
<input type="hidden" value="0" name="active">
|
||||
{% if not skip_sogo %}
|
||||
<input type="hidden" value="0" name="sogo_visible">
|
||||
{% endif %}
|
||||
<div class="row mb-2">
|
||||
<label class="control-label col-sm-2" for="address">{{ lang.edit.alias }}</label>
|
||||
<div class="col-sm-10">
|
||||
<input class="form-control" type="text" name="address" value="{{ result.address }}" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-4">
|
||||
<label class="control-label col-sm-2" for="goto">{{ lang.edit.target_address|raw }}</label>
|
||||
<div class="col-sm-10">
|
||||
<textarea id="textarea_alias_goto" class="form-control mb-4" autocapitalize="none" autocorrect="off" rows="10" id="goto" name="goto" required>{{ goto|replace({',': ', '}) }}</textarea>
|
||||
<div class="form-check">
|
||||
<label><input class="form-check-input goto_checkbox" type="checkbox" value="1" name="goto_null"{% if result.goto == 'null@localhost' %} checked{% endif %}> {{ lang.add.goto_null }}</label>
|
||||
</div>
|
||||
<div class="form-check">
|
||||
<label><input class="form-check-input goto_checkbox" type="checkbox" value="1" name="goto_spam"{% if result.goto == 'spam@localhost' %} checked{% endif %}> {{ lang.add.goto_spam|raw }}</label>
|
||||
</div>
|
||||
<div class="form-check">
|
||||
<label><input class="form-check-input goto_checkbox" type="checkbox" value="1" name="goto_ham"{% if result.goto == 'ham@localhost' %} checked{% endif %}> {{ lang.add.goto_ham|raw }}</label>
|
||||
</div>
|
||||
{% if not skip_sogo %}
|
||||
<hr>
|
||||
<div class="form-check">
|
||||
<label><input type="checkbox" class="form-check-input" value="1" name="sogo_visible"{% if result.sogo_visible == '1' %} checked{% endif %}> {{ lang.edit.sogo_visible }}</label>
|
||||
</div>
|
||||
<p class="text-muted">{{ lang.edit.sogo_visible_info }}</p>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
<hr>
|
||||
<div class="row mb-2">
|
||||
<label class="control-label col-sm-2" for="private_">{{ lang.edit.private_comment }}</label>
|
||||
<div class="col-sm-10">
|
||||
<input maxlength="160" class="form-control" type="text" name="private_comment" value="{{ result.private_comment }}" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-4">
|
||||
<label class="control-label col-sm-2" for="public_comment">{{ lang.edit.public_comment }}</label>
|
||||
<div class="col-sm-10">
|
||||
<input maxlength="160" class="form-control" type="text" name="public_comment" value="{{ result.public_comment }}" />
|
||||
</div>
|
||||
</div>
|
||||
<hr>
|
||||
<div class="row mb-2">
|
||||
<div class="offset-sm-2 col-sm-10">
|
||||
<div class="form-check">
|
||||
<label><input type="checkbox" class="form-check-input" value="1" name="active"{% if result.active == '1' %} checked{% endif %}> {{ lang.edit.active }}</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="offset-sm-2 col-sm-10">
|
||||
<button class="btn btn-xs-lg d-block d-sm-inline btn-success" data-action="edit_selected" data-id="editalias" data-item="{{ alias }}" data-api-url='edit/alias' data-api-attr='{}' href="#">{{ lang.edit.save }}</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
{% else %}
|
||||
{{ parent() }}
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
56
data/web/templates/edit/aliasdomain.twig
Executable file
56
data/web/templates/edit/aliasdomain.twig
Executable file
|
|
@ -0,0 +1,56 @@
|
|||
{% extends 'edit.twig' %}
|
||||
|
||||
{% block inner_content %}
|
||||
{% if result %}
|
||||
<h4 class="mb-4">{{ lang.edit.edit_alias_domain }}</h4>
|
||||
<form class="form-horizontal" data-id="editaliasdomain" role="form" method="post">
|
||||
<input type="hidden" value="0" name="active">
|
||||
<div class="row mb-2">
|
||||
<label class="control-label col-sm-2" for="target_domain">{{ lang.edit.target_domain }}</label>
|
||||
<div class="col-sm-10">
|
||||
<select class="full-width-select" data-live-search="true" id="addSelectDomain" name="target_domain" required>
|
||||
{% for domain in domains %}
|
||||
<option{% if result.target_domain == domain %} selected{% endif %}>{{ domain }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-2">
|
||||
<div class="offset-sm-2 col-sm-10">
|
||||
<div class="form-check">
|
||||
<label><input type="checkbox" class="form-check-input" value="1" name="active"{% if result.active == '1' %} checked{% endif %}> {{ lang.edit.active }}</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-4">
|
||||
<div class="offset-sm-2 col-sm-10">
|
||||
<button class="btn btn-xs-lg d-block d-sm-inline btn-success" data-action="edit_selected" data-id="editaliasdomain" data-item="{{ alias_domain }}" data-api-url='edit/alias-domain' data-api-attr='{}' href="#">{{ lang.edit.save }}</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
<hr>
|
||||
<form data-id="domratelimit" class="form-inline well" method="post">
|
||||
<label class="control-label mb-2">{{ lang.acl.ratelimit }}</label>
|
||||
<div class="input-group mb-4">
|
||||
<input name="rl_value" type="number" value="{{ rl.value }}" autocomplete="off" class="form-control" placeholder="{{ lang.ratelimit.disabled }}">
|
||||
<select name="rl_frame" class="form-control">
|
||||
{% include 'mailbox/rl-frame.twig' %}
|
||||
</select>
|
||||
</div>
|
||||
<button class="btn btn-xs-lg d-block d-sm-inline btn-secondary" data-action="edit_selected" data-id="domratelimit" data-item="{{ alias_domain }}" data-api-url='edit/rl-domain' data-api-attr='{}' href="#">{{ lang.admin.save }}</button>
|
||||
</form>
|
||||
{% if dkim %}
|
||||
<hr>
|
||||
<div class="row">
|
||||
<div class="col-12 col-sm-2">
|
||||
<p>{{ lang.add.domain }}: <strong>{{ result.alias_domain }}</strong> ({{ dkim.dkim_selector }}._domainkey)</p>
|
||||
</div>
|
||||
<div class="col-12 col-sm-10">
|
||||
<pre class="p-2">{{ dkim.dkim_txt }}</pre>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% else %}
|
||||
{{ parent() }}
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
56
data/web/templates/edit/app-passwd.twig
Executable file
56
data/web/templates/edit/app-passwd.twig
Executable file
|
|
@ -0,0 +1,56 @@
|
|||
{% extends 'edit.twig' %}
|
||||
|
||||
{% block inner_content %}
|
||||
{% if result %}
|
||||
<h4>{{ lang.edit.app_passwd }}</h4>
|
||||
<form class="form-horizontal" data-pwgen-length="32" data-id="editapp" role="form" method="post">
|
||||
<input type="hidden" value="0" name="active">
|
||||
<input type="hidden" value="0" name="protocols">
|
||||
<div class="row mb-4">
|
||||
<label class="control-label col-sm-2" for="app_name">{{ lang.edit.app_name }}</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="text" class="form-control" name="app_name" id="app_name" value="{{ result.name }}" required maxlength="255">
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-2">
|
||||
<label class="control-label col-sm-2" for="password">{{ lang.edit.password }} (<a href="#" class="generate_password">{{ lang.edit.generate }}</a>)</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="password" data-pwgen-field="true" data-hibp="true" class="form-control" name="password" placeholder="" autocomplete="new-password">
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-4">
|
||||
<label class="control-label col-sm-2" for="password2">{{ lang.edit.password_repeat }}</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="password" data-pwgen-field="true" class="form-control" name="password2" autocomplete="new-password">
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-2">
|
||||
<div class="offset-sm-2 col-sm-10">
|
||||
<div class="form-check">
|
||||
<label><input type="checkbox" class="form-check-input" value="1" name="active"{% if result.active == '1' %} checked{% endif %}> {{ lang.edit.active }}</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-4">
|
||||
<label class="control-label col-sm-2" for="protocols">{{ lang.edit.app_passwd_protocols }}</label>
|
||||
<div class="col-sm-10">
|
||||
<select class="full-width-select" data-live-search="true" id="protocols" name="protocols" multiple>
|
||||
<option value="imap_access" {% if result.imap_access == 1 %} selected{% endif %}>IMAP</option>
|
||||
<option value="smtp_access" {% if result.smtp_access == 1 %} selected{% endif %}>SMTP</option>
|
||||
<option value="eas_access" {% if result.eas_access == 1 %} selected{% endif %}>EAS/ActiveSync</option>
|
||||
<option value="dav_access" {% if result.dav_access == 1 %} selected{% endif %}>CardDAV/CalDAV</option>
|
||||
<option value="pop3_access" {% if result.pop3_access == 1 %} selected{% endif %}>POP3</option>
|
||||
<option value="sieve_access" {% if result.sieve_access == 1 %} selected{% endif %}>Sieve</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-2">
|
||||
<div class="offset-sm-2 col-sm-10">
|
||||
<button class="btn btn-xs-lg d-block d-sm-inline btn-success" data-action="edit_selected" data-id="editapp" data-item="{{ result.id }}" data-api-url='edit/app-passwd' data-api-attr='{}' href="#">{{ lang.edit.save }}</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
{% else %}
|
||||
{{ parent() }}
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
41
data/web/templates/edit/bcc.twig
Executable file
41
data/web/templates/edit/bcc.twig
Executable file
|
|
@ -0,0 +1,41 @@
|
|||
{% extends 'edit.twig' %}
|
||||
|
||||
{% block inner_content %}
|
||||
{% if result %}
|
||||
<h4>{{ lang.mailbox.bcc_map }}</h4>
|
||||
<br>
|
||||
<form class="form-horizontal" data-id="editbcc" role="form" method="post">
|
||||
<input type="hidden" value="0" name="active">
|
||||
<div class="row mb-2">
|
||||
<label class="control-label col-sm-2" for="bcc_dest">{{ lang.mailbox.bcc_destination }}</label>
|
||||
<div class="col-sm-10">
|
||||
<input value="{{ result.bcc_dest }}" type="text" class="form-control" name="bcc_dest" id="bcc_dest">
|
||||
<small>{{ lang.edit.bcc_dest_format|raw }}</small>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-4">
|
||||
<label class="control-label col-sm-2" for="type">{{ lang.mailbox.bcc_map_type }}</label>
|
||||
<div class="col-sm-10">
|
||||
<select id="addFilterType" name="type" id="type" required>
|
||||
<option value="sender"{% if result.type == 'sender'%} selected{% endif %}>{{ lang.mailbox.bcc_sender_map }}</option>
|
||||
<option value="rcpt"{% if result.type == 'rcpt'%} selected{% endif %}>{{ lang.mailbox.bcc_rcpt_map }}</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-2">
|
||||
<div class="offset-sm-2 col-sm-10">
|
||||
<div class="form-check">
|
||||
<label><input type="checkbox" class="form-check-input" value="1" name="active"{% if result.active == '1' %} checked{% endif %}> {{ lang.edit.active }}</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-2">
|
||||
<div class="offset-sm-2 col-sm-10">
|
||||
<button class="btn btn-xs-lg d-block d-sm-inline btn-success" data-action="edit_selected" data-id="editbcc" data-item="{{ bcc }}" data-api-url='edit/bcc' data-api-attr='{}' href="#">{{ lang.edit.save }}</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
{% else %}
|
||||
{{ parent() }}
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
135
data/web/templates/edit/domain-templates.twig
Executable file
135
data/web/templates/edit/domain-templates.twig
Executable file
|
|
@ -0,0 +1,135 @@
|
|||
{% extends 'edit.twig' %}
|
||||
|
||||
{% block inner_content %}
|
||||
{% if result %}
|
||||
<div id="dedit" class="tab-pane fade show active" role="tabpanel" aria-labelledby="domain-edit">
|
||||
<form data-id="editdomain_template" class="form-horizontal" role="form" method="post">
|
||||
|
||||
<input type="hidden" value="0" name="active">
|
||||
<input type="hidden" value="0" name="backupmx">
|
||||
<input type="hidden" value="0" name="gal">
|
||||
<input type="hidden" value="0" name="relay_all_recipients">
|
||||
<input type="hidden" value="0" name="relay_unknown_only">
|
||||
|
||||
{% if mailcow_cc_role == 'admin' %}
|
||||
<div class="row mb-4">
|
||||
<label class="control-label col-sm-2" for="max_num_aliases_for_domain">{{ lang.mailbox.template }}</label>
|
||||
<div class="col-sm-10">
|
||||
|
||||
<div class="input-group mb-3">
|
||||
<input type="text" name="template" class="form-control" aria-label="Text input with dropdown button" value="{{ template.template }}" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class="row mb-4">
|
||||
<label class="control-label col-sm-2">{{ lang.add.tags }}</label>
|
||||
<div class="col-sm-10">
|
||||
<div class="form-control tag-box">
|
||||
<input id="tags" type="text" class="tag-input">
|
||||
<span class="btn tag-add"><i class="bi bi-plus-lg"></i></span>
|
||||
<input type="hidden" value='{{ template.attributes.tags|json_encode }}' name="tags" class="tag-values" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-2">
|
||||
<label class="control-label col-sm-2" for="max_num_aliases_for_domain">{{ lang.edit.max_aliases }}</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="number" class="form-control" name="max_num_aliases_for_domain" value="{{ template.attributes.max_num_aliases_for_domain }}">
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-2">
|
||||
<label class="control-label col-sm-2" for="max_num_mboxes_for_domain">{{ lang.edit.max_mailboxes }}</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="number" class="form-control" name="max_num_mboxes_for_domain" value="{{ template.attributes.max_num_mboxes_for_domain }}">
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-2">
|
||||
<label class="control-label col-sm-2" for="def_quota_for_mbox">{{ lang.edit.mailbox_quota_def }}</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="number" class="form-control" name="def_quota_for_mbox" value="{{ (template.attributes.def_quota_for_mbox / 1048576) }}">
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-2">
|
||||
<label class="control-label col-sm-2" for="max_quota_for_mbox">{{ lang.edit.max_quota }}</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="number" class="form-control" name="max_quota_for_mbox" value="{{ (template.attributes.max_quota_for_mbox / 1048576) }}">
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-4">
|
||||
<label class="control-label col-sm-2" for="max_quota_for_domain">{{ lang.edit.domain_quota }}</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="number" class="form-control" name="max_quota_for_domain" value="{{ (template.attributes.max_quota_for_domain / 1048576) }}">
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="offset-sm-2 col-sm-10">
|
||||
<div class="form-check">
|
||||
<label><input type="checkbox" class="form-check-input" value="1" name="gal"{% if template.attributes.gal == '1' %} checked{% endif %}> {{ lang.edit.gal }}</label>
|
||||
<small class="text-muted">{{ lang.edit.gal_info|raw }}</small>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-2">
|
||||
<div class="offset-sm-2 col-sm-10">
|
||||
<div class="form-check">
|
||||
<label><input type="checkbox" class="form-check-input" value="1" name="active"{% if template.attributes.active == '1' %} checked{% endif %}{% if mailcow_cc_role != 'admin' %} disabled{% endif %}> {{ lang.edit.active }}</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<hr>
|
||||
<div class="row">
|
||||
<label class="control-label col-sm-2">{{ lang.edit.ratelimit }}</label>
|
||||
<div class="col-sm-10">
|
||||
<div class="input-group">
|
||||
<input name="rl_value" type="number" value="{{ template.attributes.rl_value }}" autocomplete="off" class="form-control mb-4" placeholder="{{ lang.ratelimit.disabled }}">
|
||||
<select name="rl_frame" class="form-control">
|
||||
{% include 'mailbox/rl-frame.twig' %}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
<hr>
|
||||
<div class="row mb-2">
|
||||
<label class="control-label col-sm-2" for="dkim_selector">{{ lang.admin.dkim_domains_selector }}</label>
|
||||
<div class="col-sm-10">
|
||||
<input class="form-control" id="dkim_selector" name="dkim_selector" value="{{ template.attributes.dkim_selector }}">
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-4">
|
||||
<label class="control-label col-sm-2" for="key_size">{{ lang.admin.dkim_key_length }}</label>
|
||||
<div class="col-sm-10">
|
||||
<select data-style="btn btn-light" class="form-control" id="key_size" name="key_size">
|
||||
<option value="1024" data-subtext="bits" {% if template.attributes.key_size == 1024 %} selected{% endif %}>1024</option>
|
||||
<option value="2048" data-subtext="bits" {% if template.attributes.key_size == 2048 %} selected{% endif %}>2048</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<hr>
|
||||
<div class="row mb-2">
|
||||
<label class="control-label col-sm-2">{{ lang.edit.backup_mx_options }}</label>
|
||||
<div class="col-sm-10">
|
||||
<div class="form-check">
|
||||
<label><input type="checkbox" class="form-check-input" value="1" name="backupmx"{% if template.attributes.backupmx == '1' %} checked{% endif %}> {{ lang.edit.relay_domain }}</label>
|
||||
<br>
|
||||
<label><input type="checkbox" class="form-check-input" value="1" name="relay_all_recipients"{% if template.attributes.relay_all_recipients == '1' %} checked{% endif %}> {{ lang.edit.relay_all }}</label>
|
||||
<p>{{ lang.edit.relay_all_info|raw }}</p>
|
||||
<label><input type="checkbox" class="form-check-input" value="1" name="relay_unknown_only"{% if template.attributes.relay_unknown_only == '1' %} checked{% endif %}> {{ lang.edit.relay_unknown_only }}</label>
|
||||
<br>
|
||||
<p>{{ lang.edit.relay_transport_info|raw }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<hr>
|
||||
<div class="row">
|
||||
<div class="offset-sm-2 col-sm-10">
|
||||
<button class="btn btn-xs-lg d-block d-sm-inline btn-success" data-action="edit_selected" data-id="editdomain_template" data-item="{{ template.id }}" data-api-url='edit/domain/template' data-api-attr='{}' href="#">{{ lang.admin.save }}</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
{% else %}
|
||||
{{ parent() }}
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
358
data/web/templates/edit/domain.twig
Executable file
358
data/web/templates/edit/domain.twig
Executable file
|
|
@ -0,0 +1,358 @@
|
|||
{% extends 'edit.twig' %}
|
||||
|
||||
{% block inner_content %}
|
||||
{% if result %}
|
||||
<div id="domain-content" class="responsive-tabs">
|
||||
<ul class="nav nav-tabs" role="tablist">
|
||||
<li role="presentation" class="nav-item"><button class="nav-link active" data-bs-toggle="tab" data-bs-target="#dedit">{{ lang.edit.domain }}</button></li>
|
||||
<li role="presentation" class="nav-item"><button class="nav-link" data-bs-toggle="tab" data-bs-target="#dratelimit">{{ lang.edit.ratelimit }}</button></li>
|
||||
<li role="presentation" class="nav-item"><button class="nav-link" data-bs-toggle="tab" data-bs-target="#dspamfilter">{{ lang.edit.spam_filter }}</button></li>
|
||||
<li role="presentation" class="nav-item"><button class="nav-link" data-bs-toggle="tab" data-bs-target="#dqwbcc">{{ lang.edit.quota_warning_bcc }}</button></li>
|
||||
<li role="presentation" class="nav-item"><button class="nav-link" data-bs-toggle="tab" data-bs-target="#dfooter">{{ lang.edit.domain_footer }}</button></li>
|
||||
</ul>
|
||||
<hr class="d-none d-md-block">
|
||||
<div class="tab-content">
|
||||
<div id="dedit" class="tab-pane fade show active" role="tabpanel" aria-labelledby="domain-edit">
|
||||
<div class="card mb-4">
|
||||
<div class="card-header d-flex d-md-none fs-5">
|
||||
<button class="btn flex-grow-1 text-start" data-bs-target="#collapse-tab-dedit" data-bs-toggle="collapse" aria-controls="collapse-tab-dedit">
|
||||
{{ lang.edit.domain }} <span class="badge bg-info table-lines"></span>
|
||||
</button>
|
||||
</div>
|
||||
<div id="collapse-tab-dedit" class="card-body collapse show" data-bs-parent="#domain-content">
|
||||
<form data-id="editdomain" class="form-horizontal" role="form" method="post">
|
||||
<input type="hidden" value="0" name="active">
|
||||
<input type="hidden" value="0" name="backupmx">
|
||||
<input type="hidden" value="0" name="gal">
|
||||
<input type="hidden" value="0" name="relay_all_recipients">
|
||||
<input type="hidden" value="0" name="relay_unknown_only">
|
||||
<div class="row mb-4">
|
||||
<label class="control-label col-sm-2" for="domain">{{ lang.mailbox.domain }}</label>
|
||||
<div class="col-sm-10">
|
||||
<span class="d-block"><strong>{{ result.domain_h_name }}</strong></span>
|
||||
{% if result.domain_h_name != result.domain_name %}
|
||||
<small>{{ result.domain_name }}</small>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-2" data-acl="{{ acl.domain_desc }}">
|
||||
<label class="control-label col-sm-2" for="description">{{ lang.edit.description }}</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="text" class="form-control" name="description" value="{{ result.description }}">
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-4">
|
||||
<label class="control-label col-sm-2">{{ lang.add.tags }}</label>
|
||||
<div class="col-sm-10">
|
||||
<div class="form-control tag-box">
|
||||
{% for tag in domain_details.tags %}
|
||||
<span data-action='delete_selected' data-item="{{ tag|url_encode }}" data-id="domain_tag_{{ tag }}" data-api-url='delete/domain/tag/{{ domain }}' class="badge bg-primary tag-badge btn-badge">
|
||||
<i class="bi bi-tag-fill"></i>
|
||||
{{ tag }}
|
||||
</span>
|
||||
{% endfor %}
|
||||
<input type="text" class="tag-input">
|
||||
<span class="btn tag-add"><i class="bi bi-plus-lg"></i></span>
|
||||
<input type="hidden" value="" name="tags" class="tag-values" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-2">
|
||||
<label class="control-label col-sm-2" for="relayhost">{{ lang.edit.relayhost }}</label>
|
||||
<div class="col-sm-10">
|
||||
<select data-acl="{{ acl.domain_relayhost }}" data-live-search="true" id="relayhost" name="relayhost" class="form-control">
|
||||
{% for rlyhost in rlyhosts %}
|
||||
<option
|
||||
style="{% if rlyhost.active != '1' %}background: #ff4136; color: #fff{% endif %}"
|
||||
{% if result.relayhost == rlyhost.id %} selected{% endif %}
|
||||
value="{{ rlyhost.id }}">
|
||||
ID {{ rlyhost.id }}: {{ rlyhost.hostname }} ({{ rlyhost.username }})
|
||||
</option>
|
||||
{% endfor %}
|
||||
<option value=""{% if not result.relayhost %} selected{% endif %}>
|
||||
{{ lang.edit.none_inherit }}
|
||||
</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
{% if mailcow_cc_role == 'admin' %}
|
||||
<div class="row mb-2">
|
||||
<label class="control-label col-sm-2" for="aliases">{{ lang.edit.max_aliases }}</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="number" class="form-control" name="aliases" value="{{ result.max_num_aliases_for_domain }}">
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-2">
|
||||
<label class="control-label col-sm-2" for="mailboxes">{{ lang.edit.max_mailboxes }}</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="number" class="form-control" name="mailboxes" value="{{ result.max_num_mboxes_for_domain }}">
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-2">
|
||||
<label class="control-label col-sm-2" for="defquota">{{ lang.edit.mailbox_quota_def }}</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="number" class="form-control" name="defquota" value="{{ (result.def_quota_for_mbox / 1048576) }}">
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-2">
|
||||
<label class="control-label col-sm-2" for="maxquota">{{ lang.edit.max_quota }}</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="number" class="form-control" name="maxquota" value="{{ (result.max_quota_for_mbox / 1048576) }}">
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-4">
|
||||
<label class="control-label col-sm-2" for="quota">{{ lang.edit.domain_quota }}</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="number" class="form-control" name="quota" value="{{ (result.max_quota_for_domain / 1048576) }}">
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-2">
|
||||
<label class="control-label col-sm-2">{{ lang.edit.backup_mx_options }}</label>
|
||||
<div class="col-sm-10">
|
||||
<div class="form-check">
|
||||
<label><input type="checkbox" class="form-check-input" value="1" name="backupmx"{% if result.backupmx == '1' %} checked{% endif %}> {{ lang.edit.relay_domain }}</label>
|
||||
<br>
|
||||
<label><input type="checkbox" class="form-check-input" value="1" name="relay_all_recipients"{% if result.relay_all_recipients == '1' %} checked{% endif %}> {{ lang.edit.relay_all }}</label>
|
||||
<p>{{ lang.edit.relay_all_info|raw }}</p>
|
||||
<label><input type="checkbox" class="form-check-input" value="1" name="relay_unknown_only"{% if result.relay_unknown_only == '1' %} checked{% endif %}> {{ lang.edit.relay_unknown_only }}</label>
|
||||
<br>
|
||||
<p>{{ lang.edit.relay_transport_info|raw }}</p>
|
||||
<hr style="margin:25px 0px 0px 0px">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
<div class="row">
|
||||
<div class="offset-sm-2 col-sm-10">
|
||||
<div class="form-check">
|
||||
<label><input type="checkbox" class="form-check-input" value="1" name="gal"{% if result.gal == '1' %} checked{% endif %}> {{ lang.edit.gal }}</label>
|
||||
<small class="text-muted">{{ lang.edit.gal_info|raw }}</small>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<hr>
|
||||
<div class="row mb-2">
|
||||
<div class="offset-sm-2 col-sm-10">
|
||||
<div class="form-check">
|
||||
<label><input type="checkbox" class="form-check-input" value="1" name="active"{% if result.active == '1' %} checked{% endif %}{% if mailcow_cc_role != 'admin' %} disabled{% endif %}> {{ lang.edit.active }}</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-2">
|
||||
<div class="offset-sm-2 col-sm-10">
|
||||
<button class="btn btn-xs-lg d-block d-sm-inline btn-success" data-action="edit_selected" data-id="editdomain" data-item="{{ domain }}" data-api-url='edit/domain' data-api-attr='{}' href="#">{{ lang.admin.save }}</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="offset-sm-2 col-sm-10">
|
||||
<small class="fst-italic d-block">{{ lang.edit.created_on }}: {{ result.created }}</small>
|
||||
<small class="fst-italic d-block">{{ lang.edit.last_modified }}: {{ result.modified }}</small>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
{% if dkim %}
|
||||
<hr>
|
||||
<div class="row">
|
||||
<div class="col-12 col-sm-2">
|
||||
<p>{{ lang.add.domain }}: <strong>{{ result.domain_name }}</strong> ({{ dkim.dkim_selector }}._domainkey)</p>
|
||||
</div>
|
||||
<div class="col-12 col-sm-10">
|
||||
<pre class="p-2">{{ dkim.dkim_txt }}</pre>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="dratelimit" class="tab-pane fade" role="tabpanel" aria-labelledby="domain-ratelimit">
|
||||
<div class="card mb-4">
|
||||
<div class="card-header d-flex d-md-none fs-5">
|
||||
<button class="btn flex-grow-1 text-start" data-bs-target="#collapse-tab-ratelimit" data-bs-toggle="collapse" aria-controls="collapse-tab-ratelimit">
|
||||
{{ lang.edit.ratelimit }} <span class="badge bg-info table-lines"></span>
|
||||
</button>
|
||||
</div>
|
||||
<div id="collapse-tab-ratelimit" class="card-body collapse" data-bs-parent="#domain-content">
|
||||
<form data-id="domratelimit" class="well" method="post">
|
||||
<div class="row mb-2">
|
||||
<label class="control-label col-sm-2">{{ lang.edit.ratelimit }}</label>
|
||||
<div class="col-sm-10">
|
||||
<div class="input-group">
|
||||
<input name="rl_value" type="number" value="{{ rl.value }}" autocomplete="off" class="form-control" placeholder="{{ lang.ratelimit.disabled }}">
|
||||
<select name="rl_frame" class="form-control">
|
||||
{% include 'mailbox/rl-frame.twig' %}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-2">
|
||||
<div class="offset-sm-2 col-sm-10">
|
||||
<button data-acl="{{ acl.ratelimit }}" class="btn btn-xs-lg d-block d-sm-inline btn-secondary" data-action="edit_selected" data-id="domratelimit" data-item="{{ domain }}" data-api-url='edit/rl-domain' data-api-attr='{}' href="#">{{ lang.admin.save }}</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="dspamfilter" class="tab-pane fade" role="tabpanel" aria-labelledby="domain-spamfilter">
|
||||
<div class="card mb-4">
|
||||
<div class="card-header d-flex d-md-none fs-5">
|
||||
<button class="btn flex-grow-1 text-start" data-bs-target="#collapse-tab-spamfilter" data-bs-toggle="collapse" aria-controls="collapse-tab-spamfilter">
|
||||
{{ lang.edit.spam_filter }} <span class="badge bg-info table-lines"></span>
|
||||
</button>
|
||||
</div>
|
||||
<div id="collapse-tab-spamfilter" class="card-body collapse" data-bs-parent="#domain-content">
|
||||
<div class="row">
|
||||
<div class="col-sm-6">
|
||||
<h4>{{ lang.user.spamfilter_wl }}</h4>
|
||||
<p>{{ lang.user.spamfilter_wl_desc|raw }}</p>
|
||||
<form class="form-inline mb-4" data-id="add_wl_policy_domain">
|
||||
<div class="input-group" data-acl="{{ acl.spam_policy }}">
|
||||
<input type="text" class="form-control" name="object_from" placeholder="*@example.org" required>
|
||||
<button class="btn btn-secondary" data-action="add_item" data-id="add_wl_policy_domain" data-api-url='add/domain-policy' data-api-attr='{"domain":"{{ domain }}","object_list":"wl"}' href="#">{{ lang.user.spamfilter_table_add }}</button>
|
||||
</div>
|
||||
</form>
|
||||
<table id="wl_policy_domain_table" class="table table-striped dt-responsive w-100"></table>
|
||||
<div class="mass-actions-user">
|
||||
<div class="btn-group" data-acl="{{ acl.spam_policy }}">
|
||||
<a class="btn btn-xs-half d-block d-sm-inline btn-sm btn-secondary" id="toggle_multi_select_all" data-id="policy_wl_domain" href="#"><i class="bi bi-check-all"></i> {{ lang.mailbox.toggle_all }}</a>
|
||||
<a class="btn btn-xs-half d-block d-sm-inline btn-sm btn-danger" data-action="delete_selected" data-id="policy_wl_domain" data-api-url='delete/domain-policy' href="#">{{ lang.mailbox.remove }}</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-6">
|
||||
<h4>{{ lang.user.spamfilter_bl }}</h4>
|
||||
<p>{{ lang.user.spamfilter_bl_desc|raw }}</p>
|
||||
<form class="form-inline mb-4" data-id="add_bl_policy_domain">
|
||||
<div class="input-group" data-acl="{{ acl.spam_policy }}">
|
||||
<input type="text" class="form-control" name="object_from" placeholder="*@example.org" required>
|
||||
<button class="btn btn-secondary" data-action="add_item" data-id="add_bl_policy_domain" data-api-url='add/domain-policy' data-api-attr='{"domain":"{{ domain }}","object_list":"bl"}' href="#">{{ lang.user.spamfilter_table_add }}</button>
|
||||
</div>
|
||||
</form>
|
||||
<table id="bl_policy_domain_table" class="table table-striped dt-responsive w-100"></table>
|
||||
<div class="mass-actions-user">
|
||||
<div class="btn-group" data-acl="{{ acl.spam_policy }}">
|
||||
<a class="btn btn-xs-half d-block d-sm-inline btn-sm btn-secondary" id="toggle_multi_select_all" data-id="policy_bl_domain" href="#"><i class="bi bi-check-all"></i> {{ lang.mailbox.toggle_all }}</a>
|
||||
<a class="btn btn-xs-half d-block d-sm-inline btn-sm btn-danger" data-action="delete_selected" data-id="policy_bl_domain" data-api-url='delete/domain-policy' href="#">{{ lang.mailbox.remove }}</a></li>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="dqwbcc" class="tab-pane fade" role="tabpanel" aria-labelledby="domain-qwbcc">
|
||||
<div class="card mb-4">
|
||||
<div class="card-header d-flex d-md-none fs-5">
|
||||
<button class="btn flex-grow-1 text-start" data-bs-target="#collapse-tab-qwbcc" data-bs-toggle="collapse" aria-controls="collapse-tab-qwbcc">
|
||||
{{ lang.edit.quota_warning_bcc }} <span class="badge bg-info table-lines"></span>
|
||||
</button>
|
||||
</div>
|
||||
<div id="collapse-tab-qwbcc" class="card-body collapse" data-bs-parent="#domain-content">
|
||||
<div class="row">
|
||||
<div class="col-sm-12">
|
||||
<h4>{{ lang.edit.quota_warning_bcc }}</h4>
|
||||
<p>{{ lang.edit.quota_warning_bcc_info|raw }}</p>
|
||||
<form class="form-horizontal" data-id="quota_bcc">
|
||||
<input type="hidden" value="0" name="active">
|
||||
<div class="row mb-2">
|
||||
<label class="control-label col-sm-2" for="script_data">{{ lang.edit.target_address|raw }}:</label>
|
||||
<div class="col-sm-10">
|
||||
<textarea spellcheck="false" autocorrect="off" autocapitalize="none" class="form-control" rows="10" id="bcc_rcpt" name="bcc_rcpt">{{ quota_notification_bcc.bcc_rcpts|join("\n") }}</textarea>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-4">
|
||||
<div class="offset-sm-2 col-sm-10">
|
||||
<div class="form-check">
|
||||
<label><input type="checkbox" class="form-check-input" value="1" name="active"{% if quota_notification_bcc.active == '1' %} checked{% endif %}> {{ lang.edit.active }}</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="offset-sm-2 col-sm-10">
|
||||
<button class="btn btn-xs-lg d-block d-sm-inline btn-success" data-action="edit_selected" data-id="quota_bcc" data-item="quota_bcc" data-api-url='edit/quota_notification_bcc' data-api-attr='{"domain":"{{ domain }}"}' href="#">{{ lang.edit.save }}</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="dfooter" class="tab-pane fade" role="tabpanel" aria-labelledby="domain-footer">
|
||||
<div class="card mb-4">
|
||||
<div class="card-header d-flex d-md-none fs-5">
|
||||
<button class="btn flex-grow-1 text-start" data-bs-target="#collapse-tab-footer" data-bs-toggle="collapse" aria-controls="collapse-tab-footer">
|
||||
{{ lang.edit.domain_footer }} <span class="badge bg-info table-lines"></span>
|
||||
</button>
|
||||
</div>
|
||||
<div id="collapse-tab-footer" class="card-body collapse" data-bs-parent="#domain-content">
|
||||
<div class="row">
|
||||
<div class="col-sm-12">
|
||||
<h4>{{ lang.edit.domain_footer }}</h4>
|
||||
<p>{{ lang.edit.domain_footer_info|raw }}</p>
|
||||
<pre>{{ lang.edit.domain_footer_info_vars.auth_user }}
|
||||
{{ lang.edit.domain_footer_info_vars.from_user }}
|
||||
{{ lang.edit.domain_footer_info_vars.from_name }}
|
||||
{{ lang.edit.domain_footer_info_vars.from_addr }}
|
||||
{{ lang.edit.domain_footer_info_vars.from_domain }}
|
||||
{{ lang.edit.domain_footer_info_vars.custom }}</pre>
|
||||
<form class="form-horizontal mt-4" data-id="domain_footer">
|
||||
<div class="row mb-4">
|
||||
<label class="control-label col-sm-2" for="exclude">{{ lang.edit.footer_exclude }}</label>
|
||||
<div class="col-sm-10">
|
||||
<select data-live-search="true" data-width="100%" style="width:100%" id="editFooterExclude" name="exclude" size="10" multiple>
|
||||
{% for mailbox in mailboxes %}
|
||||
<option value="{{ mailbox }}" {% if mailbox in domain_footer.mbox_exclude %}selected{% endif %}>
|
||||
{{ mailbox }}
|
||||
</option>
|
||||
{% endfor %}
|
||||
{% for alias in aliases %}
|
||||
<option data-subtext="Alias" value="{{ alias }}" {% if alias in domain_footer.mbox_exclude %}selected{% endif %}>
|
||||
{{ alias }}
|
||||
</option>
|
||||
{% endfor %}
|
||||
{% for alias_domain in alias_domains %}
|
||||
<option data-subtext="Alias-Domain" value="{{ alias_domain }}" {% if alias_domain in domain_footer.alias_domain_exclude %}selected{% endif %}>
|
||||
{{ alias_domain }}
|
||||
</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-4">
|
||||
<label class="control-label col-sm-2" for="domain_footer_skip_replies">{{ lang.edit.domain_footer_skip_replies }}:</label>
|
||||
<div class="col-sm-10">
|
||||
<div class="form-check">
|
||||
<label><input type="checkbox" class="form-check-input" value="1" id="domain_footer_skip_replies" name="skip_replies"{% if domain_footer.skip_replies == '1' %} checked{% endif %}></label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-2">
|
||||
<label class="control-label col-sm-2" for="domain_footer_html">{{ lang.edit.domain_footer_html }}:</label>
|
||||
<div class="col-sm-10">
|
||||
<textarea spellcheck="false" autocorrect="off" autocapitalize="none" class="form-control" rows="10" id="domain_footer_html" name="html">{{ domain_footer.html }}</textarea>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-4">
|
||||
<label class="control-label col-sm-2" for="domain_footer_plain">{{ lang.edit.domain_footer_plain }}:</label>
|
||||
<div class="col-sm-10">
|
||||
<textarea spellcheck="false" autocorrect="off" autocapitalize="none" class="form-control" rows="10" id="domain_footer_plain" name="plain">{{ domain_footer.plain }}</textarea>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="offset-sm-2 col-sm-10">
|
||||
<button class="btn btn-xs-lg d-block d-sm-inline btn-success" data-action="edit_selected" data-id="domain_footer" data-item="{{ domain }}" data-api-url='edit/domain/footer' data-api-attr='{}' href="#">{{ lang.edit.save }}</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% else %}
|
||||
{{ parent() }}
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
79
data/web/templates/edit/domainadmin.twig
Executable file
79
data/web/templates/edit/domainadmin.twig
Executable file
|
|
@ -0,0 +1,79 @@
|
|||
{% extends 'edit.twig' %}
|
||||
|
||||
{% block inner_content %}
|
||||
{% if result %}
|
||||
<h4>{{ lang.edit.domain_admin }}</h4>
|
||||
<br>
|
||||
<form class="form-horizontal" data-id="editdomainadmin" role="form" method="post" autocomplete="off">
|
||||
<input type="hidden" value="0" name="active">
|
||||
<div class="row mb-2">
|
||||
<label class="control-label col-sm-2" for="username_new">{{ lang.edit.username }}</label>
|
||||
<div class="col-sm-10">
|
||||
<input class="form-control" type="text" name="username_new" value="{{ domain_admin }}" required onkeyup="this.value = this.value.toLowerCase();" />
|
||||
↳ <kbd>a-z - _ .</kbd>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-4">
|
||||
<label class="control-label col-sm-2" for="domains">{{ lang.edit.domains }}</label>
|
||||
<div class="col-sm-10">
|
||||
<select data-live-search="true" class="full-width-select" name="domains" multiple required>
|
||||
{% for domain in result.selected_domains %}
|
||||
<option selected>{{ domain }}</option>
|
||||
{% endfor %}
|
||||
{% for domain in result.unselected_domains %}
|
||||
<option>{{ domain }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-2">
|
||||
<label class="control-label col-sm-2" for="password">{{ lang.edit.password }} (<a href="#" class="generate_password">{{ lang.edit.generate }}</a>)</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="password" data-pwgen-field="true" data-hibp="true" class="form-control" name="password" placeholder="" autocomplete="new-password">
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-4">
|
||||
<label class="control-label col-sm-2" for="password2">{{ lang.edit.password_repeat }}</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="password" data-pwgen-field="true" class="form-control" name="password2" autocomplete="new-password">
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-2">
|
||||
<div class="offset-sm-2 col-sm-10">
|
||||
<div class="form-check">
|
||||
<label><input type="checkbox" class="form-check-input" value="1" name="active"{% if result.active == '1' %} checked{% endif %}> {{ lang.edit.active }}</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-2">
|
||||
<div class="offset-sm-2 col-sm-10">
|
||||
<div class="form-check">
|
||||
<label><input type="checkbox" class="form-check-input" value="1" name="disable_tfa"> {{ lang.tfa.disable_tfa }}</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-4">
|
||||
<div class="offset-sm-2 col-sm-10">
|
||||
<button class="btn btn-xs-lg d-block d-sm-inline btn-success" data-action="edit_selected" data-api-reload-location="/admin" data-id="editdomainadmin" data-item="{{ domain_admin }}" data-api-url='edit/domain-admin' data-api-attr='{}' href="#">{{ lang.edit.save }}</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
<form data-id="daacl" class="form-inline well" method="post">
|
||||
<div class="row">
|
||||
<div class="col-sm-1">
|
||||
<p class="text-muted">ACL</p>
|
||||
</div>
|
||||
<div class="col-sm-10">
|
||||
<select class="mb-2" id="da_acl" name="da_acl" size="10" data-container="body" multiple>
|
||||
{% for acl, val in da_acls %}
|
||||
<option value="{{ acl }}"{% if val == 1 %} selected{% endif %}>{{ lang.acl[acl] }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
<button class="btn btn-xs-lg d-block d-sm-inline btn-secondary mb-2" data-action="edit_selected" data-id="daacl" data-item="{{ domain_admin }}" data-api-url='edit/da-acl' data-api-attr='{}' href="#">{{ lang.admin.save }}</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
{% else %}
|
||||
{{ parent() }}
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
45
data/web/templates/edit/filter.twig
Executable file
45
data/web/templates/edit/filter.twig
Executable file
|
|
@ -0,0 +1,45 @@
|
|||
{% extends 'edit.twig' %}
|
||||
|
||||
{% block inner_content %}
|
||||
{% if result %}
|
||||
<h4>Filter</h4>
|
||||
<form class="form-horizontal" data-id="editfilter" role="form" method="post">
|
||||
<input type="hidden" value="0" name="active">
|
||||
<div class="row mb-2">
|
||||
<label class="control-label col-sm-2" for="script_desc">{{ lang.edit.sieve_desc }}</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="text" class="form-control" name="script_desc" id="script_desc" value="{{ result.script_desc }}" required maxlength="255">
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-2">
|
||||
<label class="control-label col-sm-2" for="filter_type">{{ lang.edit.sieve_type }}</label>
|
||||
<div class="col-sm-10">
|
||||
<select id="addFilterType" name="filter_type" id="filter_type" required>
|
||||
<option value="prefilter"{% if result.filter_type == 'prefilter' %} selected{% endif %}>Prefilter</option>
|
||||
<option value="postfilter"{% if result.filter_type == 'postfilter' %} selected{% endif %}>Postfilter</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-4">
|
||||
<label class="control-label col-sm-2" for="script_data">Script:</label>
|
||||
<div class="col-sm-10">
|
||||
<textarea spellcheck="false" autocorrect="off" autocapitalize="none" class="form-control textarea-code" rows="20" id="script_data" name="script_data" required>{{ result.script_data|raw }}</textarea>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-2">
|
||||
<div class="offset-sm-2 col-sm-10">
|
||||
<div class="form-check">
|
||||
<label><input type="checkbox" class="form-check-input" value="1" name="active"{% if result.active == '1' %} checked{% endif %}> {{ lang.edit.active }}</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-2">
|
||||
<div class="offset-sm-2 col-sm-10">
|
||||
<button class="btn btn-xs-lg d-block d-sm-inline btn-success" data-action="edit_selected" data-id="editfilter" data-item="{{ result.id }}" data-api-url='edit/filter' data-api-attr='{}' href="#">{{ lang.edit.validate_save }}</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
{% else %}
|
||||
{{ parent() }}
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
169
data/web/templates/edit/mailbox-templates.twig
Executable file
169
data/web/templates/edit/mailbox-templates.twig
Executable file
|
|
@ -0,0 +1,169 @@
|
|||
{% extends 'edit.twig' %}
|
||||
|
||||
{% block inner_content %}
|
||||
{% if result %}
|
||||
<hr>
|
||||
<div id="medit" class="tab-pane fade show active" role="tabpanel" aria-labelledby="mailbox-edit">
|
||||
<form class="form-horizontal" data-id="editmailbox_template" role="form" method="post">
|
||||
|
||||
<input type="hidden" value="default" name="sender_acl">
|
||||
<input type="hidden" value="0" name="force_pw_update">
|
||||
<input type="hidden" value="0" name="sogo_access">
|
||||
<input type="hidden" value="0" name="protocol_access">
|
||||
|
||||
<div class="row mb-4">
|
||||
<label class="control-label col-sm-2" for="template">{{ lang.mailbox.template }}</label>
|
||||
<div class="col-sm-10">
|
||||
<div class="input-group mb-3">
|
||||
<input type="text" name="template" class="form-control" aria-label="Text input with dropdown button" value="{{ template.template }}" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-2">
|
||||
<label class="control-label col-sm-2">{{ lang.add.tags }}</label>
|
||||
<div class="col-sm-10">
|
||||
<div class="form-control tag-box">
|
||||
<input id="tags" type="text" class="tag-input">
|
||||
<span class="btn tag-add"><i class="bi bi-plus-lg"></i></span>
|
||||
<input type="hidden" value='{{ template.attributes.tags|json_encode }}' name="tags" class="tag-values" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-2">
|
||||
<label class="control-label col-sm-2" for="quota">{{ lang.edit.quota_mb }}</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="number" name="quota" class="w-100 form-control" min="0" value="{{ template.attributes.quota / 1048576 }}">
|
||||
<small class="text-muted">0 = ∞</small>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-2">
|
||||
<label class="control-label col-sm-2">{{ lang.user.quarantine_notification }}</label>
|
||||
<div class="col-sm-10">
|
||||
<div class="btn-group">
|
||||
<input type="radio" class="btn-check" name="quarantine_notification" id="quarantine_notification_never" autocomplete="off" value="never" {% if template.attributes.quarantine_notification == 'never' %}checked{% endif %}>
|
||||
<label class="btn btn-sm btn-xs-quart d-block d-sm-inline btn-light" for="quarantine_notification_never">{{ lang.user.never }}</label>
|
||||
|
||||
<input type="radio" class="btn-check" name="quarantine_notification" id="quarantine_notification_hourly" autocomplete="off" value="hourly" {% if template.attributes.quarantine_notification == 'hourly' %}checked{% endif %}>
|
||||
<label class="btn btn-sm btn-xs-quart d-block d-sm-inline btn-light" for="quarantine_notification_hourly">{{ lang.user.hourly }}</label>
|
||||
|
||||
<input type="radio" class="btn-check" name="quarantine_notification" id="quarantine_notification_daily" autocomplete="off" value="daily" {% if template.attributes.quarantine_notification == 'daily' %}checked{% endif %}>
|
||||
<label class="btn btn-sm btn-xs-quart d-block d-sm-inline btn-light" for="quarantine_notification_daily">{{ lang.user.daily }}</label>
|
||||
|
||||
<input type="radio" class="btn-check" name="quarantine_notification" id="quarantine_notification_weekly" autocomplete="off" value="weekly" {% if template.attributes.quarantine_notification == 'weekly' %}checked{% endif %}>
|
||||
<label class="btn btn-sm btn-xs-quart d-block d-sm-inline btn-light" for="quarantine_notification_weekly">{{ lang.user.weekly }}</label>
|
||||
</div>
|
||||
<p class="text-muted"><small>{{ lang.user.quarantine_notification_info }}</small></p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-2">
|
||||
<label class="control-label col-sm-2">{{ lang.user.quarantine_category }}</label>
|
||||
<div class="col-sm-10">
|
||||
<div class="btn-group">
|
||||
<input type="radio" class="btn-check" name="quarantine_category" id="quarantine_category_reject" autocomplete="off" value="reject" {% if template.attributes.quarantine_category == 'reject' %}checked{% endif %}>
|
||||
<label class="btn btn-sm btn-xs-quart d-block d-sm-inline btn-light" for="quarantine_category_reject">{{ lang.user.q_reject }}</label>
|
||||
|
||||
<input type="radio" class="btn-check" name="quarantine_category" id="quarantine_category_add_header" autocomplete="off" value="add_header" {% if template.attributes.quarantine_category == 'add_header' %}checked{% endif %}>
|
||||
<label class="btn btn-sm btn-xs-quart d-block d-sm-inline btn-light" for="quarantine_category_add_header">{{ lang.user.q_add_header }}</label>
|
||||
|
||||
<input type="radio" class="btn-check" name="quarantine_category" id="quarantine_category_all" autocomplete="off" value="all" {% if template.attributes.quarantine_category == 'all' %}checked{% endif %}>
|
||||
<label class="btn btn-sm btn-xs-quart d-block d-sm-inline btn-light" for="quarantine_category_all">{{ lang.user.q_all }}</label>
|
||||
</div>
|
||||
<p class="text-muted"><small>{{ lang.user.quarantine_category_info }}</small></p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-4">
|
||||
<label class="control-label col-sm-2" for="sender_acl">{{ lang.user.tls_policy }}</label>
|
||||
<div class="col-sm-10">
|
||||
<div class="btn-group">
|
||||
<input type="checkbox" class="btn-check" name="tls_enforce_in" id="tls_enforce_in" autocomplete="off" value="1" {% if template.attributes.tls_enforce_in == '1' %}checked{% endif %}>
|
||||
<label class="btn btn-sm btn-xs-quart d-block d-sm-inline btn-light" for="tls_enforce_in">{{ lang.user.tls_enforce_in }}</label>
|
||||
|
||||
<input type="checkbox" class="btn-check" name="tls_enforce_out" id="tls_enforce_out" autocomplete="off" value="1" {% if template.attributes.tls_enforce_out == '1' %}checked{% endif %}>
|
||||
<label class="btn btn-sm btn-xs-quart d-block d-sm-inline btn-light" for="tls_enforce_out">{{ lang.user.tls_enforce_out }}</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-2">
|
||||
<label class="control-label col-sm-2" for="protocol_access">{{ lang.edit.allowed_protocols }}</label>
|
||||
<div class="col-sm-10">
|
||||
<select name="protocol_access" multiple class="form-control">
|
||||
<option value="imap"{% if template.attributes.imap_access == '1' %} selected{% endif %}>IMAP</option>
|
||||
<option value="pop3"{% if template.attributes.pop3_access == '1' %} selected{% endif %}>POP3</option>
|
||||
<option value="smtp"{% if template.attributes.smtp_access == '1' %} selected{% endif %}>SMTP</option>
|
||||
<option value="sieve"{% if template.attributes.sieve_access == '1' %} selected{% endif %}>Sieve</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-4">
|
||||
<label class="control-label col-sm-2">ACL</label>
|
||||
<div class="col-sm-10">
|
||||
<select id="template_user_acl" name="acl" size="10" multiple class="form-control">
|
||||
<option value="spam_alias" {% if template.attributes.acl_spam_alias == '1' %} selected{% endif %}>{{ lang.acl["spam_alias"] }}</option>
|
||||
<option value="tls_policy" {% if template.attributes.acl_tls_policy == '1' %} selected{% endif %}>{{ lang.acl["tls_policy"] }}</option>
|
||||
<option value="spam_score" {% if template.attributes.acl_spam_score == '1' %} selected{% endif %}>{{ lang.acl["spam_score"] }}</option>
|
||||
<option value="spam_policy" {% if template.attributes.acl_spam_policy == '1' %} selected{% endif %}>{{ lang.acl["spam_policy"] }}</option>
|
||||
<option value="delimiter_action" {% if template.attributes.acl_delimiter_action == '1' %} selected{% endif %}>{{ lang.acl["delimiter_action"] }}</option>
|
||||
<option value="syncjobs" {% if template.attributes.acl_syncjobs == '1' %} selected{% endif %}>{{ lang.acl["syncjobs"] }}</option>
|
||||
<option value="eas_reset" {% if template.attributes.acl_eas_reset == '1' %} selected{% endif %}>{{ lang.acl["eas_reset"] }}</option>
|
||||
<option value="sogo_profile_reset" {% if template.attributes.acl_sogo_profile_reset == '1' %} selected{% endif %}>{{ lang.acl["sogo_profile_reset"] }}</option>
|
||||
<option value="pushover" {% if template.attributes.acl_pushover == '1' %} selected{% endif %}>{{ lang.acl["pushover"] }}</option>
|
||||
<option value="quarantine" {% if template.attributes.acl_quarantine == '1' %} selected{% endif %}>{{ lang.acl["quarantine"] }}</option>
|
||||
<option value="quarantine_attachments" {% if template.attributes.acl_quarantine_attachments == '1' %} selected{% endif %}>{{ lang.acl["quarantine_attachments"] }}</option>
|
||||
<option value="quarantine_notification" {% if template.attributes.acl_quarantine_notification == '1' %} selected{% endif %}>{{ lang.acl["quarantine_notification"] }}</option>
|
||||
<option value="quarantine_category" {% if template.attributes.acl_quarantine_category == '1' %} selected{% endif %}>{{ lang.acl["quarantine_category"] }}</option>
|
||||
<option value="app_passwds" {% if template.attributes.acl_app_passwds == '1' %} selected{% endif %}>{{ lang.acl["app_passwds"] }}</option>
|
||||
<option value="pw_reset" {% if template.attributes.acl_pw_reset == '1' %} selected{% endif %}>{{ lang.acl["pw_reset"] }}</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-4">
|
||||
<label class="control-label col-sm-2">{{ lang.acl.ratelimit }}</label>
|
||||
<div class="col-sm-10">
|
||||
<div class="input-group">
|
||||
<input name="rl_value" type="number" autocomplete="off" value="{{ template.attributes.rl_value }}" class="form-control mb-2" placeholder="{{ lang.ratelimit.disabled }}">
|
||||
<select name="rl_frame" class="form-control">
|
||||
{% include 'mailbox/rl-frame.twig' %}
|
||||
</select>
|
||||
</div>
|
||||
<p class="text-muted mt-1">{{ lang.edit.mbox_rl_info }}</p>
|
||||
</div>
|
||||
</div>
|
||||
<hr>
|
||||
<div class="row my-2">
|
||||
<div class="offset-sm-2 col-sm-10">
|
||||
<select name="active" class="form-control">
|
||||
<option value="1"{% if template.attributes.active == '1' %} selected{% endif %}>{{ lang.edit.active }}</option>
|
||||
<option value="2"{% if template.attributes.active == '2' %} selected{% endif %}>{{ lang.edit.disable_login }}</option>
|
||||
<option value="0"{% if template.attributes.active == '0' %} selected{% endif %}>{{ lang.edit.inactive }}</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="offset-sm-2 col-sm-10">
|
||||
<div class="form-check">
|
||||
<label><input type="checkbox" class="form-check-input" value="1" name="force_pw_update"{% if template.attributes.force_pw_update == '1' %} checked{% endif %}> {{ lang.edit.force_pw_update }}</label>
|
||||
<small class="text-muted">{{ lang.edit.force_pw_update_info|format(ui_texts.main_name) }}</small>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% if not skip_sogo %}
|
||||
<div class="row">
|
||||
<div class="offset-sm-2 col-sm-10">
|
||||
<div class="form-check">
|
||||
<label><input type="checkbox" class="form-check-input" value="1" name="sogo_access"{% if template.attributes.sogo_access == '1' %} checked{% endif %}> {{ lang.edit.sogo_access }}</label>
|
||||
<small class="text-muted">{{ lang.edit.sogo_access_info }}</small>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
<div class="row my-2">
|
||||
<div class="offset-sm-2 col-sm-10">
|
||||
<button class="btn btn-xs-lg d-block d-sm-inline btn-success" data-action="edit_selected" data-id="editmailbox_template" data-item="{{ template.id }}" data-api-url='edit/mailbox/template' data-api-attr='{}' href="#">{{ lang.edit.save }}</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
{% else %}
|
||||
{{ parent() }}
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
485
data/web/templates/edit/mailbox.twig
Executable file
485
data/web/templates/edit/mailbox.twig
Executable file
|
|
@ -0,0 +1,485 @@
|
|||
{% extends 'edit.twig' %}
|
||||
|
||||
{% block inner_content %}
|
||||
{% if result %}
|
||||
<div id="mailbox-content" class="responsive-tabs">
|
||||
<ul class="nav nav-tabs" role="tablist">
|
||||
<li role="presentation" class="nav-item"><button class="nav-link active" data-bs-toggle="tab" data-bs-target="#medit">{{ lang.edit.mailbox }}</button></li>
|
||||
<li role="presentation" class="nav-item"><button class="nav-link" data-bs-toggle="tab" data-bs-target="#mattr">{{ lang.edit.custom_attributes }}</button></li>
|
||||
<li role="presentation" class="nav-item"><button class="nav-link" data-bs-toggle="tab" data-bs-target="#mpushover">{{ lang.edit.pushover }}</button></li>
|
||||
<li role="presentation" class="nav-item"><button class="nav-link" data-bs-toggle="tab" data-bs-target="#macl">{{ lang.edit.acl }}</button></li>
|
||||
<li role="presentation" class="nav-item"><button class="nav-link" data-bs-toggle="tab" data-bs-target="#mrl">{{ lang.edit.ratelimit }}</button></li>
|
||||
</ul>
|
||||
<hr class="d-none d-md-block">
|
||||
<div class="tab-content">
|
||||
<div id="medit" class="tab-pane fade show active" role="tabpanel" aria-labelledby="mailbox-edit">
|
||||
<div class="card mb-4">
|
||||
<div class="card-header d-flex d-md-none fs-5">
|
||||
<button class="btn flex-grow-1 text-start" data-bs-target="#collapse-tab-medit" data-bs-toggle="collapse" aria-controls="collapse-tab-medit">
|
||||
{{ lang.edit.mailbox }} <span class="badge bg-info table-lines"></span>
|
||||
</button>
|
||||
</div>
|
||||
<div id="collapse-tab-medit" class="card-body collapse show" data-bs-parent="#mailbox-content">
|
||||
<form class="form-horizontal" data-id="editmailbox" role="form" method="post">
|
||||
<input type="hidden" value="default" name="sender_acl">
|
||||
<input type="hidden" value="0" name="force_pw_update">
|
||||
<input type="hidden" value="0" name="sogo_access">
|
||||
<input type="hidden" value="0" name="protocol_access">
|
||||
<div class="row mb-2">
|
||||
<label class="control-label col-sm-2" for="name">{{ lang.edit.full_name }}</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="text" class="form-control" name="name" value="{{ result.name }}">
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-4">
|
||||
<label class="control-label col-sm-2">{{ lang.add.tags }}</label>
|
||||
<div class="col-sm-10">
|
||||
<div class="form-control tag-box">
|
||||
{% for tag in mailbox_details.tags %}
|
||||
<span data-action='delete_selected' data-item="{{ tag }}" data-id="mailbox_tag_{{ tag }}" data-api-url='delete/mailbox/tag/{{ mailbox }}' class="badge bg-primary tag-badge btn-badge">
|
||||
<i class="bi bi-tag-fill"></i>
|
||||
{{ tag }}
|
||||
</span>
|
||||
{% endfor %}
|
||||
<input type="text" class="tag-input">
|
||||
<span class="btn tag-add"><i class="bi bi-plus-lg"></i></span>
|
||||
<input type="hidden" value="" name="tags" class="tag-values" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-2">
|
||||
<label class="control-label col-sm-2" for="quota">{{ lang.edit.quota_mb }}
|
||||
<br><span id="quotaBadge" class="badge bg-info">max. {{ (result.max_new_quota / 1048576) }} MiB</span>
|
||||
</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="number" name="quota" style="width:100%" min="0" max="{{ (result.max_new_quota / 1048576) }}" value="{{ (result.quota / 1048576) }}" class="form-control">
|
||||
<small class="text-muted">0 = ∞</small>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-2">
|
||||
<label class="control-label col-sm-2" for="sender_acl">{{ lang.edit.sender_acl }}</label>
|
||||
<div class="col-sm-10">
|
||||
<select data-live-search="true" data-width="100%" style="width:100%" id="editSelectSenderACL" name="sender_acl" size="10" multiple>
|
||||
{% for domain in sender_acl_handles.sender_acl_domains.ro %}
|
||||
<option data-subtext="Admin" value="{{ domain }}" disabled selected>
|
||||
{{ lang.edit.dont_check_sender_acl|format(domain) }}
|
||||
</option>
|
||||
{% endfor %}
|
||||
{% for alias in sender_acl_handles.sender_acl_addresses.ro %}
|
||||
<option data-subtext="Admin" disabled selected>
|
||||
{{ alias }}
|
||||
</option>
|
||||
{% endfor %}
|
||||
{% for alias in sender_acl_handles.fixed_sender_aliases %}
|
||||
<option data-subtext="Alias" disabled selected>{{ alias }}</option>
|
||||
{% endfor %}
|
||||
{% for domain in sender_acl_handles.sender_acl_domains.rw %}
|
||||
<option value="{{ domain }}" selected>
|
||||
{{ lang.edit.dont_check_sender_acl|format(domain) }}
|
||||
</option>
|
||||
{% endfor %}
|
||||
{% for domain in sender_acl_handles.sender_acl_domains.selectable %}
|
||||
<option value="{{ domain }}">
|
||||
{{ lang.edit.dont_check_sender_acl|format(domain) }}
|
||||
</option>
|
||||
{% endfor %}
|
||||
{% for address in sender_acl_handles.sender_acl_addresses.rw %}
|
||||
<option selected>{{ address }}</option>
|
||||
{% endfor %}
|
||||
{% for address in sender_acl_handles.sender_acl_addresses.selectable %}
|
||||
<option>{{ address }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
<div id="sender_acl_disabled"><i class="bi bi-shield-exclamation"></i> {{ lang.edit.sender_acl_disabled|raw }}</div>
|
||||
<small class="text-muted d-block">{{ lang.edit.sender_acl_info|raw }}</small>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-2">
|
||||
<label class="control-label col-sm-2" for="relayhost">{{ lang.edit.relayhost }}</label>
|
||||
<div class="col-sm-10">
|
||||
<select data-acl="{{ acl.mailbox_relayhost }}" data-live-search="true" id="relayhost" name="relayhost" class="form-control mb-4">
|
||||
{% for rlyhost in rlyhosts %}
|
||||
<option
|
||||
style="{% if rlyhost.active != '1' %}background: #ff4136; color: #fff{% endif %}"
|
||||
{% if result.attributes.relayhost == rlyhost.id %} selected{% endif %}
|
||||
value="{{ rlyhost.id }}">
|
||||
ID {{ rlyhost.id }}: {{ rlyhost.hostname }} ({{ rlyhost.username }})
|
||||
</option>
|
||||
{% endfor %}
|
||||
<option value=""{% if not result.attributes.relayhost %} selected{% endif %}>
|
||||
{{ lang.edit.none_inherit }}
|
||||
</option>
|
||||
</select>
|
||||
<p class="d-block d-sm-none" style="margin: 0;padding: 0"> </p>
|
||||
<small class="text-muted d-block">{{ lang.edit.mailbox_relayhost_info }}</small>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-2">
|
||||
<label class="control-label col-sm-2">{{ lang.user.quarantine_notification }}</label>
|
||||
<div class="col-sm-10">
|
||||
<div class="btn-group" data-acl="{{ acl.quarantine_notification }}">
|
||||
<button type="button" class="btn btn-sm btn-xs-quart d-block d-sm-inline{% if quarantine_notification == 'never' %} btn-dark{% else %} btn-light{% endif %}"
|
||||
data-action="edit_selected"
|
||||
data-item="{{ mailbox }}"
|
||||
data-id="quarantine_notification"
|
||||
data-api-url='edit/quarantine_notification'
|
||||
data-api-attr='{"quarantine_notification":"never"}'>{{ lang.user.never }}</button>
|
||||
<button type="button" class="btn btn-sm btn-xs-quart d-block d-sm-inline{% if quarantine_notification == 'hourly' %} btn-dark{% else %} btn-light{% endif %}"
|
||||
data-action="edit_selected"
|
||||
data-item="{{ mailbox }}"
|
||||
data-id="quarantine_notification"
|
||||
data-api-url='edit/quarantine_notification'
|
||||
data-api-attr='{"quarantine_notification":"hourly"}'>{{ lang.user.hourly }}</button>
|
||||
<button type="button" class="btn btn-sm btn-xs-quart d-block d-sm-inline{% if quarantine_notification == 'daily' %} btn-dark{% else %} btn-light{% endif %}"
|
||||
data-action="edit_selected"
|
||||
data-item="{{ mailbox }}"
|
||||
data-id="quarantine_notification"
|
||||
data-api-url='edit/quarantine_notification'
|
||||
data-api-attr='{"quarantine_notification":"daily"}'>{{ lang.user.daily }}</button>
|
||||
<button type="button" class="btn btn-sm btn-xs-quart d-block d-sm-inline{% if quarantine_notification == 'weekly' %} btn-dark{% else %} btn-light{% endif %}"
|
||||
data-action="edit_selected"
|
||||
data-item="{{ mailbox }}"
|
||||
data-id="quarantine_notification"
|
||||
data-api-url='edit/quarantine_notification'
|
||||
data-api-attr='{"quarantine_notification":"weekly"}'>{{ lang.user.weekly }}</button>
|
||||
</div>
|
||||
<p class="text-muted"><small>{{ lang.user.quarantine_notification_info }}</small></p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-2">
|
||||
<label class="control-label col-sm-2">{{ lang.user.quarantine_category }}</label>
|
||||
<div class="col-sm-10">
|
||||
<div class="btn-group" data-acl="{{ acl.quarantine_category }}">
|
||||
<button type="button" class="btn btn-sm btn-xs-third d-block d-sm-inline{% if quarantine_category == 'reject' %} btn-dark{% else %} btn-light{% endif %}"
|
||||
data-action="edit_selected"
|
||||
data-item="{{ mailbox }}"
|
||||
data-id="quarantine_category"
|
||||
data-api-url='edit/quarantine_category'
|
||||
data-api-attr='{"quarantine_category":"reject"}'>{{ lang.user.q_reject }}</button>
|
||||
<button type="button" class="btn btn-sm btn-xs-third d-block d-sm-inline{% if quarantine_category == 'add_header' %} btn-dark{% else %} btn-light{% endif %}"
|
||||
data-action="edit_selected"
|
||||
data-item="{{ mailbox }}"
|
||||
data-id="quarantine_category"
|
||||
data-api-url='edit/quarantine_category'
|
||||
data-api-attr='{"quarantine_category":"add_header"}'>{{ lang.user.q_add_header }}</button>
|
||||
<button type="button" class="btn btn-sm btn-xs-third d-block d-sm-inline{% if quarantine_category == 'all' %} btn-dark{% else %} btn-light{% endif %}"
|
||||
data-action="edit_selected"
|
||||
data-item="{{ mailbox }}"
|
||||
data-id="quarantine_category"
|
||||
data-api-url='edit/quarantine_category'
|
||||
data-api-attr='{"quarantine_category":"all"}'>{{ lang.user.q_all }}</button>
|
||||
</div>
|
||||
<p class="text-muted"><small>{{ lang.user.quarantine_category_info }}</small></p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-4">
|
||||
<label class="control-label col-sm-2" for="sender_acl">{{ lang.user.tls_policy }}</label>
|
||||
<div class="col-sm-10">
|
||||
<div class="btn-group" data-acl="{{ acl.tls_policy }}">
|
||||
<button type="button" class="btn btn-sm btn-xs-half d-block d-sm-inline{% if get_tls_policy.tls_enforce_in == '1' %} btn-dark{% else %} btn-light{% endif %}"
|
||||
data-action="edit_selected"
|
||||
data-item="{{ mailbox }}"
|
||||
data-id="tls_policy"
|
||||
data-api-url='edit/tls_policy'
|
||||
data-api-attr='{"tls_enforce_in": {% if get_tls_policy.tls_enforce_in == '1' %}0{% else %}1{% endif %} }'>{{ lang.user.tls_enforce_in }}</button>
|
||||
<button type="button" class="btn btn-sm btn-xs-half d-block d-sm-inline{% if get_tls_policy.tls_enforce_out == '1' %} btn-dark{% else %} btn-light{% endif %}"
|
||||
data-action="edit_selected"
|
||||
data-item="{{ mailbox }}"
|
||||
data-id="tls_policy"
|
||||
data-api-url='edit/tls_policy'
|
||||
data-api-attr='{"tls_enforce_out": {% if get_tls_policy.tls_enforce_out == '1' %}0{% else %}1{% endif %} }'>{{ lang.user.tls_enforce_out }}</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<label class="control-label col-sm-2" for="password">{{ lang.edit.password }} (<a href="#" class="generate_password">{{ lang.edit.generate }}</a>)</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="password" data-pwgen-field="true" data-hibp="true" class="form-control" name="password" placeholder="{{ lang.edit.unchanged_if_empty }}" autocomplete="new-password">
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-4">
|
||||
<label class="control-label col-sm-2" for="password2">{{ lang.edit.password_repeat }}</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="password" data-pwgen-field="true" class="form-control" name="password2" autocomplete="new-password">
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-4">
|
||||
<label class="control-label col-sm-2" for="pw_recovery_email">{{ lang.edit.password_recovery_email }}</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="email" class="form-control" name="pw_recovery_email" value="{{ result.attributes.recovery_email }}">
|
||||
<small class="text-muted">{{ lang.admin.password_reset_info }}</small>
|
||||
</div>
|
||||
</div>
|
||||
<div data-acl="{{ acl.extend_sender_acl }}" class="row mb-4">
|
||||
<label class="control-label col-sm-2" for="extended_sender_acl">{{ lang.edit.extended_sender_acl }}</label>
|
||||
<div class="col-sm-10">
|
||||
{% if sender_acl_handles.external_sender_aliases %}
|
||||
{% set ext_sender_acl = sender_acl_handles.external_sender_aliases|join(', ') %}
|
||||
{% endif %}
|
||||
{% if acl.extend_sender_acl and acl.extend_sender_acl == 1 %}
|
||||
<input type="text" class="form-control" name="extended_sender_acl" value="{{ ext_sender_acl }}" placeholder="user1@example.com, user2@example.org, @example.com, ...">
|
||||
<small class="text-muted">{{ lang.edit.extended_sender_acl_info|raw }}</small>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<label class="control-label col-sm-2" for="protocol_access">{{ lang.edit.allowed_protocols }}</label>
|
||||
<div class="col-sm-10">
|
||||
<select data-acl="{{ acl.protocol_access }}" name="protocol_access" multiple class="form-control">
|
||||
<option value="imap"{% if result.attributes.imap_access == '1' %} selected{% endif %}>IMAP</option>
|
||||
<option value="pop3"{% if result.attributes.pop3_access == '1' %} selected{% endif %}>POP3</option>
|
||||
<option value="smtp"{% if result.attributes.smtp_access == '1' %} selected{% endif %}>SMTP</option>
|
||||
<option value="sieve"{% if result.attributes.sieve_access == '1' %} selected{% endif %}>Sieve</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div hidden data-acl="{{ acl.smtp_ip_access }}" class="row">
|
||||
<label class="control-label col-sm-2" for="allow_from_smtp">{{ lang.edit.allow_from_smtp }}</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="text" class="form-control" name="allow_from_smtp" value="{{ allow_from_smtp }}" placeholder="1.1.1.1, 10.2.0.0/24, ...">
|
||||
<small class="text-muted">{{ lang.edit.allow_from_smtp_info }}</small>
|
||||
</div>
|
||||
</div>
|
||||
<hr>
|
||||
<div class="row">
|
||||
<div class="offset-sm-2 col-sm-10">
|
||||
<select name="active" class="form-control">
|
||||
<option value="1"{% if result.active == '1' %} selected{% endif %}>{{ lang.edit.active }}</option>
|
||||
<option value="2"{% if result.active == '2' %} selected{% endif %}>{{ lang.edit.disable_login }}</option>
|
||||
<option value="0"{% if result.active == '0' %} selected{% endif %}>{{ lang.edit.inactive }}</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mt-2">
|
||||
<div class="offset-sm-2 col-sm-10">
|
||||
<div class="form-check">
|
||||
<label><input type="checkbox" class="form-check-input" value="1" name="force_pw_update"{% if result.attributes.force_pw_update == '1' %} checked{% endif %}> {{ lang.edit.force_pw_update }}</label>
|
||||
<small class="text-muted">{{ lang.edit.force_pw_update_info|format(ui_texts.main_name) }}</small>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% if not skip_sogo %}
|
||||
<div data-acl="{{ acl.sogo_access }}" class="row">
|
||||
<div class="offset-sm-2 col-sm-10">
|
||||
<div class="form-check">
|
||||
<label><input type="checkbox" class="form-check-input" value="1" name="sogo_access"{% if result.attributes.sogo_access == '1' %} checked{% endif %}> {{ lang.edit.sogo_access }}</label>
|
||||
<small class="text-muted">{{ lang.edit.sogo_access_info }}</small>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
<div class="row mt-2 mb-2">
|
||||
<div class="offset-sm-2 col-sm-10">
|
||||
<button class="btn btn-xs-lg d-block d-sm-inline btn-success" data-action="edit_selected" data-id="editmailbox" data-item="{{ result.username }}" data-api-url='edit/mailbox' data-api-attr='{}' href="#">{{ lang.edit.save }}</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="offset-sm-2 col-sm-10">
|
||||
<small class="fst-italic d-block">{{ lang.edit.created_on }}: {{ result.created }}</small>
|
||||
<small class="fst-italic d-block">{{ lang.edit.last_modified }}: {{ result.modified }}</small>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="mattr" class="tab-pane fade" role="tabpanel" aria-labelledby="mailbox-attr">
|
||||
<div class="card mb-4">
|
||||
<div class="card-header d-flex d-md-none fs-5">
|
||||
<button class="btn flex-grow-1 text-start" data-bs-target="#collapse-tab-mattr" data-bs-toggle="collapse" aria-controls="collapse-tab-mattr">
|
||||
{{ lang.edit.mailbox }} <span class="badge bg-info table-lines"></span>
|
||||
</button>
|
||||
</div>
|
||||
<div id="collapse-tab-mattr" class="card-body collapse show" data-bs-parent="#mailbox-content">
|
||||
<form class="form-inline" data-id="mbox_attr" role="form" method="post">
|
||||
<table class="table table-condensed" style="white-space: nowrap;" id="mbox_attr_table">
|
||||
<tr>
|
||||
<th>{{ lang.user.attribute }}</th>
|
||||
<th>{{ lang.user.value }}</th>
|
||||
<th style="width:100px;"> </th>
|
||||
</tr>
|
||||
{% for key, val in result.custom_attributes %}
|
||||
<tr>
|
||||
<td><input class="input-sm input-xs-lg form-control" data-id="mbox_attr" type="text" name="attribute" required value="{{ key }}"></td>
|
||||
<td><input class="input-sm input-xs-lg form-control" data-id="mbox_attr" type="text" name="value" required value="{{ val }}"></td>
|
||||
<td><a href="#" role="button" class="btn btn-sm btn-xs-lg btn-secondary h-100 w-100" type="button">{{ lang.admin.remove_row }}</a></td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
<p><div class="btn-group">
|
||||
<button class="btn btn-sm btn-xs-half d-block d-sm-inline btn-success" data-action="edit_selected" data-item="{{ mailbox }}" data-id="mbox_attr" data-api-url='edit/mailbox/custom-attribute' data-api-attr='{}' href="#"><i class="bi bi-check-lg"></i> {{ lang.admin.save }}</button>
|
||||
<button class="btn btn-sm btn-xs-half d-block d-sm-inline btn-secondary" type="button" id="add_mbox_attr_row">{{ lang.admin.add_row }}</button>
|
||||
</div></p>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="mpushover" class="tab-pane fade" role="tabpanel" aria-labelledby="mailbox-pushover">
|
||||
<div class="card mb-4">
|
||||
<div class="card-header d-flex d-md-none fs-5">
|
||||
<button class="btn flex-grow-1 text-start" data-bs-target="#collapse-tab-mpushover" data-bs-toggle="collapse" aria-controls="collapse-tab-mpushover">
|
||||
{{ lang.edit.pushover }} <span class="badge bg-info table-lines"></span>
|
||||
</button>
|
||||
</div>
|
||||
<div id="collapse-tab-mpushover" class="card-body collapse" data-bs-parent="#mailbox-content">
|
||||
<form data-id="pushover" class="form well" method="post">
|
||||
<input type="hidden" value="0" name="evaluate_x_prio">
|
||||
<input type="hidden" value="0" name="only_x_prio">
|
||||
<input type="hidden" value="0" name="active">
|
||||
<div class="row">
|
||||
<div class="col-sm-1">
|
||||
<p class="text-muted"><a href="https://pushover.net" target="_blank"><img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAMAAABg3Am1AAACglBMVEUAAAAAAAEAAAAilecFGigAAAAAAAAAAAAAAAANj+c3n+Ypm+oeYI4KWI4MieAtkdQbleoJcLcjmeswmN4Rit4KgdMKUYQJKUAQSnILL0kMNlMSTngimOoNPF0hlOQBBgkNOlkRS3MHIjUhk+IPf8wKLUYsjM0AAAASTngAAAAAAAAPfckbdLIbdrYUWIgegsgce70knfEAAAAknfENOVkGHi8YaaIjnvEdgMUhkuAQSG8aca0hleQUh9YLjOM4nOEMgtMcbaYWa6YemO02ltkKhNktgLodYZEPXJEyi8kKesktfLUzj84cWYMiluckZ5YJXJYeW4Y0k9YKfs4yjs0pc6YHZaUviskLfMkqmugak+cqkNcViNcqeK4Iaq4XRmYGPmYMKDsFJTstgr0LdL0ti84CCQ4BCQ4Qgc8rlt8XjN8shcQsi8wZSGgEP2cRMEUDKkUAAAD///8dmvEamfExo/EXmPEWl/ERlvElnvEsofEjnfETl/Enn/Ezo/E4pvEvovEfm/E1pPEzpPEvofEOlfEpoPEamPEQlfEYmfE6p/EgnPEVlvEroPE3pfE2pfENk/Ern/E3pPEcmfEfmvEnnvBlufT6/P0soPAknPDd7/zs9vzo9PxBqfItofAqoPD9/f3B4/q43/mx2/l/xfZ6w/Vxv/VtvfVgt/RXtPNTsfNEq/L3+/31+v3a7fvR6vvH5fqs2vmc0/jx+P3v9/3h8fzW7PvV7PvL5/q13fmo1/mh1PiY0fiNy/aHyfZ2wfVou/Vdt/RPsPM3oeoQkuowmeAgjdgcgMQbeLrw9/3k8vy74Pm63/mX0PdYtfNNr/Ikm+4wnOchkuAVjOAfdrMVcrOdoJikAAAAcnRSTlMAIQ8IzzweFwf+/fvw8P79+/Xt7e3p6eji4d7U08y8qZyTiIWDgn53bWxqaWBKQ0JBOjUwMCkoJCEfHBkT/vz8/Pv7+vr69/b29PTy7ezm5ubm5N7e29vQ0M/Pv7+4uLW1pqaWloWDg3x7e21mUVFFRUXdPracAAAEbElEQVRIx4WUZbvaQBCFF+ru7u7u7u7u7t4mvVwSoBC0JIUCLRQolLq7u7vr/+nMLkmQyvlwyfPcd86e3ZldUqwyQ/p329J+XfutPQYOLUP+q55rFtQJRvY79+xxlZTUWbKpz7/xrrMr2+3BoNPpdLn2lJQ4HEeqLOr1d7z7XNkesQed4A848G63Oy4Gmg/6Mz542QvZbqe8C/Ig73CLYiYTrtLmT3zfqbIcAR7y4wIqH/B6M9Fo0+Ldb6sM9ph/v4ozPuz12mxRofaAAr7jCNkuoz/jNf9AGHibkBCm51fsGKvxsAGWx4H+jBcEi6V2birDpCL/9Klrd1KHbiSvPWP8V0tTnTfO03iXi57P6WNHOVUf44IFdFDRz6pV5fw8Zy5z3JVH5+R48OwxqDiGvKJIY9R+9JsCuJ5HPg74OVEMpz+nbdEPUHEWeEk6IDUnTC1l5r+f8uffc0cfxc8fS17kLso24SwUPFDA/6DE82xKDOPliJ7n/GGOOyWK9zD9CdjvOfg9Dv6AH+AX04LW9gj2i8W/APx1UbxwCAu+wPmcpgUKL/EHdvtq4uwaZwCuznPJVY5LHhED15G/isd5Hz4eKui/e/du02YoKFeD5mHzHIN/nxEDe25gQQwKorAid04CfyzwL4XutXvl1Pt1guMOwwKPkU8mYIFT8JHK+vv8prpDScUVL+j8s3lOctw1GIhbWHAS+HgKPk7xPM/4UtNAYmzizJkf6NgTb/gM8jePQLsewMdthS3g95tMpT1IhVm6v1s8fYmLeb13Odwp8Fh5KY048y/d14WUrwrb1e/X/rNp73nkD8kWS+wi/MZ4XuetG4mhKubJm3/WNEvi8SHwB56nPKjUam0LBdp9ARwupFemTYudvgN/L1+A/Ko/LGBuS8pPy+YR1fuCTWNKnUyoeUyYx2o2dyEVGmr5xTD42xzvkD16+Pb9WIIH6fmt1r3mbsTY7Bvw+n23naT8BUWh86bz6G/e259UXPUK3gfAxQDlo7Rpx3Geqb2e3wp83SGEdKpB7zvwYbzvT2n65xLwbH6YP+M9C8vA8E1wxLU8gkCbdhXGUyrMgwVrcbzLHonr78lzDvWM3q/C/HtDlXoSUIe3YkblhRPIX4E8Oo/9siLv8dRjV7SBlkdgTXvKS7nzsA/9AfeEuhKq9T8zWIDv1Sd6ETAP4D6/H/1V+1BojvruNa4SZXz4JhY84dV5MOF5agUvu5OsOo+KRpG30KalEnoeDccFlutPZYs38D5n3zcpr1/0fBhfb3DOY1z2tSAgLxWezz6zuoHhfUmOejf6blHQH/sFuJYfcMZX307ytKvRa3ifoV/586P5j+tICtS77BuJxzxYAPZsntX8k3eSIhlajK4p8b7iefCEKs03kD/I2LnxL9ovH+43y4fAv1YrI/mzDBsavAX/UppfzVOrZT/ydxk6lJ047MfLfVbcb6hS9ZEzWxekKQ5WrtPqZg3rV6tWrX6Tle3KQZj/q6KxQnmDoXwFY0VSrN9e8FRXBCTAvwAAAABJRU5ErkJggg==" class="img img-fluid"></a></p>
|
||||
</div>
|
||||
<div class="col-sm-10">
|
||||
<p class="text-muted">{{ lang.user.pushover_info|format(mailbox)|raw }}</p>
|
||||
<p class="text-muted">{{ lang.edit.pushover_vars|raw }}: <code>{SUBJECT}</code>, <code>{SENDER}</code>, <code>{SENDER_ADDRESS}</code>, <code>{SENDER_NAME}</code>, <code>{TO_NAME}</code>, <code>{TO_ADDRESS}</code>, <code>{MSG_ID}</code></p>
|
||||
<div class="row">
|
||||
<div class="col-sm-6 mb-2">
|
||||
<label for="token">API Token/Key (Application)</label>
|
||||
<input type="text" class="form-control" name="token" maxlength="30" value="{{ pushover_data.token }}" required>
|
||||
</div>
|
||||
<div class="col-sm-6 mb-2">
|
||||
<label for="key">User/Group Key</label>
|
||||
<input type="text" class="form-control" name="key" maxlength="30" value="{{ pushover_data.key }}" required>
|
||||
</div>
|
||||
<div class="col-sm-6 mb-4">
|
||||
<label for="title">{{ lang.edit.pushover_title }}</label>
|
||||
<input type="text" class="form-control" name="title" value="{{ pushover_data.title }}" placeholder="Mail">
|
||||
</div>
|
||||
<div class="col-sm-6 mb-4">
|
||||
<label for="text">{{ lang.edit.pushover_text }}</label>
|
||||
<input type="text" class="form-control" name="text" value="{{ pushover_data.text }}" placeholder="You've got mail 📧">
|
||||
</div>
|
||||
<div class="col-sm-12 mb-4">
|
||||
<label for="text">{{ lang.edit.pushover_sender_array|raw }}</label>
|
||||
<input type="text" class="form-control" name="senders" value="{{ pushover_data.senders }}" placeholder="sender1@example.com, sender2@example.com">
|
||||
</div>
|
||||
<div class="col-sm-12 mb-2">
|
||||
<div class="form-group">
|
||||
<label for="sound">{{ lang.edit.pushover_sound }}</label><br>
|
||||
<select name="sound" class="form-control">
|
||||
<option value="pushover"{% if pushover_data.attributes.sound == 'pushover' %} selected{% endif %}>Pushover (default)</option>
|
||||
<option value="bike"{% if pushover_data.attributes.sound == 'bike' %} selected{% endif %}>Bike</option>
|
||||
<option value="bugle"{% if pushover_data.attributes.sound == 'bugle' %} selected{% endif %}>Bugle</option>
|
||||
<option value="cashregister"{% if pushover_data.attributes.sound == 'cashregister' %} selected{% endif %}>Cash Register</option>
|
||||
<option value="classical"{% if pushover_data.attributes.sound == 'classical' %} selected{% endif %}>Classical</option>
|
||||
<option value="cosmic"{% if pushover_data.attributes.sound == 'cosmic' %} selected{% endif %}>Cosmic</option>
|
||||
<option value="falling"{% if pushover_data.attributes.sound == 'falling' %} selected{% endif %}>Falling</option>
|
||||
<option value="gamelan"{% if pushover_data.attributes.sound == 'gamelan' %} selected{% endif %}>Gamelan</option>
|
||||
<option value="incoming"{% if pushover_data.attributes.sound == 'incoming' %} selected{% endif %}>Incoming</option>
|
||||
<option value="intermission"{% if pushover_data.attributes.sound == 'intermission' %} selected{% endif %}>Intermission</option>
|
||||
<option value="magic"{% if pushover_data.attributes.sound == 'magic' %} selected{% endif %}>Magic</option>
|
||||
<option value="mechanical"{% if pushover_data.attributes.sound == 'mechanical' %} selected{% endif %}>Mechanical</option>
|
||||
<option value="pianobar"{% if pushover_data.attributes.sound == 'pianobar' %} selected{% endif %}>Piano Bar</option>
|
||||
<option value="siren"{% if pushover_data.attributes.sound == 'siren' %} selected{% endif %}>Siren</option>
|
||||
<option value="spacealarm"{% if pushover_data.attributes.sound == 'spacealarm' %} selected{% endif %}>Space Alarm</option>
|
||||
<option value="tugboat"{% if pushover_data.attributes.sound == 'tugboat' %} selected{% endif %}>Tug Boat</option>
|
||||
<option value="alien"{% if pushover_data.attributes.sound == 'alien' %} selected{% endif %}>Alien Alarm (long)</option>
|
||||
<option value="climb"{% if pushover_data.attributes.sound == 'climb' %} selected{% endif %}>Climb (long)</option>
|
||||
<option value="persistent"{% if pushover_data.attributes.sound == 'persistent' %} selected{% endif %}>Persistent (long)</option>
|
||||
<option value="echo"{% if pushover_data.attributes.sound == 'echo' %} selected{% endif %}>Pushover Echo (long)</option>
|
||||
<option value="updown"{% if pushover_data.attributes.sound == 'updown' %} selected{% endif %}>Up Down (long)</option>
|
||||
<option value="vibrate"{% if pushover_data.attributes.sound == 'vibrate' %} selected{% endif %}>Vibrate Only</option>
|
||||
<option value="none"{% if pushover_data.attributes.sound == 'none' %} selected{% endif %}> None (silent) </option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-12">
|
||||
<div class="form-check">
|
||||
<label><input type="checkbox" class="form-check-input" value="1" name="active"{% if pushover_data.active == '1' %} checked{% endif %}> {{ lang.edit.active }}</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-12">
|
||||
<legend style="cursor:pointer;margin-top:10px" data-bs-target="#po_advanced" unselectable="on" data-bs-toggle="collapse">
|
||||
<i class="bi bi-plus"></i> {{ lang.edit.advanced_settings }}
|
||||
</legend>
|
||||
<hr />
|
||||
</div>
|
||||
<div class="col-sm-12 mb-4">
|
||||
<div id="po_advanced" class="collapse">
|
||||
<label for="text">{{ lang.edit.pushover_sender_regex }}</label>
|
||||
<input type="text" class="form-control mt-2" name="senders_regex" value="{{ pushover_data.senders_regex }}" placeholder="/(.*@example\.org$|^foo@example\.com$)/i" regex="true">
|
||||
<div class="form-check mt-4">
|
||||
<label><input type="checkbox" class="form-check-input" value="1" name="evaluate_x_prio"{% if pushover_data.attributes.evaluate_x_prio == '1' %} checked{% endif %}> {{ lang.edit.pushover_evaluate_x_prio|raw }}</label>
|
||||
</div>
|
||||
<div class="form-check mt-2">
|
||||
<label><input type="checkbox" class="form-check-input" value="1" name="only_x_prio"{% if pushover_data.attributes.only_x_prio == '1' %} checked{% endif %}> {{ lang.edit.pushover_only_x_prio|raw }}</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="btn-group" data-acl="{{ acl.pushover }}">
|
||||
<a class="btn btn-sm btn-xs-half d-block d-sm-inline btn-success" data-action="edit_selected" data-id="pushover" data-item="{{ mailbox }}" data-api-url='edit/pushover' data-api-attr='{}' href="#">{{ lang.edit.save }}</a>
|
||||
<a class="btn btn-sm btn-xs-half d-block d-sm-inline btn-secondary" data-action="edit_selected" data-id="pushover-test" data-item="{{ mailbox }}" data-api-url='edit/pushover-test' data-api-attr='{}' href="#"><i class="bi bi-check-lg"></i> {{ lang.edit.pushover_verify }}</a>
|
||||
<a id="pushover_delete" class="btn btn-sm d-block d-sm-inline btn-danger" data-action="edit_selected" data-id="pushover-delete" data-item="{{ mailbox }}" data-api-url='edit/pushover' data-api-attr='{"delete":"true"}' href="#"><i class="bi bi-trash"></i> {{ lang.edit.remove }}</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="macl" class="tab-pane fade" role="tabpanel" aria-labelledby="mailbox-acl">
|
||||
<div class="card mb-4">
|
||||
<div class="card-header d-flex d-md-none fs-5">
|
||||
<button class="btn flex-grow-1 text-start" data-bs-target="#collapse-tab-macl" data-bs-toggle="collapse" aria-controls="collapse-tab-macl">
|
||||
{{ lang.edit.acl }} <span class="badge bg-info table-lines"></span>
|
||||
</button>
|
||||
</div>
|
||||
<div id="collapse-tab-macl" class="card-body collapse" data-bs-parent="#mailbox-content">
|
||||
<form data-id="useracl" class="form-inline well" method="post">
|
||||
<div class="row">
|
||||
<div class="col-sm-1">
|
||||
<p class="text-muted">ACL</p>
|
||||
</div>
|
||||
<div class="col-sm-10">
|
||||
<select id="user_acl" name="user_acl" size="10" multiple>
|
||||
{% for acl, val in user_acls %}
|
||||
<option value="{{ acl }}"{% if val == 1 %} selected{% endif %}>{{ lang.acl[acl] }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
<button class="btn btn-xs-lg d-block d-sm-inline btn-secondary" data-action="edit_selected" data-id="useracl" data-item="{{ mailbox }}" data-api-url='edit/user-acl' data-api-attr='{}' href="#">{{ lang.edit.save }}</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="mrl" class="tab-pane fade" role="tabpanel" aria-labelledby="mailbox-rl">
|
||||
<div class="card mb-4">
|
||||
<div class="card-header d-flex d-md-none fs-5">
|
||||
<button class="btn flex-grow-1 text-start" data-bs-target="#collapse-tab-mrl" data-bs-toggle="collapse" aria-controls="collapse-tab-mrl">
|
||||
{{ lang.edit.ratelimit }} <span class="badge bg-info table-lines"></span>
|
||||
</button>
|
||||
</div>
|
||||
<div id="collapse-tab-mrl" class="card-body collapse" data-bs-parent="#mailbox-content">
|
||||
<form data-id="mboxratelimit" class="well" method="post">
|
||||
<div class="row mb-2">
|
||||
<div class="col-sm-2">
|
||||
<p class="text-muted">{{ lang.acl.ratelimit }}</p>
|
||||
</div>
|
||||
<div class="col-sm-10">
|
||||
<div class="input-group">
|
||||
<input name="rl_value" type="number" autocomplete="off" value="{{ rl.value }}" class="form-control" placeholder="{{ lang.ratelimit.disabled }}">
|
||||
<select name="rl_frame" class="form-control">
|
||||
{% include 'mailbox/rl-frame.twig' %}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-2">
|
||||
<div class="offset-sm-2 col-sm-10">
|
||||
<button class="btn btn-xs-lg d-block d-sm-inline btn-secondary" data-action="edit_selected" data-id="mboxratelimit" data-item="{{ mailbox }}" data-api-url='edit/rl-mbox' data-api-attr='{}' href="#">{{ lang.edit.save }}</button>
|
||||
<p class="text-muted mt-2">{{ lang.edit.mbox_rl_info }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% else %}
|
||||
{{ parent() }}
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
40
data/web/templates/edit/oauth2client.twig
Executable file
40
data/web/templates/edit/oauth2client.twig
Executable file
|
|
@ -0,0 +1,40 @@
|
|||
{% extends 'edit.twig' %}
|
||||
|
||||
{% block inner_content %}
|
||||
{% if result %}
|
||||
<h4>OAuth2</h4>
|
||||
<form data-id="oauth2client" class="form-horizontal" role="form" method="post">
|
||||
<div class="row mb-2">
|
||||
<label class="control-label col-sm-2" for="client_id">{{ lang.edit.client_id }}</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="text" class="form-control" name="client_id" id="client_id" value="{{ result.client_id }}" disabled>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-2">
|
||||
<label class="control-label col-sm-2" for="client_secret">{{ lang.edit.client_secret }}</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="text" class="form-control" name="client_secret" id="client_secret" value="{{ result.client_secret }}" disabled>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-2">
|
||||
<label class="control-label col-sm-2" for="scope">{{ lang.edit.scope }}</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="text" class="form-control" name="scope" id="scope" value="{{ result.scope }}" disabled>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-4">
|
||||
<label class="control-label col-sm-2" for="redirect_uri">{{ lang.edit.redirect_uri }}</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="text" class="form-control" name="redirect_uri" id="redirect_uri" value="{{ result.redirect_uri }}">
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="offset-sm-2 col-sm-10">
|
||||
<button class="btn btn-xs-lg d-block d-sm-inline btn-secondary" data-action="edit_selected" data-id="oauth2client" data-item="{{ oauth2client }}" data-api-url='edit/oauth2-client' data-api-attr='{}' href="#">{{ lang.admin.save }}</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
{% else %}
|
||||
{{ parent() }}
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
39
data/web/templates/edit/recipient_map.twig
Executable file
39
data/web/templates/edit/recipient_map.twig
Executable file
|
|
@ -0,0 +1,39 @@
|
|||
{% extends 'edit.twig' %}
|
||||
|
||||
{% block inner_content %}
|
||||
{% if result %}
|
||||
<h4>{{ lang.mailbox.recipient_map }}: {{ result.recipient_map_old }}</h4>
|
||||
<br>
|
||||
<form class="form-horizontal" data-id="edit_recipient_map" role="form" method="post">
|
||||
<input type="hidden" value="0" name="active">
|
||||
<div class="row mb-2">
|
||||
<label class="control-label col-sm-2" for="recipient_map_new">{{ lang.mailbox.recipient_map_old }}</label>
|
||||
<div class="col-sm-10">
|
||||
<input value="{{ result.recipient_map_old }}" type="text" class="form-control" name="recipient_map_old" id="recipient_map_old">
|
||||
<small>{{ lang.mailbox.recipient_map_old_info }}</small>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-4">
|
||||
<label class="control-label col-sm-2" for="recipient_map_new">{{ lang.mailbox.recipient_map_new }}</label>
|
||||
<div class="col-sm-10">
|
||||
<input value="{{ result.recipient_map_new }}" type="text" class="form-control" name="recipient_map_new" id="recipient_map_new">
|
||||
<small>{{ lang.mailbox.recipient_map_new_info }}</small>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-2">
|
||||
<div class="offset-sm-2 col-sm-10">
|
||||
<div class="form-check">
|
||||
<label><input type="checkbox" class="form-check-input" value="1" name="active"{% if result.active == '1' %} checked{% endif %}> {{ lang.edit.active }}</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-2">
|
||||
<div class="offset-sm-2 col-sm-10">
|
||||
<button class="btn btn-xs-lg d-block d-sm-inline btn-success" data-action="edit_selected" data-id="edit_recipient_map" data-item="{{ map }}" data-api-url='edit/recipient_map' data-api-attr='{}' href="#">{{ lang.edit.save }}</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
{% else %}
|
||||
{{ parent() }}
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
43
data/web/templates/edit/relayhost.twig
Executable file
43
data/web/templates/edit/relayhost.twig
Executable file
|
|
@ -0,0 +1,43 @@
|
|||
{% extends 'edit.twig' %}
|
||||
|
||||
{% block inner_content %}
|
||||
{% if result %}
|
||||
<h4>{{ lang.edit.resource }}</h4>
|
||||
<form class="form-horizontal" role="form" method="post" data-id="editrelayhost">
|
||||
<input type="hidden" value="0" name="active">
|
||||
<div class="row mb-2">
|
||||
<label class="control-label col-sm-2" for="hostname">{{ lang.add.hostname }}</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="text" class="form-control" name="hostname" value="{{ result.hostname }}" required>
|
||||
<p class="text-muted">{{ lang.add.relayhost_wrapped_tls_info|raw }}</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-2">
|
||||
<label class="control-label col-sm-2" for="username">{{ lang.add.username }}</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="text" class="form-control" name="username" value="{{ result.username }}">
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-4">
|
||||
<label class="control-label col-sm-2" for="password">{{ lang.add.password }}</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="text" data-hibp="true" class="form-control" name="password" value="{{ result.password }}">
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-2">
|
||||
<div class="offset-sm-2 col-sm-10">
|
||||
<div class="form-check">
|
||||
<label><input type="checkbox" class="form-check-input" value="1" name="active"{% if result.active == '1' %} checked{% endif %}> {{ lang.edit.active }}</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-2">
|
||||
<div class="offset-sm-2 col-sm-10">
|
||||
<button class="btn btn-xs-lg d-block d-sm-inline btn-success" data-action="edit_selected" data-id="editrelayhost" data-item="{{ result.id }}" data-api-url='edit/relayhost' data-api-attr='{}' href="#">{{ lang.edit.save }}</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
{% else %}
|
||||
{{ parent() }}
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
55
data/web/templates/edit/resource.twig
Executable file
55
data/web/templates/edit/resource.twig
Executable file
|
|
@ -0,0 +1,55 @@
|
|||
{% extends 'edit.twig' %}
|
||||
|
||||
{% block inner_content %}
|
||||
{% if result %}
|
||||
<h4>{{ lang.edit.resource }}</h4>
|
||||
<form class="form-horizontal" role="form" method="post" data-id="editresource">
|
||||
<input type="hidden" value="0" name="active">
|
||||
<div class="row mb-4">
|
||||
<label class="control-label col-sm-2" for="description">{{ lang.add.description }}</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="text" class="form-control" name="description" value="{{ result.description }}" required>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-2">
|
||||
<label class="control-label col-sm-2" for="domain">{{ lang.edit.kind }}</label>
|
||||
<div class="col-sm-10">
|
||||
<select name="kind" title="{{ lang.edit.select }}" required>
|
||||
<option value="location"{% if result.kind == 'location' %} selected{% endif %}>Location</option>
|
||||
<option value="group"{% if result.kind == 'group' %} selected{% endif %}>Group</option>
|
||||
<option value="thing"{% if result.kind == 'thing' %} selected{% endif %}>Thing</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-4">
|
||||
<label class="control-label col-sm-2" for="multiple_bookings_select">{{ lang.add.multiple_bookings }}</label>
|
||||
<div class="col-sm-10">
|
||||
<select name="multiple_bookings_select" id="editSelectMultipleBookings" title="{{ lang.add.select }}" required>
|
||||
<option value="0"{% if result.multiple_bookings == 0 %} selected{% endif %}>{{ lang.mailbox.booking_null }}</option>
|
||||
<option value="-1"{% if result.multiple_bookings == -1 %} selected{% endif %}>{{ lang.mailbox.booking_ltnull }}</option>
|
||||
<option value="custom"{% if result.multiple_bookings >= 1 %} selected{% endif %}>{{ lang.mailbox.booking_custom }}</option>
|
||||
</select>
|
||||
<div style="display:none" id="multiple_bookings_custom_div">
|
||||
<hr>
|
||||
<input type="number" class="form-control" name="multiple_bookings_custom" id="multiple_bookings_custom"{% if result.multiple_bookings >= 1 %} value="{{ result.multiple_bookings }}"{% endif %}>
|
||||
</div>
|
||||
<input type="hidden" name="multiple_bookings" id="multiple_bookings">
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-2">
|
||||
<div class="offset-sm-2 col-sm-10">
|
||||
<div class="form-check">
|
||||
<label><input type="checkbox" class="form-check-input" value="1" name="active"{% if result.active == '1' %} checked{% endif %}> {{ lang.edit.active }}</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="offset-sm-2 col-sm-10">
|
||||
<button class="btn btn-xs-lg d-block d-sm-inline btn-success" data-action="edit_selected" data-id="editresource" data-item="{{ result.name }}" data-api-url='edit/resource' data-api-attr='{}' href="#">{{ lang.edit.save }}</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
{% else %}
|
||||
{{ parent() }}
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
168
data/web/templates/edit/syncjob.twig
Executable file
168
data/web/templates/edit/syncjob.twig
Executable file
|
|
@ -0,0 +1,168 @@
|
|||
{% extends 'edit.twig' %}
|
||||
|
||||
{% block inner_content %}
|
||||
{% if result %}
|
||||
<h4 class="mb-4">{{ lang.edit.syncjob }}</h4>
|
||||
<form class="form-horizontal" data-id="editsyncjob" role="form" method="post">
|
||||
<input type="hidden" value="0" name="delete2duplicates">
|
||||
<input type="hidden" value="0" name="delete1">
|
||||
<input type="hidden" value="0" name="delete2">
|
||||
<input type="hidden" value="0" name="automap">
|
||||
<input type="hidden" value="0" name="skipcrossduplicates">
|
||||
<input type="hidden" value="0" name="active">
|
||||
<input type="hidden" value="0" name="subscribeall">
|
||||
<input type="hidden" value="0" name="dry">
|
||||
<div class="row mb-2">
|
||||
<label class="control-label col-sm-2" for="host1">{{ lang.edit.hostname }}</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="text" class="form-control" name="host1" id="host1" value="{{ result.host1 }}">
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-4">
|
||||
<label class="control-label col-sm-2" for="port1">Port</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="number" class="form-control" name="port1" id="port1" min="1" max="65535" value="{{ result.port1 }}">
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-2">
|
||||
<label class="control-label col-sm-2" for="user1">{{ lang.edit.username }}</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="text" class="form-control" name="user1" id="user1" value="{{ result.user1 }}">
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-4">
|
||||
<label class="control-label col-sm-2" for="password1">{{ lang.edit.password }}</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="password" class="form-control" name="password1" id="password1" value="{{ result.password1 }}">
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-2">
|
||||
<label class="control-label col-sm-2" for="enc1">{{ lang.edit.encryption }}</label>
|
||||
<div class="col-sm-10">
|
||||
<select id="enc1" name="enc1">
|
||||
<option value="SSL"{% if result.enc1 == 'SSL' %} selected{% endif %}>SSL</option>
|
||||
<option value="TLS"{% if result.enc1 == 'TLS' %} selected{% endif %}>STARTTLS</option>
|
||||
<option value="PLAIN"{% if result.enc1 == 'PLAIN' %} selected{% endif %}>PLAIN</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-2">
|
||||
<label class="control-label col-sm-2" for="mins_interval">{{ lang.edit.mins_interval }}</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="number" class="form-control" name="mins_interval" min="1" max="43800" value="{{ result.mins_interval }}" required>
|
||||
<small class="text-muted">1-43800</small>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-2">
|
||||
<label class="control-label col-sm-2" for="subfolder2">{{ lang.edit.subfolder2|raw }}</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="text" class="form-control" name="subfolder2" id="subfolder2" value="{{ result.subfolder2 }}">
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-2">
|
||||
<label class="control-label col-sm-2" for="maxage">{{ lang.edit.maxage|raw }}</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="number" class="form-control" name="maxage" id="maxage" min="0" max="32000" value="{{ result.maxage }}">
|
||||
<small class="text-muted">0-32000</small>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-2">
|
||||
<label class="control-label col-sm-2" for="maxbytespersecond">{{ lang.edit.maxbytespersecond|raw }}</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="number" class="form-control" name="maxbytespersecond" id="maxbytespersecond" min="0" max="125000000" value="{{ result.maxbytespersecond }}">
|
||||
<small class="text-muted">0-125000000</small>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-2">
|
||||
<label class="control-label col-sm-2" for="timeout1">{{ lang.add.timeout1 }}</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="number" class="form-control" name="timeout1" id="timeout1" min="1" max="32000" value="{{ result.timeout1 }}">
|
||||
<small class="text-muted">1-32000</small>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-2">
|
||||
<label class="control-label col-sm-2" for="timeout2">{{ lang.add.timeout2 }}</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="number" class="form-control" name="timeout2" id="timeout2" min="1" max="32000" value="{{ result.timeout2 }}">
|
||||
<small class="text-muted">1-32000</small>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-2">
|
||||
<label class="control-label col-sm-2" for="exclude">{{ lang.edit.exclude }}</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="text" class="form-control" name="exclude" id="exclude" value="{{ result.exclude }}">
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-4">
|
||||
<label class="control-label col-sm-2" for="custom_params">{{ lang.add.custom_params }}</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="text" class="form-control" name="custom_params" id="custom_params" value="{{ result.custom_params }}" placeholder="--some-param=xy --other-param=yx">
|
||||
<small class="text-muted">{{ lang.add.custom_params_hint }}</small>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-2">
|
||||
<div class="offset-sm-2 col-sm-10">
|
||||
<div class="form-check">
|
||||
<label><input type="checkbox" class="form-check-input" value="1" name="delete2duplicates"{% if result.delete2duplicates == '1' %} checked{% endif %}> {{ lang.edit.delete2duplicates }} (--delete2duplicates)</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-2">
|
||||
<div class="offset-sm-2 col-sm-10">
|
||||
<div class="form-check">
|
||||
<label><input type="checkbox" class="form-check-input" value="1" name="delete1"{% if result.delete1 == '1' %} checked{% endif %}> {{ lang.edit.delete1 }} (--delete1)</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-2">
|
||||
<div class="offset-sm-2 col-sm-10">
|
||||
<div class="form-check">
|
||||
<label><input type="checkbox" class="form-check-input" value="1" name="delete2"{% if result.delete2 == '1' %} checked{% endif %}> {{ lang.edit.delete2 }} (--delete2)</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-2">
|
||||
<div class="offset-sm-2 col-sm-10">
|
||||
<div class="form-check">
|
||||
<label><input type="checkbox" class="form-check-input" value="1" name="automap"{% if result.automap == '1' %} checked{% endif %}> {{ lang.edit.automap }} (--automap)</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-2">
|
||||
<div class="offset-sm-2 col-sm-10">
|
||||
<div class="form-check">
|
||||
<label><input type="checkbox" class="form-check-input" value="1" name="skipcrossduplicates"{% if result.skipcrossduplicates == '1' %} checked{% endif %}> {{ lang.edit.skipcrossduplicates }} (--skipcrossduplicates)</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-2">
|
||||
<div class="offset-sm-2 col-sm-10">
|
||||
<div class="form-check">
|
||||
<label><input type="checkbox" class="form-check-input" value="1" name="subscribeall"{% if result.subscribeall == '1' %} checked{% endif %}> {{ lang.add.subscribeall }} (--subscribeall)</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-2">
|
||||
<div class="offset-sm-2 col-sm-10">
|
||||
<div class="form-check">
|
||||
<label><input type="checkbox" class="form-check-input" value="1" name="dry"{% if result.dry == '1' %} checked{% endif %}> {{ lang.add.dry }} (--dry)</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-4">
|
||||
<div class="offset-sm-2 col-sm-10">
|
||||
<div class="form-check">
|
||||
<label><input type="checkbox" class="form-check-input" value="1" name="active"{% if result.active == '1' %} checked{% endif %}> {{ lang.edit.active }}</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-2">
|
||||
<div class="offset-sm-2 col-sm-10">
|
||||
<button class="btn btn-xs-lg d-block d-sm-inline btn-success" data-action="edit_selected" data-id="editsyncjob" data-item="{{ result.id }}" data-api-url='edit/syncjob' data-api-attr='{}' href="#">{{ lang.edit.save }}</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
{% else %}
|
||||
{{ parent() }}
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
49
data/web/templates/edit/tls_policy_map.twig
Executable file
49
data/web/templates/edit/tls_policy_map.twig
Executable file
|
|
@ -0,0 +1,49 @@
|
|||
{% extends 'edit.twig' %}
|
||||
|
||||
{% block inner_content %}
|
||||
{% if result %}
|
||||
<h4>{{ lang.mailbox.tls_policy_maps }}: {{ result.dest }}</h4>
|
||||
<br>
|
||||
<form class="form-horizontal" data-id="edit_tls_policy_maps" role="form" method="post">
|
||||
<input type="hidden" value="0" name="active">
|
||||
<div class="row mb-2">
|
||||
<label class="control-label col-sm-2" for="dest">{{ lang.mailbox.tls_map_dest }}</label>
|
||||
<div class="col-sm-10">
|
||||
<input value="{{ result.dest }}" type="text" class="form-control" name="dest" id="dest">
|
||||
<small>{{ lang.mailbox.tls_map_dest_info }}</small>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-2">
|
||||
<label class="control-label col-sm-2" for="policy">{{ lang.mailbox.tls_map_policy }}</label>
|
||||
<div class="col-sm-10">
|
||||
<select class="full-width-select" name="policy" required>
|
||||
{% for policy in policy_options %}
|
||||
<option value="{{ policy }}"{% if result.policy == policy %} selected{% endif %}>{{ policy }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-4">
|
||||
<label class="control-label col-sm-2" for="parameters">{{ lang.mailbox.tls_map_parameters }}</label>
|
||||
<div class="col-sm-10">
|
||||
<input value="{{ result.parameters }}" type="text" class="form-control" name="parameters" id="parameters">
|
||||
<small>{{ lang.mailbox.tls_map_parameters_info }}</small>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-2">
|
||||
<div class="offset-sm-2 col-sm-10">
|
||||
<div class="form-check">
|
||||
<label><input type="checkbox" class="form-check-input" value="1" name="active"{% if result.active == '1' %} checked{% endif %}> {{ lang.edit.active }}</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-2">
|
||||
<div class="offset-sm-2 col-sm-10">
|
||||
<button class="btn btn-xs-lg d-block d-sm-inline btn-success" data-action="edit_selected" data-id="edit_tls_policy_maps" data-item="{{ map }}" data-api-url='edit/tls-policy-map' data-api-attr='{}' href="#">{{ lang.edit.save }}</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
{% else %}
|
||||
{{ parent() }}
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
56
data/web/templates/edit/transport.twig
Executable file
56
data/web/templates/edit/transport.twig
Executable file
|
|
@ -0,0 +1,56 @@
|
|||
{% extends 'edit.twig' %}
|
||||
|
||||
{% block inner_content %}
|
||||
{% if result %}
|
||||
<h4>{{ lang.edit.resource }}</h4>
|
||||
<form class="form-horizontal" role="form" method="post" data-id="edittransport">
|
||||
<input type="hidden" value="0" name="active">
|
||||
<input type="hidden" value="0" name="is_mx_based">
|
||||
<div class="row mb-2">
|
||||
<label class="control-label col-sm-2" for="destination">{{ lang.add.destination }}</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="text" class="form-control" name="destination" value="{{ result.destination }}" required>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-4">
|
||||
<label class="control-label col-sm-2" for="nexthop">{{ lang.edit.nexthop }}</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="text" class="form-control" name="nexthop" placeholder='[0.0.0.0], [0.0.0.0]:25, host:25, host, [host]:25' value="{{ result.nexthop }}" required>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-2">
|
||||
<label class="control-label col-sm-2" for="username">{{ lang.add.username }}</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="text" class="form-control" name="username" value="{{ result.username }}">
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-4">
|
||||
<label class="control-label col-sm-2" for="password">{{ lang.add.password }}</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="text" data-hibp="true" class="form-control" name="password" value="{{ result.password }}">
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-2">
|
||||
<div class="offset-sm-2 col-sm-10">
|
||||
<div class="form-check">
|
||||
<label><input type="checkbox" class="form-check-input" value="1" name="is_mx_based"{% if result.is_mx_based == '1' %} checked{% endif %}> {{ lang.edit.lookup_mx|raw }}</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-2">
|
||||
<div class="offset-sm-2 col-sm-10">
|
||||
<div class="form-check">
|
||||
<label><input type="checkbox" class="form-check-input" value="1" name="active"{% if result.active == '1' %} checked{% endif %}> {{ lang.edit.active }}</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-2">
|
||||
<div class="offset-sm-2 col-sm-10">
|
||||
<button class="btn btn-xs-lg d-block d-sm-inline btn-success" data-action="edit_selected" data-id="edittransport" data-item="{{ result.id }}" data-api-url='edit/transport' data-api-attr='{}' href="#">{{ lang.edit.save }}</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
{% else %}
|
||||
{{ parent() }}
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
29
data/web/templates/fido2.twig
Executable file
29
data/web/templates/fido2.twig
Executable file
|
|
@ -0,0 +1,29 @@
|
|||
{% if fido2_data %}
|
||||
{% for key_info in fido2_data %}
|
||||
<tr>
|
||||
<td>
|
||||
{% if fido2_cid == key_info.cid %}
|
||||
<i class="bi bi-unlock-fill"></i>
|
||||
{% endif %}
|
||||
{% if key_info.fn %}
|
||||
{{ key_info.fn }}
|
||||
{% else %}
|
||||
{{ key_info.subject }}
|
||||
{% endif %}
|
||||
</td>
|
||||
<td style="min-width:240px;text-align: right">
|
||||
<form style="display:inline;" method="post">
|
||||
<input type="hidden" name="unset_fido2_key" value="{{ key_info.cid }}">
|
||||
<div class="btn-group">
|
||||
<a href="#" class="btn btn-sm btn-xs-lg btn-secondary" data-cid="{{ key_info.cid }}" data-subject="{{ key_info.subject|base64_encode }}" data-bs-toggle="modal" data-bs-target="#fido2ChangeFn">
|
||||
<i class="bi bi-pencil-fill"></i> {{ lang.fido2.rename }}
|
||||
</a>
|
||||
<a href="#" onClick='return confirm("{{ lang.admin.ays }}")?$(this).closest("form").submit():"";' class="btn btn-sm btn-xs-lg btn-danger">
|
||||
<i class="bi bi-trash"></i> {{ lang.admin.remove }}
|
||||
</a>
|
||||
</div>
|
||||
</form>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
115
data/web/templates/index.twig
Executable file
115
data/web/templates/index.twig
Executable file
|
|
@ -0,0 +1,115 @@
|
|||
{% extends 'base.twig' %}
|
||||
|
||||
{% block navbar %}{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="row mb-4" style="margin-top: 60px">
|
||||
<div class="col-12 col-md-7 col-lg-6 col-xl-5 ms-auto me-auto">
|
||||
<div class="card">
|
||||
<div class="card-header d-flex align-items-center">
|
||||
<i class="bi bi-person-fill me-2"></i> {{ lang.login.login }}
|
||||
<div class="ms-auto form-check form-switch my-auto d-flex align-items-center">
|
||||
<label class="form-check-label"><i class="bi bi-moon-fill"></i></label>
|
||||
<input class="form-check-input ms-2" type="checkbox" id="dark-mode-toggle">
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="text-center mailcow-logo mb-4">
|
||||
<img class="main-logo" src="{{ logo|default('/img/cow_mailcow.svg') }}" alt="mailcow">
|
||||
<img class="main-logo-dark" src="{{ logo_dark|default('/img/cow_mailcow.svg') }}" alt="mailcow-logo-dark">
|
||||
</div>
|
||||
{% if ui_texts.ui_announcement_text and ui_texts.ui_announcement_active %}
|
||||
<div class="my-4 alert alert-{{ ui_texts.ui_announcement_type }} rot-enc ui-announcement-alert">{{ ui_texts.ui_announcement_text|rot13 }}</div>
|
||||
{% endif %}
|
||||
<legend>{% if oauth2_request %}{{ lang.oauth2.authorize_app }}{% else %}{{ ui_texts.main_name|raw }}{% endif %}</legend><hr />
|
||||
{% if is_mobileconfig %}
|
||||
<div class="my-4 alert alert-info ">{{ lang.login.mobileconfig_info }}</div>
|
||||
{% endif %}
|
||||
<form method="post" autofill="off">
|
||||
<div class="d-flex mt-3">
|
||||
<label class="visually-hidden" for="login_user">{{ lang.login.username }}</label>
|
||||
<div class="input-group">
|
||||
<div class="input-group-text"><i class="bi bi-person-fill"></i></div>
|
||||
<input name="login_user" autocorrect="off" autocapitalize="none" type="{% if is_mobileconfig %}email{% else %}text{% endif %}" id="login_user" class="form-control" placeholder="{{ lang.login.username }}" required="" autofocus="" autocomplete="username">
|
||||
</div>
|
||||
</div>
|
||||
<div class="d-flex mt-3">
|
||||
<label class="visually-hidden" for="pass_user">{{ lang.login.password }}</label>
|
||||
<div class="input-group">
|
||||
<div class="input-group-text"><i class="bi bi-lock-fill"></i></div>
|
||||
<input name="pass_user" type="password" id="pass_user" class="form-control" placeholder="{{ lang.login.password }}" required="" autocomplete="current-password">
|
||||
</div>
|
||||
</div>
|
||||
<div class="d-flex justify-content-between mt-4" style="position: relative">
|
||||
<div class="d-grid gap-2 d-sm-block">
|
||||
<button type="submit" class="btn btn-xs-lg btn-success" value="Login">{{ lang.login.login }}</button>
|
||||
<button type="button" class="btn btn-xs-lg btn-success" id="fido2-login"><i class="bi bi-shield-fill-check"></i> {{ lang.login.fido2_webauthn }}</button>
|
||||
</div>
|
||||
{% if not oauth2_request %}
|
||||
<div class="d-grid d-sm-block">
|
||||
<button type="button" {% if available_languages|length == 1 %}disabled="true"{% endif %} class="btn btn-secondary ms-auto dropdown-toggle" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
||||
<span class="flag-icon flag-icon-{{ mailcow_locale[-2:] }}"></span>
|
||||
</button>
|
||||
<ul class="dropdown-menu ms-auto login">
|
||||
{% for key, val in available_languages %}
|
||||
<li>
|
||||
<a class="dropdown-item {% if mailcow_locale == key %}active{% endif %}" href="?{{ query_string({'lang': key}) }}">
|
||||
<span class="flag-icon flag-icon-{{ key[-2:] }}"></span>{{ val }}
|
||||
</a>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</form>
|
||||
<div class="mt-3 mb-4">
|
||||
<a href="/reset-password">{{ lang.login.forgot_password }}</a>
|
||||
</div>
|
||||
{% if login_delay %}
|
||||
<p><div class="my-4 alert alert-info">{{ lang.login.delayed|format(login_delay) }}</b></div></p>
|
||||
{% endif %}
|
||||
<div class="my-4" id="fido2-alerts"></div>
|
||||
{% if not oauth2_request and (mailcow_apps or app_links) %}
|
||||
<legend><i class="bi bi-link-45deg"></i> {{ ui_texts.apps_name|raw }}</legend><hr />
|
||||
<div class="my-2 d-grid gap-2 d-sm-block apps">
|
||||
{% for app in mailcow_apps %}
|
||||
{% if not skip_sogo or not is_uri('SOGo', app.link) %}
|
||||
<a href="{{ app.link }}" role="button" {% if app.description %}title="{{ app.description }}"{% endif %} class="btn btn-primary">{{ app.name }}</a>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% for row in app_links %}
|
||||
{% for key, val in row %}
|
||||
<a href="{{ val }}" role="button" class="btn btn-primary">{{ key }}</a>
|
||||
{% endfor %}
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% if not oauth2_request %}
|
||||
<div class="row">
|
||||
<div class="col-12 col-md-7 col-lg-6 col-xl-5 ms-auto me-auto">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<a class="btn btn-link" data-bs-toggle="collapse" href="#collapse1"><i class="bi bi-patch-question-fill"></i> {{ lang.start.help }}</a>
|
||||
</div>
|
||||
<div id="collapse1" class="card-collapse collapse">
|
||||
<div class="card-body">
|
||||
{% if ui_texts.help_text %}
|
||||
<p>{{ ui_texts.help_text|raw }}</p>
|
||||
{% else %}
|
||||
<p><span style="border-bottom: 1px dotted #999;">{{ ui_texts.main_name|raw }}</span></p>
|
||||
<p>{{ lang.start.mailcow_panel_detail|raw }}</p>
|
||||
<p><span style="border-bottom: 1px dotted #999;">{{ ui_texts.apps_name|raw }}</span></p>
|
||||
<p>{{ lang.start.mailcow_apps_detail|raw }}</p>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endblock %}
|
||||
78
data/web/templates/mailbox.twig
Executable file
78
data/web/templates/mailbox.twig
Executable file
|
|
@ -0,0 +1,78 @@
|
|||
{% extends 'base.twig' %}
|
||||
|
||||
{% block content %}
|
||||
<div id="mail-content" class="responsive-tabs">
|
||||
<ul class="nav nav-tabs" role="tablist">
|
||||
{% if mailcow_cc_role == 'admin' %}
|
||||
<li class="nav-item dropdown" role="presentation">
|
||||
<a class="nav-link dropdown-toggle active" data-bs-toggle="dropdown" href="#">{{ lang.mailbox.domains }}</a>
|
||||
<ul class="dropdown-menu">
|
||||
<li><button class="dropdown-item" aria-selected="false" aria-controls="tab-domains" role="tab" data-bs-toggle="tab" data-bs-target="#tab-domains">{{ lang.mailbox.domains }}</button></li>
|
||||
<li><button class="dropdown-item" aria-selected="false" aria-controls="tab-templates-domains" role="tab" data-bs-toggle="tab" data-bs-target="#tab-templates-domains">{{ lang.mailbox.templates }}</button></li>
|
||||
</ul>
|
||||
</li>
|
||||
{% else %}
|
||||
<li class="nav-item" role="presentation"><button class="nav-link" aria-controls="tab-domains" role="tab" data-bs-toggle="tab" data-bs-target="#tab-domains">{{ lang.mailbox.domains }}</button></li>
|
||||
{% endif %}
|
||||
{% if mailcow_cc_role == 'admin' %}
|
||||
<li class="nav-item dropdown" role="presentation">
|
||||
<a class="nav-link dropdown-toggle" data-bs-toggle="dropdown" href="#">{{ lang.mailbox.mailboxes }}</a>
|
||||
<ul class="dropdown-menu">
|
||||
<li><button class="dropdown-item" aria-selected="false" aria-controls="tab-mailboxes" role="tab" data-bs-toggle="tab" data-bs-target="#tab-mailboxes">{{ lang.mailbox.mailboxes }}</button></li>
|
||||
<li><button class="dropdown-item" aria-selected="false" aria-controls="tab-templates-mbox" role="tab" data-bs-toggle="tab" data-bs-target="#tab-templates-mbox">{{ lang.mailbox.templates }}</button></li>
|
||||
</ul>
|
||||
</li>
|
||||
{% else %}
|
||||
<li class="nav-item" role="presentation"><button class="nav-link" aria-controls="tab-mailboxes" role="tab" data-bs-toggle="tab" data-bs-target="#tab-mailboxes">{{ lang.mailbox.mailboxes }}</button></li>
|
||||
{% endif %}
|
||||
<li class="nav-item" role="presentation"><button class="nav-link" aria-controls="tab-resources" role="tab" data-bs-toggle="tab" data-bs-target="#tab-resources">{{ lang.mailbox.resources }}</button></li>
|
||||
<li class="nav-item dropdown">
|
||||
<a class="nav-link dropdown-toggle" data-bs-toggle="dropdown" href="#">{{ lang.mailbox.aliases }}</a>
|
||||
<ul class="dropdown-menu">
|
||||
<li role="presentation"><button class="dropdown-item" aria-selected="false" aria-controls="tab-mbox-aliases" role="tab" data-bs-toggle="tab" data-bs-target="#tab-mbox-aliases">{{ lang.mailbox.aliases }}</button></li>
|
||||
<li role="presentation"><button class="dropdown-item" aria-selected="false" aria-controls="tab-domain-aliases" role="tab" data-bs-toggle="tab" data-bs-target="#tab-domain-aliases">{{ lang.mailbox.domain_aliases }}</button></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="nav-item" role="presentation"><button class="nav-link" aria-selected="false" aria-controls="tab-syncjobs" role="tab" data-bs-toggle="tab" data-bs-target="#tab-syncjobs">{{ lang.mailbox.sync_jobs }}</button></li>
|
||||
<li class="nav-item" role="presentation"><button class="nav-link" aria-selected="false" aria-controls="tab-filters" role="tab" data-bs-toggle="tab" data-bs-target="#tab-filters">{{ lang.mailbox.filters }}</button></li>
|
||||
<li class="nav-item" role="presentation"><button class="nav-link" aria-selected="false" aria-controls="tab-bcc" role="tab" data-bs-toggle="tab" data-bs-target="#tab-bcc">{{ lang.mailbox.address_rewriting }}</button></li>
|
||||
<li class="nav-item" role="presentation"{% if mailcow_cc_role != 'admin' %} class="d-none"{% endif %}><button class="nav-link" aria-selected="false" aria-controls="tab-tls-policy" role="tab" data-bs-toggle="tab" data-bs-target="#tab-tls-policy">{{ lang.mailbox.tls_policy_maps }}</button></li>
|
||||
</ul>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<div class="tab-content" style="padding-top:20px">
|
||||
{% include 'mailbox/tab-domains.twig' %}
|
||||
{% if mailcow_cc_role == 'admin' %}
|
||||
{% include 'mailbox/tab-templates-domains.twig' %}
|
||||
{% endif %}
|
||||
{% include 'mailbox/tab-mailboxes.twig' %}
|
||||
{% if mailcow_cc_role == 'admin' %}
|
||||
{% include 'mailbox/tab-templates-mbox.twig' %}
|
||||
{% endif %}
|
||||
{% include 'mailbox/tab-resources.twig' %}
|
||||
{% include 'mailbox/tab-domain-aliases.twig' %}
|
||||
{% include 'mailbox/tab-mbox-aliases.twig' %}
|
||||
{% include 'mailbox/tab-syncjobs.twig' %}
|
||||
{% include 'mailbox/tab-filters.twig' %}
|
||||
{% include 'mailbox/tab-bcc.twig' %}
|
||||
{% include 'mailbox/tab-tls-policy.twig' %}
|
||||
</div> <!-- /tab-content -->
|
||||
</div> <!-- /col-md-12 -->
|
||||
</div> <!-- /row -->
|
||||
</div>
|
||||
|
||||
{% include 'modals/mailbox.twig' %}
|
||||
|
||||
<script type='text/javascript'>
|
||||
var acl = '{{ acl_json|raw }}';
|
||||
var lang = {{ lang_mailbox|raw }};
|
||||
var lang_rl = {{ lang_rl|raw }};
|
||||
var lang_datatables = {{ lang_datatables|raw }};
|
||||
var csrf_token = '{{ csrf_token }}';
|
||||
var pagination_size = Math.trunc('{{ pagination_size }}');
|
||||
var role = '{{ role }}';
|
||||
var is_dual = {{ is_dual }};
|
||||
var ALLOW_ADMIN_EMAIL_LOGIN = {{ allow_admin_email_login }};
|
||||
</script>
|
||||
{% endblock %}
|
||||
4
data/web/templates/mailbox/rl-frame.twig
Executable file
4
data/web/templates/mailbox/rl-frame.twig
Executable file
|
|
@ -0,0 +1,4 @@
|
|||
<option value="s"{% if rl.frame == 's' %} selected{% endif %}>{{ lang.ratelimit.second }}</option>
|
||||
<option value="m"{% if rl.frame == 'm' %} selected{% endif %}>{{ lang.ratelimit.minute }}</option>
|
||||
<option value="h"{% if rl.frame == 'h' %} selected{% endif %}>{{ lang.ratelimit.hour }}</option>
|
||||
<option value="d"{% if rl.frame == 'd' %} selected{% endif %}>{{ lang.ratelimit.day }}</option>
|
||||
104
data/web/templates/mailbox/tab-bcc.twig
Executable file
104
data/web/templates/mailbox/tab-bcc.twig
Executable file
|
|
@ -0,0 +1,104 @@
|
|||
<div class="tab-pane fade" id="tab-bcc" role="tabpanel" aria-labelledby="tab-bcc">
|
||||
<div class="card mb-4">
|
||||
<div class="card-header d-flex fs-5">
|
||||
<button class="btn d-md-none flex-grow-1 text-start" data-bs-target="#collapse-tab-bcc" data-bs-toggle="collapse" aria-controls="collapse-tab-bcc">
|
||||
{{ lang.mailbox.bcc_maps }} <span class="badge bg-info table-lines"></span>
|
||||
</button>
|
||||
<span class="d-none d-md-block">{{ lang.mailbox.bcc_maps }} <span class="badge bg-info table-lines"></span></span>
|
||||
|
||||
<div class="btn-group ms-auto d-flex">
|
||||
<button class="btn btn-xs btn-secondary refresh_table" data-draw="draw_bcc_table" data-table="bcc_table">{{ lang.admin.refresh }}</button>
|
||||
</div>
|
||||
</div>
|
||||
<div id="collapse-tab-bcc" class="card-body collapse" data-bs-parent="#mail-content">
|
||||
<div class="mass-actions-mailbox mb-4 d-none d-sm-block">
|
||||
<div class="btn-group" data-acl="{{ acl.bcc_maps }}">
|
||||
<a class="btn btn-sm btn-xs-half btn-secondary" id="toggle_multi_select_all" data-id="bcc" href="#"><i class="bi bi-check-all"></i> {{ lang.mailbox.toggle_all }}</a>
|
||||
<a class="btn btn-sm btn-xs-half btn-secondary dropdown-toggle" data-bs-toggle="dropdown" href="#">{{ lang.mailbox.quick_actions }}</a>
|
||||
<ul class="dropdown-menu">
|
||||
<li><a class="dropdown-item" data-action="edit_selected" data-id="bcc" data-api-url='edit/bcc' data-api-attr='{"active":"1"}' href="#">{{ lang.mailbox.activate }}</a></li>
|
||||
<li><a class="dropdown-item" data-action="edit_selected" data-id="bcc" data-api-url='edit/bcc' data-api-attr='{"active":"0"}' href="#">{{ lang.mailbox.deactivate }}</a></li>
|
||||
<li><hr class="dropdown-divider"></li>
|
||||
<li><a class="dropdown-item" data-action="edit_selected" data-id="bcc" data-api-url='edit/bcc' data-api-attr='{"type":"sender"}' href="#">{{ lang.mailbox.bcc_to_sender }}</a></li>
|
||||
<li><a class="dropdown-item" data-action="edit_selected" data-id="bcc" data-api-url='edit/bcc' data-api-attr='{"type":"rcpt"}' href="#">{{ lang.mailbox.bcc_to_rcpt }}</a></li>
|
||||
<li><hr class="dropdown-divider"></li>
|
||||
<li><a class="dropdown-item" data-action="delete_selected" data-id="bcc" data-api-url='delete/bcc' href="#">{{ lang.mailbox.remove }}</a></li>
|
||||
<li class="table_collapse_option"><hr class="dropdown-divider"></li>
|
||||
<li class="table_collapse_option"><a class="dropdown-item" data-datatables-expand="bcc_table">{{ lang.datatables.expand_all }}</a></li>
|
||||
<li class="table_collapse_option"><a class="dropdown-item" data-datatables-collapse="bcc_table">{{ lang.datatables.collapse_all }}</a></li>
|
||||
</ul>
|
||||
<a class="btn btn-sm btn-success" href="#" data-bs-toggle="modal" data-bs-target="#addBCCModalAdmin"><i class="bi bi-plus-lg"></i> {{ lang.mailbox.add_bcc_entry }}</a>
|
||||
</div>
|
||||
</div>
|
||||
<p class="text-muted">{{ lang.mailbox.bcc_info|raw }}</p>
|
||||
<table id="bcc_table" class="table table-striped dt-responsive w-100"></table>
|
||||
<div class="mass-actions-mailbox mt-4">
|
||||
<div class="btn-group" data-acl="{{ acl.bcc_maps }}">
|
||||
<a class="btn btn-sm btn-xs-lg btn-xs-half btn-secondary" id="toggle_multi_select_all" data-id="bcc" href="#"><i class="bi bi-check-all"></i> {{ lang.mailbox.toggle_all }}</a>
|
||||
<a class="btn btn-sm btn-xs-lg btn-xs-half btn-secondary dropdown-toggle" data-bs-toggle="dropdown" href="#">{{ lang.mailbox.quick_actions }}</a>
|
||||
<ul class="dropdown-menu">
|
||||
<li><a class="dropdown-item" data-action="edit_selected" data-id="bcc" data-api-url='edit/bcc' data-api-attr='{"active":"1"}' href="#">{{ lang.mailbox.activate }}</a></li>
|
||||
<li><a class="dropdown-item" data-action="edit_selected" data-id="bcc" data-api-url='edit/bcc' data-api-attr='{"active":"0"}' href="#">{{ lang.mailbox.deactivate }}</a></li>
|
||||
<li><hr class="dropdown-divider"></li>
|
||||
<li><a class="dropdown-item" data-action="edit_selected" data-id="bcc" data-api-url='edit/bcc' data-api-attr='{"type":"sender"}' href="#">{{ lang.mailbox.bcc_to_sender }}</a></li>
|
||||
<li><a class="dropdown-item" data-action="edit_selected" data-id="bcc" data-api-url='edit/bcc' data-api-attr='{"type":"rcpt"}' href="#">{{ lang.mailbox.bcc_to_rcpt }}</a></li>
|
||||
<li><hr class="dropdown-divider"></li>
|
||||
<li><a class="dropdown-item" data-action="delete_selected" data-id="bcc" data-api-url='delete/bcc' href="#">{{ lang.mailbox.remove }}</a></li>
|
||||
<li class="table_collapse_option"><hr class="dropdown-divider"></li>
|
||||
<li class="table_collapse_option"><a class="dropdown-item" data-datatables-expand="bcc_table">{{ lang.datatables.expand_all }}</a></li>
|
||||
<li class="table_collapse_option"><a class="dropdown-item" data-datatables-collapse="bcc_table">{{ lang.datatables.collapse_all }}</a></li>
|
||||
</ul>
|
||||
<a class="btn btn-sm btn-xs-lg btn-success" href="#" data-bs-toggle="modal" data-bs-target="#addBCCModalAdmin"><i class="bi bi-plus-lg"></i> {{ lang.mailbox.add_bcc_entry }}</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card mb-4{% if mailcow_cc_role != 'admin' %} d-none{% endif %}">
|
||||
<div class="card-header d-flex fs-5">
|
||||
<button class="btn d-md-none flex-grow-1 text-start" data-bs-target="#collapse-tab-bcc-filters" data-bs-toggle="collapse" aria-controls="collapse-tab-bcc-filters">
|
||||
{{ lang.mailbox.recipient_maps }} <span class="badge bg-info table-lines"></span>
|
||||
</button>
|
||||
<span class="d-none d-md-block">{{ lang.mailbox.recipient_maps }} <span class="badge bg-info table-lines"></span></span>
|
||||
|
||||
<div class="btn-group ms-auto d-flex">
|
||||
<button class="btn btn-xs btn-secondary refresh_table" data-draw="draw_recipient_map_table" data-table="recipient_map_table">{{ lang.admin.refresh }}</button>
|
||||
</div>
|
||||
</div>
|
||||
<div id="collapse-tab-bcc-filters" class="card-body collapse" data-bs-parent="#mail-content">
|
||||
<div class="mass-actions-mailbox mb-4 d-none d-sm-block">
|
||||
<div class="btn-group">
|
||||
<a class="btn btn-sm btn-xs-half btn-secondary" id="toggle_multi_select_all" data-id="recipient_map" href="#"><i class="bi bi-check-all"></i> {{ lang.mailbox.toggle_all }}</a>
|
||||
<a class="btn btn-sm btn-xs-half btn-secondary dropdown-toggle" data-bs-toggle="dropdown" href="#">{{ lang.mailbox.quick_actions }}</a>
|
||||
<ul class="dropdown-menu">
|
||||
<li><a class="dropdown-item" data-action="edit_selected" data-id="recipient_map" data-api-url='edit/recipient_map' data-api-attr='{"active":"1"}' href="#">{{ lang.mailbox.activate }}</a></li>
|
||||
<li><a class="dropdown-item" data-action="edit_selected" data-id="recipient_map" data-api-url='edit/recipient_map' data-api-attr='{"active":"0"}' href="#">{{ lang.mailbox.deactivate }}</a></li>
|
||||
<li><hr class="dropdown-divider"></li>
|
||||
<li><a class="dropdown-item" data-action="delete_selected" data-id="recipient_map" data-api-url='delete/recipient_map' href="#">{{ lang.mailbox.remove }}</a></li>
|
||||
<li class="table_collapse_option"><hr class="dropdown-divider"></li>
|
||||
<li class="table_collapse_option"><a class="dropdown-item" data-datatables-expand="recipient_map_table">{{ lang.datatables.expand_all }}</a></li>
|
||||
<li class="table_collapse_option"><a class="dropdown-item" data-datatables-collapse="recipient_map_table">{{ lang.datatables.collapse_all }}</a></li>
|
||||
</ul>
|
||||
<a class="btn btn-sm btn-success" href="#" data-bs-toggle="modal" data-bs-target="#addRecipientMapModalAdmin"><i class="bi bi-plus-lg"></i> {{ lang.mailbox.add_recipient_map_entry }}</a>
|
||||
</div>
|
||||
</div>
|
||||
<p class="text-muted">{{ lang.mailbox.recipient_map_info }}</p>
|
||||
<table id="recipient_map_table" class="table table-striped dt-responsive w-100"></table>
|
||||
<div class="mass-actions-mailbox mt-4">
|
||||
<div class="btn-group">
|
||||
<a class="btn btn-sm btn-xs-lg btn-xs-half btn-secondary" id="toggle_multi_select_all" data-id="recipient_map" href="#"><i class="bi bi-check-all"></i> {{ lang.mailbox.toggle_all }}</a>
|
||||
<a class="btn btn-sm btn-xs-lg btn-xs-half btn-secondary dropdown-toggle" data-bs-toggle="dropdown" href="#">{{ lang.mailbox.quick_actions }}</a>
|
||||
<ul class="dropdown-menu">
|
||||
<li><a class="dropdown-item" data-action="edit_selected" data-id="recipient_map" data-api-url='edit/recipient_map' data-api-attr='{"active":"1"}' href="#">{{ lang.mailbox.activate }}</a></li>
|
||||
<li><a class="dropdown-item" data-action="edit_selected" data-id="recipient_map" data-api-url='edit/recipient_map' data-api-attr='{"active":"0"}' href="#">{{ lang.mailbox.deactivate }}</a></li>
|
||||
<li><hr class="dropdown-divider"></li>
|
||||
<li><a class="dropdown-item" data-action="delete_selected" data-id="recipient_map" data-api-url='delete/recipient_map' href="#">{{ lang.mailbox.remove }}</a></li>
|
||||
<li class="table_collapse_option"><hr class="dropdown-divider"></li>
|
||||
<li class="table_collapse_option"><a class="dropdown-item" data-datatables-expand="recipient_map_table">{{ lang.datatables.expand_all }}</a></li>
|
||||
<li class="table_collapse_option"><a class="dropdown-item" data-datatables-collapse="recipient_map_table">{{ lang.datatables.collapse_all }}</a></li>
|
||||
</ul>
|
||||
<a class="btn btn-sm btn-xs-lg btn-success" href="#" data-bs-toggle="modal" data-bs-target="#addRecipientMapModalAdmin"><i class="bi bi-plus-lg"></i> {{ lang.mailbox.add_recipient_map_entry }}</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
49
data/web/templates/mailbox/tab-domain-aliases.twig
Executable file
49
data/web/templates/mailbox/tab-domain-aliases.twig
Executable file
|
|
@ -0,0 +1,49 @@
|
|||
<div class="tab-pane fade" id="tab-domain-aliases" role="tabpanel" aria-labelledby="tab-domain-aliases">
|
||||
<div class="card mb-4">
|
||||
<div class="card-header d-flex fs-5">
|
||||
<button class="btn d-md-none flex-grow-1 text-start" data-bs-target="#collapse-tab-domain-aliases" data-bs-toggle="collapse" aria-controls="collapse-tab-domain-aliases">
|
||||
{{ lang.mailbox.domain_aliases }} <span class="badge bg-info table-lines"></span>
|
||||
</button>
|
||||
<span class="d-none d-md-block">{{ lang.mailbox.domain_aliases }} <span class="badge bg-info table-lines"></span></span>
|
||||
|
||||
<div class="btn-group ms-auto d-flex">
|
||||
<button class="btn btn-xs btn-secondary refresh_table" data-draw="draw_aliasdomain_table" data-table="aliasdomain_table">{{ lang.admin.refresh }}</button>
|
||||
</div>
|
||||
</div>
|
||||
<div id="collapse-tab-domain-aliases" class="card-body collapse" data-bs-parent="#mail-content">
|
||||
<div class="mass-actions-mailbox mb-4 d-none d-sm-block">
|
||||
<div class="btn-group">
|
||||
<a class="btn btn-sm btn-xs-half btn-secondary" id="toggle_multi_select_all" data-id="alias-domain" href="#"><i class="bi bi-check-all"></i> {{ lang.mailbox.toggle_all }}</a>
|
||||
<a class="btn btn-sm btn-xs-half btn-secondary dropdown-toggle" data-bs-toggle="dropdown" href="#">{{ lang.mailbox.quick_actions }}</a>
|
||||
<ul class="dropdown-menu">
|
||||
<li><a class="dropdown-item" data-action="edit_selected" data-id="alias-domain" data-api-url='edit/alias-domain' data-api-attr='{"active":"1"}' href="#">{{ lang.mailbox.activate }}</a></li>
|
||||
<li><a class="dropdown-item" data-action="edit_selected" data-id="alias-domain" data-api-url='edit/alias-domain' data-api-attr='{"active":"0"}' href="#">{{ lang.mailbox.deactivate }}</a></li>
|
||||
<li><hr class="dropdown-divider"></li>
|
||||
<li><a class="dropdown-item" data-action="delete_selected" data-id="alias-domain" data-api-url='delete/alias-domain' href="#">{{ lang.mailbox.remove }}</a></li>
|
||||
<li class="table_collapse_option"><hr class="dropdown-divider"></li>
|
||||
<li class="table_collapse_option"><a class="dropdown-item" data-datatables-expand="aliasdomain_table">{{ lang.datatables.expand_all }}</a></li>
|
||||
<li class="table_collapse_option"><a class="dropdown-item" data-datatables-collapse="aliasdomain_table">{{ lang.datatables.collapse_all }}</a></li>
|
||||
</ul>
|
||||
<a class="btn btn-sm btn-success" href="#" data-acl="{{ acl.alias_domains }}" data-bs-toggle="modal" data-bs-target="#addAliasDomainModal"><i class="bi bi-plus-lg"></i> {{ lang.mailbox.add_domain_alias }}</a>
|
||||
</div>
|
||||
</div>
|
||||
<table id="aliasdomain_table" class="table table-striped dt-responsive w-100"></table>
|
||||
<div class="mass-actions-mailbox mt-4">
|
||||
<div class="btn-group">
|
||||
<a class="btn btn-sm btn-xs-lg btn-xs-half btn-secondary" id="toggle_multi_select_all" data-id="alias-domain" href="#"><i class="bi bi-check-all"></i> {{ lang.mailbox.toggle_all }}</a>
|
||||
<a class="btn btn-sm btn-xs-lg btn-xs-half btn-secondary dropdown-toggle" data-bs-toggle="dropdown" href="#">{{ lang.mailbox.quick_actions }}</a>
|
||||
<ul class="dropdown-menu">
|
||||
<li><a class="dropdown-item" data-action="edit_selected" data-id="alias-domain" data-api-url='edit/alias-domain' data-api-attr='{"active":"1"}' href="#">{{ lang.mailbox.activate }}</a></li>
|
||||
<li><a class="dropdown-item" data-action="edit_selected" data-id="alias-domain" data-api-url='edit/alias-domain' data-api-attr='{"active":"0"}' href="#">{{ lang.mailbox.deactivate }}</a></li>
|
||||
<li><hr class="dropdown-divider"></li>
|
||||
<li><a class="dropdown-item" data-action="delete_selected" data-id="alias-domain" data-api-url='delete/alias-domain' href="#">{{ lang.mailbox.remove }}</a></li>
|
||||
<li class="table_collapse_option"><hr class="dropdown-divider"></li>
|
||||
<li class="table_collapse_option"><a class="dropdown-item" data-datatables-expand="aliasdomain_table">{{ lang.datatables.expand_all }}</a></li>
|
||||
<li class="table_collapse_option"><a class="dropdown-item" data-datatables-collapse="aliasdomain_table">{{ lang.datatables.collapse_all }}</a></li>
|
||||
</ul>
|
||||
<a class="btn btn-sm btn-xs-lg btn-success" href="#" data-acl="{{ acl.alias_domains }}" data-bs-toggle="modal" data-bs-target="#addAliasDomainModal"><i class="bi bi-plus-lg"></i> {{ lang.mailbox.add_domain_alias }}</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
58
data/web/templates/mailbox/tab-domains.twig
Executable file
58
data/web/templates/mailbox/tab-domains.twig
Executable file
|
|
@ -0,0 +1,58 @@
|
|||
<div class="tab-pane fade show active" id="tab-domains" role="tabpanel" aria-labelledby="tab-domains">
|
||||
<div class="card mb-4">
|
||||
<div class="card-header d-flex fs-5">
|
||||
<button class="btn d-sm-block d-md-none flex-grow-1 text-start" data-bs-target="#collapse-tab-domains" data-bs-toggle="collapse" aria-controls="collapse-tab-domains">
|
||||
{{ lang.mailbox.domains }} <span class="badge bg-info table-lines"></span>
|
||||
</button>
|
||||
<span class="d-none d-md-block">{{ lang.mailbox.domains }} <span class="badge bg-info table-lines"></span></span>
|
||||
|
||||
<div class="btn-group ms-auto d-flex">
|
||||
<button class="btn btn-xs btn-secondary refresh_table" data-draw="draw_domain_table" data-table="domain_table">{{ lang.admin.refresh }}</button>
|
||||
</div>
|
||||
</div>
|
||||
<div id="collapse-tab-domains" class="card-body collapse show" data-bs-parent="#mail-content">
|
||||
{#<div class="mass-actions-mailbox" data-actions-header="true"></div>#}
|
||||
<div class="mass-actions-mailbox mb-4 d-none d-sm-block">
|
||||
<div class="btn-group">
|
||||
<button class="btn btn-sm btn-xs-half btn-secondary" id="toggle_multi_select_all" data-id="domain" href="#"><i class="bi bi-check-all"></i> {{ lang.mailbox.toggle_all }}</button>
|
||||
<button class="btn btn-sm btn-xs-half btn-secondary dropdown-toggle" data-bs-toggle="dropdown" href="#">{{ lang.mailbox.quick_actions }}</button>
|
||||
<ul class="dropdown-menu">
|
||||
{% if mailcow_cc_role == 'admin' %}
|
||||
<li><a class="dropdown-item" data-action="edit_selected" data-id="domain" data-api-url='edit/domain' data-api-attr='{"active":"1"}' href="#">{{ lang.mailbox.activate }}</a></li>
|
||||
<li><a class="dropdown-item" data-action="edit_selected" data-id="domain" data-api-url='edit/domain' data-api-attr='{"active":"0"}' href="#">{{ lang.mailbox.deactivate }}</a></li>
|
||||
<li><hr class="dropdown-divider"></li>
|
||||
<li><a class="dropdown-item" data-action="delete_selected" data-id="domain" data-api-url='delete/domain' href="#">{{ lang.mailbox.remove }}</a></li>
|
||||
<li class="table_collapse_option"><hr class="dropdown-divider"></li>
|
||||
{% endif %}
|
||||
<li class="table_collapse_option"><a class="dropdown-item" data-datatables-expand="domain_table">{{ lang.datatables.expand_all }}</a></li>
|
||||
<li class="table_collapse_option"><a class="dropdown-item" data-datatables-collapse="domain_table">{{ lang.datatables.collapse_all }}</a></li>
|
||||
</ul>
|
||||
{% if mailcow_cc_role == 'admin' %}
|
||||
<button class="btn btn-sm btn-success" data-bs-toggle="modal" data-bs-target="#addDomainModal"><i class="bi bi-plus-lg"></i> {{ lang.mailbox.add_domain }}</button>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
<table id="domain_table" class="table table-striped dt-responsive w-100"></table>
|
||||
<div class="mass-actions-mailbox mt-4">
|
||||
<div class="btn-group">
|
||||
<button class="btn btn-sm btn-xs-lg btn-xs-half btn-secondary" id="toggle_multi_select_all" data-id="domain" href="#"><i class="bi bi-check-all"></i> {{ lang.mailbox.toggle_all }}</button>
|
||||
<button class="btn btn-sm btn-xs-lg btn-xs-half btn-secondary dropdown-toggle" data-bs-toggle="dropdown" href="#">{{ lang.mailbox.quick_actions }}</button>
|
||||
<ul class="dropdown-menu">
|
||||
{% if mailcow_cc_role == 'admin' %}
|
||||
<li><a class="dropdown-item" data-action="edit_selected" data-id="domain" data-api-url='edit/domain' data-api-attr='{"active":"1"}' href="#">{{ lang.mailbox.activate }}</a></li>
|
||||
<li><a class="dropdown-item" data-action="edit_selected" data-id="domain" data-api-url='edit/domain' data-api-attr='{"active":"0"}' href="#">{{ lang.mailbox.deactivate }}</a></li>
|
||||
<li><hr class="dropdown-divider"></li>
|
||||
<li><a class="dropdown-item" data-action="delete_selected" data-id="domain" data-api-url='delete/domain' href="#">{{ lang.mailbox.remove }}</a></li>
|
||||
<li class="table_collapse_option"><hr class="dropdown-divider"></li>
|
||||
{% endif %}
|
||||
<li class="table_collapse_option"><a class="dropdown-item" data-datatables-expand="domain_table">{{ lang.datatables.expand_all }}</a></li>
|
||||
<li class="table_collapse_option"><a class="dropdown-item" data-datatables-collapse="domain_table">{{ lang.datatables.collapse_all }}</a></li>
|
||||
</ul>
|
||||
{% if mailcow_cc_role == 'admin' %}
|
||||
<button class="btn btn-sm btn-xs-lg btn-success" href="#" data-bs-toggle="modal" data-bs-target="#addDomainModal"><i class="bi bi-plus-lg"></i> {{ lang.mailbox.add_domain }}</button>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
96
data/web/templates/mailbox/tab-filters.twig
Executable file
96
data/web/templates/mailbox/tab-filters.twig
Executable file
|
|
@ -0,0 +1,96 @@
|
|||
<div class="tab-pane fade" id="tab-filters" role="tabpanel" aria-labelledby="tab-filters">
|
||||
<div class="card mb-4">
|
||||
<div class="card-header d-flex fs-5">
|
||||
<button class="btn d-md-none flex-grow-1 text-start" data-bs-target="#collapse-tab-filters" data-bs-toggle="collapse" aria-controls="collapse-tab-filters">
|
||||
{{ lang.mailbox.filters }} <span class="badge bg-info table-lines"></span>
|
||||
</button>
|
||||
<span class="d-none d-md-block">{{ lang.mailbox.filters }} <span class="badge bg-info table-lines"></span></span>
|
||||
|
||||
<div class="btn-group ms-auto d-flex">
|
||||
<button class="btn btn-xs btn-secondary refresh_table" data-draw="draw_filter_table" data-table="filter_table">{{ lang.admin.refresh }}</button>
|
||||
</div>
|
||||
</div>
|
||||
<div id="collapse-tab-filters" class="card-body collapse" data-bs-parent="#mail-content">
|
||||
<div class="mass-actions-mailbox mb-4 d-none d-sm-block">
|
||||
<div class="btn-group" data-acl="{{ acl.filters }}">
|
||||
<a class="btn btn-sm btn-xs-half btn-secondary" id="toggle_multi_select_all" data-id="filter_item" href="#"><i class="bi bi-check-all"></i> {{ lang.mailbox.toggle_all }}</a>
|
||||
<a class="btn btn-sm btn-xs-half btn-secondary dropdown-toggle" data-bs-toggle="dropdown" href="#">{{ lang.mailbox.quick_actions }}</a>
|
||||
<ul class="dropdown-menu">
|
||||
<li><a class="dropdown-item" data-action="edit_selected" data-id="filter_item" data-api-url='edit/filter' data-api-attr='{"active":"1"}' href="#">{{ lang.mailbox.activate }}</a></li>
|
||||
<li><a class="dropdown-item" data-action="edit_selected" data-id="filter_item" data-api-url='edit/filter' data-api-attr='{"active":"0"}' href="#">{{ lang.mailbox.deactivate }}</a></li>
|
||||
<li><hr class="dropdown-divider"></li>
|
||||
<li><a class="dropdown-item" data-action="edit_selected" data-id="filter_item" data-api-url='edit/filter' data-api-attr='{"filter_type":"prefilter"}' href="#">{{ lang.mailbox.set_prefilter }}</a></li>
|
||||
<li><a class="dropdown-item" data-action="edit_selected" data-id="filter_item" data-api-url='edit/filter' data-api-attr='{"filter_type":"postfilter"}' href="#">{{ lang.mailbox.set_postfilter }}</a></li>
|
||||
<li><hr class="dropdown-divider"></li>
|
||||
<li><a class="dropdown-item" data-action="delete_selected" data-text="{{ lang.user.eas_reset }}?" data-id="filter_item" data-api-url='delete/filter' href="#">{{ lang.mailbox.remove }}</a></li>
|
||||
<li class="table_collapse_option"><hr class="dropdown-divider"></li>
|
||||
<li class="table_collapse_option"><a class="dropdown-item" data-datatables-expand="filter_table">{{ lang.datatables.expand_all }}</a></li>
|
||||
<li class="table_collapse_option"><a class="dropdown-item" data-datatables-collapse="filter_table">{{ lang.datatables.collapse_all }}</a></li>
|
||||
</ul>
|
||||
<a class="btn btn-sm btn-success" href="#" data-bs-toggle="modal" data-bs-target="#addFilterModalAdmin"><i class="bi bi-plus-lg"></i> {{ lang.mailbox.add_filter }}</a>
|
||||
</div>
|
||||
</div>
|
||||
<p class="text-muted">{{ lang.mailbox.sieve_info|raw }}</p><br>
|
||||
<table id="filter_table" class="table table-striped dt-responsive w-100"></table>
|
||||
<div class="mass-actions-mailbox mt-4 mb-4">
|
||||
<div class="btn-group" data-acl="{{ acl.filters }}">
|
||||
<a class="btn btn-sm btn-xs-lg btn-xs-half btn-secondary" id="toggle_multi_select_all" data-id="filter_item" href="#"><i class="bi bi-check-all"></i> {{ lang.mailbox.toggle_all }}</a>
|
||||
<a class="btn btn-sm btn-xs-lg btn-xs-half btn-secondary dropdown-toggle" data-bs-toggle="dropdown" href="#">{{ lang.mailbox.quick_actions }}</a>
|
||||
<ul class="dropdown-menu">
|
||||
<li><a class="dropdown-item" data-action="edit_selected" data-id="filter_item" data-api-url='edit/filter' data-api-attr='{"active":"1"}' href="#">{{ lang.mailbox.activate }}</a></li>
|
||||
<li><a class="dropdown-item" data-action="edit_selected" data-id="filter_item" data-api-url='edit/filter' data-api-attr='{"active":"0"}' href="#">{{ lang.mailbox.deactivate }}</a></li>
|
||||
<li><hr class="dropdown-divider"></li>
|
||||
<li><a class="dropdown-item" data-action="edit_selected" data-id="filter_item" data-api-url='edit/filter' data-api-attr='{"filter_type":"prefilter"}' href="#">{{ lang.mailbox.set_prefilter }}</a></li>
|
||||
<li><a class="dropdown-item" data-action="edit_selected" data-id="filter_item" data-api-url='edit/filter' data-api-attr='{"filter_type":"postfilter"}' href="#">{{ lang.mailbox.set_postfilter }}</a></li>
|
||||
<li><hr class="dropdown-divider"></li>
|
||||
<li><a class="dropdown-item" data-action="delete_selected" data-text="{{ lang.user.eas_reset }}?" data-id="filter_item" data-api-url='delete/filter' href="#">{{ lang.mailbox.remove }}</a></li>
|
||||
<li class="table_collapse_option"><hr class="dropdown-divider"></li>
|
||||
<li class="table_collapse_option"><a class="dropdown-item" data-datatables-expand="filter_table">{{ lang.datatables.expand_all }}</a></li>
|
||||
<li class="table_collapse_option"><a class="dropdown-item" data-datatables-collapse="filter_table">{{ lang.datatables.collapse_all }}</a></li>
|
||||
</ul>
|
||||
<a class="btn btn-sm btn-xs-lg btn-success" href="#" data-bs-toggle="modal" data-bs-target="#addFilterModalAdmin"><i class="bi bi-plus-lg"></i> {{ lang.mailbox.add_filter }}</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="{% if mailcow_cc_role != 'admin' %}hidden{% endif %}">
|
||||
<div class="row">
|
||||
<div class="col-lg-6 mt-4">
|
||||
<h5>Global Prefilter</h5>
|
||||
<form class="form-horizontal" data-cached-form="false" role="form" data-id="add_prefilter">
|
||||
<div class="row">
|
||||
<div class="col-sm-12">
|
||||
<textarea autocorrect="off" spellcheck="false" autocapitalize="none" class="form-control textarea-code script_data" rows="10" name="script_data" required>{{ global_filters.prefilter }}</textarea>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mt-2">
|
||||
<div class="col-sm-10 add_filter_btns">
|
||||
<div class="btn-group">
|
||||
<button class="btn btn-sm btn-xs-lg btn-xs-half btn-secondary validate_sieve" href="#">{{ lang.add.validate }}</button>
|
||||
<button class="btn btn-sm btn-xs-lg btn-xs-half btn-success add_sieve_script" data-action="add_item" data-id="add_prefilter" data-api-url='add/global-filter' data-api-attr='{"filter_type":"prefilter"}' href="#" disabled><i class="bi bi-check-lg"></i> {{ lang.admin.save }}</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div class="col-lg-6 mt-4">
|
||||
<h5>Global Postfilter</h5>
|
||||
<form class="form-horizontal" data-cached-form="false" role="form" data-id="add_postfilter">
|
||||
<div class="row">
|
||||
<div class="col-sm-12">
|
||||
<textarea autocorrect="off" spellcheck="false" autocapitalize="none" class="form-control textarea-code script_data" rows="10" name="script_data" required>{{ global_filters.postfilter }}</textarea>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mt-2">
|
||||
<div class="col-sm-10 add_filter_btns">
|
||||
<div class="btn-group">
|
||||
<button class="btn btn-sm btn-xs-lg btn-xs-half btn-secondary validate_sieve" href="#">{{ lang.add.validate }}</button>
|
||||
<button class="btn btn-sm btn-xs-lg btn-xs-half btn-success add_sieve_script" data-action="add_item" data-id="add_postfilter" data-api-url='add/global-filter' data-api-attr='{"filter_type":"postfilter"}' href="#" disabled><i class="bi bi-check-lg"></i> {{ lang.admin.save }}</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
244
data/web/templates/mailbox/tab-mailboxes.twig
Executable file
244
data/web/templates/mailbox/tab-mailboxes.twig
Executable file
|
|
@ -0,0 +1,244 @@
|
|||
<div class="tab-pane fade" id="tab-mailboxes" role="tabpanel" aria-labelledby="tab-mailboxes">
|
||||
<div class="card mb-4">
|
||||
<div class="card-header d-flex fs-5">
|
||||
<button class="btn d-md-none flex-grow-1 text-start" data-bs-target="#collapse-tab-mailboxes" data-bs-toggle="collapse" aria-controls="collapse-tab-mailboxes">
|
||||
{{ lang.mailbox.mailboxes }} <span class="badge bg-info table-lines"></span>
|
||||
</button>
|
||||
<span class="d-none d-md-block">{{ lang.mailbox.mailboxes }} <span class="badge bg-info table-lines"></span></span>
|
||||
|
||||
<div class="btn-group ms-auto d-flex">
|
||||
<button class="btn btn-xs btn-secondary refresh_table" data-draw="draw_mailbox_table" data-table="mailbox_table">{{ lang.admin.refresh }}</button>
|
||||
</div>
|
||||
</div>
|
||||
<div id="collapse-tab-mailboxes" class="card-body collapse" data-bs-parent="#mail-content">
|
||||
<div class="mass-actions-mailbox mb-4 d-none d-sm-block">
|
||||
<div class="btn-group d-flex d-lg-none">
|
||||
<a class="btn btn-sm btn-xs-half btn-secondary" id="toggle_multi_select_all" data-id="mailbox" href="#"><i class="bi bi-check-all"></i> {{ lang.mailbox.toggle_all }}</a>
|
||||
<a class="btn btn-sm btn-xs-half btn-secondary dropdown-toggle" data-bs-toggle="dropdown" href="#">{{ lang.mailbox.quick_actions }}</a>
|
||||
<ul class="dropdown-menu">
|
||||
<li class="table_collapse_option"><a class="dropdown-item" data-datatables-expand="mailbox_table">{{ lang.datatables.expand_all }}</a></li>
|
||||
<li class="table_collapse_option"><a class="dropdown-item" data-datatables-collapse="mailbox_table">{{ lang.datatables.collapse_all }}</a></li>
|
||||
<li class="table_collapse_option"><hr class="dropdown-divider"></li>
|
||||
<li class="dropdown-header">{{ lang.mailbox.mailbox }}</li>
|
||||
<li><a class="dropdown-item" data-action="edit_selected" data-id="mailbox" data-api-url='edit/mailbox' data-api-attr='{"active":"1"}' href="#">{{ lang.mailbox.activate }}</a></li>
|
||||
<li><a class="dropdown-item" data-action="edit_selected" data-id="mailbox" data-api-url='edit/mailbox' data-api-attr='{"active":"0"}' href="#">{{ lang.mailbox.deactivate }}</a></li>
|
||||
<li><a class="dropdown-item" data-action="delete_selected" data-id="mailbox" data-api-url='delete/mailbox' href="#">{{ lang.mailbox.remove }}</a></li>
|
||||
<li><hr class="dropdown-divider"></li>
|
||||
<li class="dropdown-header">{{ lang.mailbox.tls_enforce_in }}</li>
|
||||
<li><a class="dropdown-item" data-action="edit_selected" data-id="mailbox" data-api-url='edit/tls_policy' data-api-attr='{"tls_enforce_in":"1"}' href="#">{{ lang.mailbox.activate }}</a></li>
|
||||
<li><a class="dropdown-item" data-action="edit_selected" data-id="mailbox" data-api-url='edit/tls_policy' data-api-attr='{"tls_enforce_in":"0"}' href="#">{{ lang.mailbox.deactivate }}</a></li>
|
||||
<li><hr class="dropdown-divider"></li>
|
||||
<li class="dropdown-header">{{ lang.mailbox.tls_enforce_out }}</li>
|
||||
<li><a class="dropdown-item" data-action="edit_selected" data-id="mailbox" data-api-url='edit/tls_policy' data-api-attr='{"tls_enforce_out":"1"}' href="#">{{ lang.mailbox.activate }}</a></li>
|
||||
<li><a class="dropdown-item" data-action="edit_selected" data-id="mailbox" data-api-url='edit/tls_policy' data-api-attr='{"tls_enforce_out":"0"}' href="#">{{ lang.mailbox.deactivate }}</a></li>
|
||||
<li><hr class="dropdown-divider"></li>
|
||||
<li class="dropdown-header">{{ lang.mailbox.quarantine_notification }}</li>
|
||||
<li><a class="dropdown-item" data-action="edit_selected" data-id="mailbox" data-api-url='edit/quarantine_notification' data-api-attr='{"quarantine_notification":"hourly"}' href="#">{{ lang.user.hourly }}</a></li>
|
||||
<li><a class="dropdown-item" data-action="edit_selected" data-id="mailbox" data-api-url='edit/quarantine_notification' data-api-attr='{"quarantine_notification":"daily"}' href="#">{{ lang.user.daily }}</a></li>
|
||||
<li><a class="dropdown-item" data-action="edit_selected" data-id="mailbox" data-api-url='edit/quarantine_notification' data-api-attr='{"quarantine_notification":"weekly"}' href="#">{{ lang.user.weekly }}</a></li>
|
||||
<li><a class="dropdown-item" data-action="edit_selected" data-id="mailbox" data-api-url='edit/quarantine_notification' data-api-attr='{"quarantine_notification":"never"}' href="#">{{ lang.user.never }}</a></li>
|
||||
<li><hr class="dropdown-divider"></li>
|
||||
<li><a class="dropdown-item" data-action="edit_selected" data-id="mailbox" data-api-url='edit/quarantine_category' data-api-attr='{"quarantine_category":"reject"}' href="#">{{ lang.user.q_reject }}</a></li>
|
||||
<li><a class="dropdown-item" data-action="edit_selected" data-id="mailbox" data-api-url='edit/quarantine_category' data-api-attr='{"quarantine_category":"add_header"}' href="#">{{ lang.user.q_add_header }}</a></li>
|
||||
<li><a class="dropdown-item" data-action="edit_selected" data-id="mailbox" data-api-url='edit/quarantine_category' data-api-attr='{"quarantine_category":"all"}' href="#">{{ lang.user.q_all }}</a></li>
|
||||
<li><hr class="dropdown-divider"></li>
|
||||
<li class="dropdown-header">{{ lang.mailbox.allowed_protocols }}</li>
|
||||
<li class="dropdown-header">IMAP</li>
|
||||
<li><a class="dropdown-item" data-action="edit_selected" data-id="mailbox" data-api-url='edit/mailbox' data-api-attr='{"imap_access":1}' href="#">{{ lang.mailbox.activate }}</a></li>
|
||||
<li><a class="dropdown-item" data-action="edit_selected" data-id="mailbox" data-api-url='edit/mailbox' data-api-attr='{"imap_access":0}' href="#">{{ lang.mailbox.deactivate }}</a></li>
|
||||
<li><hr class="dropdown-divider"></li>
|
||||
<li class="dropdown-header">POP3</li>
|
||||
<li><a class="dropdown-item" data-action="edit_selected" data-id="mailbox" data-api-url='edit/mailbox' data-api-attr='{"pop3_access":1}' href="#">{{ lang.mailbox.activate }}</a></li>
|
||||
<li><a class="dropdown-item" data-action="edit_selected" data-id="mailbox" data-api-url='edit/mailbox' data-api-attr='{"pop3_access":0}' href="#">{{ lang.mailbox.deactivate }}</a></li>
|
||||
<li><hr class="dropdown-divider"></li>
|
||||
<li class="dropdown-header">SMTP</li>
|
||||
<li><a class="dropdown-item" data-action="edit_selected" data-id="mailbox" data-api-url='edit/mailbox' data-api-attr='{"smtp_access":1}' href="#">{{ lang.mailbox.activate }}</a></li>
|
||||
<li><a class="dropdown-item" data-action="edit_selected" data-id="mailbox" data-api-url='edit/mailbox' data-api-attr='{"smtp_access":0}' href="#">{{ lang.mailbox.deactivate }}</a></li>
|
||||
<li><hr class="dropdown-divider"></li>
|
||||
<li class="dropdown-header">Sieve</li>
|
||||
<li><a class="dropdown-item" data-action="edit_selected" data-id="mailbox" data-api-url='edit/mailbox' data-api-attr='{"sieve_access":1}' href="#">{{ lang.mailbox.activate }}</a></li>
|
||||
<li><a class="dropdown-item" data-action="edit_selected" data-id="mailbox" data-api-url='edit/mailbox' data-api-attr='{"sieve_access":0}' href="#">{{ lang.mailbox.deactivate }}</a></li>
|
||||
</ul>
|
||||
<a class="btn btn-sm btn-success" href="#" data-bs-toggle="modal" data-bs-target="#addMailboxModal"><i class="bi bi-plus-lg"></i> {{ lang.mailbox.add_mailbox }}</a>
|
||||
</div>
|
||||
<div class="btn-group d-none d-lg-flex">
|
||||
<a class="btn btn-sm btn-secondary" id="toggle_multi_select_all" data-id="mailbox" href="#"><i class="bi bi-check-all"></i> {{ lang.mailbox.toggle_all }}</a>
|
||||
<a class="btn btn-sm btn-xs-half btn-secondary dropdown-toggle" data-bs-toggle="dropdown" href="#">{{ lang.mailbox.quick_actions }}</a>
|
||||
<ul class="dropdown-menu">
|
||||
<li class="table_collapse_option"><a class="dropdown-item" data-datatables-expand="mailbox_table">{{ lang.datatables.expand_all }}</a></li>
|
||||
<li class="table_collapse_option"><a class="dropdown-item" data-datatables-collapse="mailbox_table">{{ lang.datatables.collapse_all }}</a></li>
|
||||
</ul>
|
||||
<div class="btn-group">
|
||||
<a class="btn btn-sm btn-secondary dropdown-toggle" data-bs-toggle="dropdown" href="#">{{ lang.mailbox.mailbox }}</a>
|
||||
<ul class="dropdown-menu">
|
||||
<li><a class="dropdown-item" data-action="edit_selected" data-id="mailbox" data-api-url='edit/mailbox' data-api-attr='{"active":"1"}' href="#">{{ lang.mailbox.activate }}</a></li>
|
||||
<li><a class="dropdown-item" data-action="edit_selected" data-id="mailbox" data-api-url='edit/mailbox' data-api-attr='{"active":"2"}' href="#">{{ lang.mailbox.disable_login }}</a></li>
|
||||
<li><a class="dropdown-item" data-action="edit_selected" data-id="mailbox" data-api-url='edit/mailbox' data-api-attr='{"active":"0"}' href="#">{{ lang.mailbox.deactivate }}</a></li>
|
||||
<li><hr class="dropdown-divider"></li>
|
||||
<li><a class="dropdown-item" data-action="delete_selected" data-id="mailbox" data-api-url='delete/mailbox' href="#">{{ lang.mailbox.remove }}</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="btn-group">
|
||||
<a class="btn btn-sm btn-secondary dropdown-toggle" data-bs-toggle="dropdown" href="#">TLS</a>
|
||||
<ul class="dropdown-menu">
|
||||
<li class="dropdown-header">{{ lang.mailbox.tls_enforce_in }}</li>
|
||||
<li><a class="dropdown-item" data-action="edit_selected" data-id="mailbox" data-api-url='edit/tls_policy' data-api-attr='{"tls_enforce_in":"1"}' href="#">{{ lang.mailbox.activate }}</a></li>
|
||||
<li><a class="dropdown-item" data-action="edit_selected" data-id="mailbox" data-api-url='edit/tls_policy' data-api-attr='{"tls_enforce_in":"0"}' href="#">{{ lang.mailbox.deactivate }}</a></li>
|
||||
<li><hr class="dropdown-divider"></li>
|
||||
<li class="dropdown-header">{{ lang.mailbox.tls_enforce_out }}</li>
|
||||
<li><a class="dropdown-item" data-action="edit_selected" data-id="mailbox" data-api-url='edit/tls_policy' data-api-attr='{"tls_enforce_out":"1"}' href="#">{{ lang.mailbox.activate }}</a></li>
|
||||
<li><a class="dropdown-item" data-action="edit_selected" data-id="mailbox" data-api-url='edit/tls_policy' data-api-attr='{"tls_enforce_out":"0"}' href="#">{{ lang.mailbox.deactivate }}</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="btn-group">
|
||||
<a class="btn btn-sm btn-secondary dropdown-toggle" data-bs-toggle="dropdown" href="#">{{ lang.mailbox.allowed_protocols }}</a>
|
||||
<ul class="dropdown-menu">
|
||||
<li class="dropdown-header">IMAP</li>
|
||||
<li><a class="dropdown-item" data-action="edit_selected" data-id="mailbox" data-api-url='edit/mailbox' data-api-attr='{"imap_access":1}' href="#">{{ lang.mailbox.activate }}</a></li>
|
||||
<li><a class="dropdown-item" data-action="edit_selected" data-id="mailbox" data-api-url='edit/mailbox' data-api-attr='{"imap_access":0}' href="#">{{ lang.mailbox.deactivate }}</a></li>
|
||||
<li><hr class="dropdown-divider"></li>
|
||||
<li class="dropdown-header">POP3</li>
|
||||
<li><a class="dropdown-item" data-action="edit_selected" data-id="mailbox" data-api-url='edit/mailbox' data-api-attr='{"pop3_access":1}' href="#">{{ lang.mailbox.activate }}</a></li>
|
||||
<li><a class="dropdown-item" data-action="edit_selected" data-id="mailbox" data-api-url='edit/mailbox' data-api-attr='{"pop3_access":0}' href="#">{{ lang.mailbox.deactivate }}</a></li>
|
||||
<li><hr class="dropdown-divider"></li>
|
||||
<li class="dropdown-header">SMTP</li>
|
||||
<li><a class="dropdown-item" data-action="edit_selected" data-id="mailbox" data-api-url='edit/mailbox' data-api-attr='{"smtp_access":1}' href="#">{{ lang.mailbox.activate }}</a></li>
|
||||
<li><a class="dropdown-item" data-action="edit_selected" data-id="mailbox" data-api-url='edit/mailbox' data-api-attr='{"smtp_access":0}' href="#">{{ lang.mailbox.deactivate }}</a></li>
|
||||
<li class="dropdown-header">Sieve</li>
|
||||
<li><a class="dropdown-item" data-action="edit_selected" data-id="mailbox" data-api-url='edit/mailbox' data-api-attr='{"sieve_access":1}' href="#">{{ lang.mailbox.activate }}</a></li>
|
||||
<li><a class="dropdown-item" data-action="edit_selected" data-id="mailbox" data-api-url='edit/mailbox' data-api-attr='{"sieve_access":0}' href="#">{{ lang.mailbox.deactivate }}</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="btn-group">
|
||||
<a class="btn btn-sm btn-secondary dropdown-toggle" data-bs-toggle="dropdown" href="#">{{ lang.mailbox.quarantine_notification }}</a>
|
||||
<ul class="dropdown-menu">
|
||||
<li><a class="dropdown-item" data-action="edit_selected" data-id="mailbox" data-api-url='edit/quarantine_notification' data-api-attr='{"quarantine_notification":"hourly"}' href="#">{{ lang.user.hourly }}</a></li>
|
||||
<li><a class="dropdown-item" data-action="edit_selected" data-id="mailbox" data-api-url='edit/quarantine_notification' data-api-attr='{"quarantine_notification":"daily"}' href="#">{{ lang.user.daily }}</a></li>
|
||||
<li><a class="dropdown-item" data-action="edit_selected" data-id="mailbox" data-api-url='edit/quarantine_notification' data-api-attr='{"quarantine_notification":"weekly"}' href="#">{{ lang.user.weekly }}</a></li>
|
||||
<li><a class="dropdown-item" data-action="edit_selected" data-id="mailbox" data-api-url='edit/quarantine_notification' data-api-attr='{"quarantine_notification":"never"}' href="#">{{ lang.user.never }}</a></li>
|
||||
<li><hr class="dropdown-divider"></li>
|
||||
<li><a class="dropdown-item" data-action="edit_selected" data-id="mailbox" data-api-url='edit/quarantine_category' data-api-attr='{"quarantine_category":"reject"}' href="#">{{ lang.user.q_reject }}</a></li>
|
||||
<li><a class="dropdown-item" data-action="edit_selected" data-id="mailbox" data-api-url='edit/quarantine_category' data-api-attr='{"quarantine_category":"add_header"}' href="#">{{ lang.user.q_add_header }}</a></li>
|
||||
<li><a class="dropdown-item" data-action="edit_selected" data-id="mailbox" data-api-url='edit/quarantine_category' data-api-attr='{"quarantine_category":"all"}' href="#">{{ lang.user.q_all }}</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<a class="btn btn-sm btn-success" href="#" data-bs-toggle="modal" data-bs-target="#addMailboxModal"><i class="bi bi-plus-lg"></i> {{ lang.mailbox.add_mailbox }}</a>
|
||||
</div>
|
||||
</div>
|
||||
<table id="mailbox_table" class="table table-striped dt-responsive w-100"></table>
|
||||
<div class="mass-actions-mailbox mt-4">
|
||||
<div class="btn-group d-flex d-lg-none">
|
||||
<a class="btn btn-sm btn-xs-lg btn-xs-half btn-secondary" id="toggle_multi_select_all" data-id="mailbox" href="#"><i class="bi bi-check-all"></i> {{ lang.mailbox.toggle_all }}</a>
|
||||
<a class="btn btn-sm btn-xs-lg btn-xs-half btn-secondary dropdown-toggle" data-bs-toggle="dropdown" href="#">{{ lang.mailbox.quick_actions }}</a>
|
||||
<ul class="dropdown-menu">
|
||||
<li class="table_collapse_option"><a class="dropdown-item" data-datatables-expand="mailbox_table">{{ lang.datatables.expand_all }}</a></li>
|
||||
<li class="table_collapse_option"><a class="dropdown-item" data-datatables-collapse="mailbox_table">{{ lang.datatables.collapse_all }}</a></li>
|
||||
<li class="table_collapse_option"><hr class="dropdown-divider"></li>
|
||||
<li class="dropdown-header">{{ lang.mailbox.mailbox }}</li>
|
||||
<li><a class="dropdown-item" data-action="edit_selected" data-id="mailbox" data-api-url='edit/mailbox' data-api-attr='{"active":"1"}' href="#">{{ lang.mailbox.activate }}</a></li>
|
||||
<li><a class="dropdown-item" data-action="edit_selected" data-id="mailbox" data-api-url='edit/mailbox' data-api-attr='{"active":"0"}' href="#">{{ lang.mailbox.deactivate }}</a></li>
|
||||
<li><a class="dropdown-item" data-action="delete_selected" data-id="mailbox" data-api-url='delete/mailbox' href="#">{{ lang.mailbox.remove }}</a></li>
|
||||
<li><hr class="dropdown-divider"></li>
|
||||
<li class="dropdown-header">{{ lang.mailbox.tls_enforce_in }}</li>
|
||||
<li><a class="dropdown-item" data-action="edit_selected" data-id="mailbox" data-api-url='edit/tls_policy' data-api-attr='{"tls_enforce_in":"1"}' href="#">{{ lang.mailbox.activate }}</a></li>
|
||||
<li><a class="dropdown-item" data-action="edit_selected" data-id="mailbox" data-api-url='edit/tls_policy' data-api-attr='{"tls_enforce_in":"0"}' href="#">{{ lang.mailbox.deactivate }}</a></li>
|
||||
<li><hr class="dropdown-divider"></li>
|
||||
<li class="dropdown-header">{{ lang.mailbox.tls_enforce_out }}</li>
|
||||
<li><a class="dropdown-item" data-action="edit_selected" data-id="mailbox" data-api-url='edit/tls_policy' data-api-attr='{"tls_enforce_out":"1"}' href="#">{{ lang.mailbox.activate }}</a></li>
|
||||
<li><a class="dropdown-item" data-action="edit_selected" data-id="mailbox" data-api-url='edit/tls_policy' data-api-attr='{"tls_enforce_out":"0"}' href="#">{{ lang.mailbox.deactivate }}</a></li>
|
||||
<li><hr class="dropdown-divider"></li>
|
||||
<li class="dropdown-header">{{ lang.mailbox.quarantine_notification }}</li>
|
||||
<li><a class="dropdown-item" data-action="edit_selected" data-id="mailbox" data-api-url='edit/quarantine_notification' data-api-attr='{"quarantine_notification":"hourly"}' href="#">{{ lang.user.hourly }}</a></li>
|
||||
<li><a class="dropdown-item" data-action="edit_selected" data-id="mailbox" data-api-url='edit/quarantine_notification' data-api-attr='{"quarantine_notification":"daily"}' href="#">{{ lang.user.daily }}</a></li>
|
||||
<li><a class="dropdown-item" data-action="edit_selected" data-id="mailbox" data-api-url='edit/quarantine_notification' data-api-attr='{"quarantine_notification":"weekly"}' href="#">{{ lang.user.weekly }}</a></li>
|
||||
<li><a class="dropdown-item" data-action="edit_selected" data-id="mailbox" data-api-url='edit/quarantine_notification' data-api-attr='{"quarantine_notification":"never"}' href="#">{{ lang.user.never }}</a></li>
|
||||
<li><hr class="dropdown-divider"></li>
|
||||
<li><a class="dropdown-item" data-action="edit_selected" data-id="mailbox" data-api-url='edit/quarantine_category' data-api-attr='{"quarantine_category":"reject"}' href="#">{{ lang.user.q_reject }}</a></li>
|
||||
<li><a class="dropdown-item" data-action="edit_selected" data-id="mailbox" data-api-url='edit/quarantine_category' data-api-attr='{"quarantine_category":"add_header"}' href="#">{{ lang.user.q_add_header }}</a></li>
|
||||
<li><a class="dropdown-item" data-action="edit_selected" data-id="mailbox" data-api-url='edit/quarantine_category' data-api-attr='{"quarantine_category":"all"}' href="#">{{ lang.user.q_all }}</a></li>
|
||||
<li><hr class="dropdown-divider"></li>
|
||||
<li class="dropdown-header">{{ lang.mailbox.allowed_protocols }}</li>
|
||||
<li class="dropdown-header">IMAP</li>
|
||||
<li><a class="dropdown-item" data-action="edit_selected" data-id="mailbox" data-api-url='edit/mailbox' data-api-attr='{"imap_access":1}' href="#">{{ lang.mailbox.activate }}</a></li>
|
||||
<li><a class="dropdown-item" data-action="edit_selected" data-id="mailbox" data-api-url='edit/mailbox' data-api-attr='{"imap_access":0}' href="#">{{ lang.mailbox.deactivate }}</a></li>
|
||||
<li><hr class="dropdown-divider"></li>
|
||||
<li class="dropdown-header">POP3</li>
|
||||
<li><a class="dropdown-item" data-action="edit_selected" data-id="mailbox" data-api-url='edit/mailbox' data-api-attr='{"pop3_access":1}' href="#">{{ lang.mailbox.activate }}</a></li>
|
||||
<li><a class="dropdown-item" data-action="edit_selected" data-id="mailbox" data-api-url='edit/mailbox' data-api-attr='{"pop3_access":0}' href="#">{{ lang.mailbox.deactivate }}</a></li>
|
||||
<li><hr class="dropdown-divider"></li>
|
||||
<li class="dropdown-header">SMTP</li>
|
||||
<li><a class="dropdown-item" data-action="edit_selected" data-id="mailbox" data-api-url='edit/mailbox' data-api-attr='{"smtp_access":1}' href="#">{{ lang.mailbox.activate }}</a></li>
|
||||
<li><a class="dropdown-item" data-action="edit_selected" data-id="mailbox" data-api-url='edit/mailbox' data-api-attr='{"smtp_access":0}' href="#">{{ lang.mailbox.deactivate }}</a></li>
|
||||
<li class="dropdown-header">Sieve</li>
|
||||
<li><a class="dropdown-item" data-action="edit_selected" data-id="mailbox" data-api-url='edit/mailbox' data-api-attr='{"sieve_access":1}' href="#">{{ lang.mailbox.activate }}</a></li>
|
||||
<li><a class="dropdown-item" data-action="edit_selected" data-id="mailbox" data-api-url='edit/mailbox' data-api-attr='{"sieve_access":0}' href="#">{{ lang.mailbox.deactivate }}</a></li>
|
||||
</ul>
|
||||
<a class="btn btn-sm btn-xs-lg btn-success" href="#" data-bs-toggle="modal" data-bs-target="#addMailboxModal"><i class="bi bi-plus-lg"></i> {{ lang.mailbox.add_mailbox }}</a>
|
||||
</div>
|
||||
<div class="btn-group d-none d-lg-flex">
|
||||
<a class="btn btn-sm btn-secondary" id="toggle_multi_select_all" data-id="mailbox" href="#"><i class="bi bi-check-all"></i> {{ lang.mailbox.toggle_all }}</a>
|
||||
<a class="btn btn-sm btn-xs-half btn-secondary dropdown-toggle" data-bs-toggle="dropdown" href="#">{{ lang.mailbox.quick_actions }}</a>
|
||||
<ul class="dropdown-menu">
|
||||
<li class="table_collapse_option"><a class="dropdown-item" data-datatables-expand="mailbox_table">{{ lang.datatables.expand_all }}</a></li>
|
||||
<li class="table_collapse_option"><a class="dropdown-item" data-datatables-collapse="mailbox_table">{{ lang.datatables.collapse_all }}</a></li>
|
||||
</ul>
|
||||
<div class="btn-group">
|
||||
<a class="btn btn-sm btn-secondary dropdown-toggle" data-bs-toggle="dropdown" href="#">{{ lang.mailbox.mailbox }}</a>
|
||||
<ul class="dropdown-menu">
|
||||
<li><a class="dropdown-item" data-action="edit_selected" data-id="mailbox" data-api-url='edit/mailbox' data-api-attr='{"active":"1"}' href="#">{{ lang.mailbox.activate }}</a></li>
|
||||
<li><a class="dropdown-item" data-action="edit_selected" data-id="mailbox" data-api-url='edit/mailbox' data-api-attr='{"active":"2"}' href="#">{{ lang.mailbox.disable_login }}</a></li>
|
||||
<li><a class="dropdown-item" data-action="edit_selected" data-id="mailbox" data-api-url='edit/mailbox' data-api-attr='{"active":"0"}' href="#">{{ lang.mailbox.deactivate }}</a></li>
|
||||
<li><hr class="dropdown-divider"></li>
|
||||
<li><a class="dropdown-item" data-action="delete_selected" data-id="mailbox" data-api-url='delete/mailbox' href="#">{{ lang.mailbox.remove }}</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="btn-group">
|
||||
<a class="btn btn-sm btn-secondary dropdown-toggle" data-bs-toggle="dropdown" href="#">TLS</a>
|
||||
<ul class="dropdown-menu">
|
||||
<li class="dropdown-header">{{ lang.mailbox.tls_enforce_in }}</li>
|
||||
<li><a class="dropdown-item" data-action="edit_selected" data-id="mailbox" data-api-url='edit/tls_policy' data-api-attr='{"tls_enforce_in":"1"}' href="#">{{ lang.mailbox.activate }}</a></li>
|
||||
<li><a class="dropdown-item" data-action="edit_selected" data-id="mailbox" data-api-url='edit/tls_policy' data-api-attr='{"tls_enforce_in":"0"}' href="#">{{ lang.mailbox.deactivate }}</a></li>
|
||||
<li><hr class="dropdown-divider"></li>
|
||||
<li class="dropdown-header">{{ lang.mailbox.tls_enforce_out }}</li>
|
||||
<li><a class="dropdown-item" data-action="edit_selected" data-id="mailbox" data-api-url='edit/tls_policy' data-api-attr='{"tls_enforce_out":"1"}' href="#">{{ lang.mailbox.activate }}</a></li>
|
||||
<li><a class="dropdown-item" data-action="edit_selected" data-id="mailbox" data-api-url='edit/tls_policy' data-api-attr='{"tls_enforce_out":"0"}' href="#">{{ lang.mailbox.deactivate }}</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="btn-group">
|
||||
<a class="btn btn-sm btn-secondary dropdown-toggle" data-bs-toggle="dropdown" href="#">{{ lang.mailbox.allowed_protocols }}</a>
|
||||
<ul class="dropdown-menu">
|
||||
<li class="dropdown-header">IMAP</li>
|
||||
<li><a class="dropdown-item" data-action="edit_selected" data-id="mailbox" data-api-url='edit/mailbox' data-api-attr='{"imap_access":1}' href="#">{{ lang.mailbox.activate }}</a></li>
|
||||
<li><a class="dropdown-item" data-action="edit_selected" data-id="mailbox" data-api-url='edit/mailbox' data-api-attr='{"imap_access":0}' href="#">{{ lang.mailbox.deactivate }}</a></li>
|
||||
<li><hr class="dropdown-divider"></li>
|
||||
<li class="dropdown-header">POP3</li>
|
||||
<li><a class="dropdown-item" data-action="edit_selected" data-id="mailbox" data-api-url='edit/mailbox' data-api-attr='{"pop3_access":1}' href="#">{{ lang.mailbox.activate }}</a></li>
|
||||
<li><a class="dropdown-item" data-action="edit_selected" data-id="mailbox" data-api-url='edit/mailbox' data-api-attr='{"pop3_access":0}' href="#">{{ lang.mailbox.deactivate }}</a></li>
|
||||
<li><hr class="dropdown-divider"></li>
|
||||
<li class="dropdown-header">SMTP</li>
|
||||
<li><a class="dropdown-item" data-action="edit_selected" data-id="mailbox" data-api-url='edit/mailbox' data-api-attr='{"smtp_access":1}' href="#">{{ lang.mailbox.activate }}</a></li>
|
||||
<li><a class="dropdown-item" data-action="edit_selected" data-id="mailbox" data-api-url='edit/mailbox' data-api-attr='{"smtp_access":0}' href="#">{{ lang.mailbox.deactivate }}</a></li>
|
||||
<li class="dropdown-header">Sieve</li>
|
||||
<li><a class="dropdown-item" data-action="edit_selected" data-id="mailbox" data-api-url='edit/mailbox' data-api-attr='{"sieve_access":1}' href="#">{{ lang.mailbox.activate }}</a></li>
|
||||
<li><a class="dropdown-item" data-action="edit_selected" data-id="mailbox" data-api-url='edit/mailbox' data-api-attr='{"sieve_access":0}' href="#">{{ lang.mailbox.deactivate }}</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="btn-group">
|
||||
<a class="btn btn-sm btn-secondary dropdown-toggle" data-bs-toggle="dropdown" href="#">{{ lang.mailbox.quarantine_notification }}</a>
|
||||
<ul class="dropdown-menu">
|
||||
<li><a class="dropdown-item" data-action="edit_selected" data-id="mailbox" data-api-url='edit/quarantine_notification' data-api-attr='{"quarantine_notification":"hourly"}' href="#">{{ lang.user.hourly }}</a></li>
|
||||
<li><a class="dropdown-item" data-action="edit_selected" data-id="mailbox" data-api-url='edit/quarantine_notification' data-api-attr='{"quarantine_notification":"daily"}' href="#">{{ lang.user.daily }}</a></li>
|
||||
<li><a class="dropdown-item" data-action="edit_selected" data-id="mailbox" data-api-url='edit/quarantine_notification' data-api-attr='{"quarantine_notification":"weekly"}' href="#">{{ lang.user.weekly }}</a></li>
|
||||
<li><a class="dropdown-item" data-action="edit_selected" data-id="mailbox" data-api-url='edit/quarantine_notification' data-api-attr='{"quarantine_notification":"never"}' href="#">{{ lang.user.never }}</a></li>
|
||||
<li><hr class="dropdown-divider"></li>
|
||||
<li><a class="dropdown-item" data-action="edit_selected" data-id="mailbox" data-api-url='edit/quarantine_category' data-api-attr='{"quarantine_category":"reject"}' href="#">{{ lang.user.q_reject }}</a></li>
|
||||
<li><a class="dropdown-item" data-action="edit_selected" data-id="mailbox" data-api-url='edit/quarantine_category' data-api-attr='{"quarantine_category":"add_header"}' href="#">{{ lang.user.q_add_header }}</a></li>
|
||||
<li><a class="dropdown-item" data-action="edit_selected" data-id="mailbox" data-api-url='edit/quarantine_category' data-api-attr='{"quarantine_category":"all"}' href="#">{{ lang.user.q_all }}</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<a class="btn btn-sm btn-success" href="#" data-bs-toggle="modal" data-bs-target="#addMailboxModal"><i class="bi bi-plus-lg"></i> {{ lang.mailbox.add_mailbox }}</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
62
data/web/templates/mailbox/tab-mbox-aliases.twig
Executable file
62
data/web/templates/mailbox/tab-mbox-aliases.twig
Executable file
|
|
@ -0,0 +1,62 @@
|
|||
<div class="tab-pane fade" id="tab-mbox-aliases" role="tabpanel" aria-labelledby="tab-mbox-aliases">
|
||||
<div class="card mb-4">
|
||||
<div class="card-header d-flex fs-5">
|
||||
<button class="btn d-md-none flex-grow-1 text-start" data-bs-target="#collapse-tab-mbox-aliases" data-bs-toggle="collapse" aria-controls="collapse-tab-mbox-aliases">
|
||||
{{ lang.mailbox.aliases }} <span class="badge bg-info table-lines"></span>
|
||||
</button>
|
||||
<span class="d-none d-md-block">{{ lang.mailbox.aliases }} <span class="badge bg-info table-lines"></span></span>
|
||||
|
||||
<div class="btn-group ms-auto d-flex">
|
||||
<button class="btn btn-xs btn-secondary refresh_table" data-draw="draw_alias_table" data-table="alias_table">{{ lang.admin.refresh }}</button>
|
||||
</div>
|
||||
</div>
|
||||
<div id="collapse-tab-mbox-aliases" class="card-body collapse" data-bs-parent="#mail-content">
|
||||
<div class="mass-actions-mailbox mb-4 d-none d-sm-block">
|
||||
<div class="btn-group">
|
||||
<a class="btn btn-sm btn-xs-half btn-secondary" id="toggle_multi_select_all" data-id="alias" href="#"><i class="bi bi-check-all"></i> {{ lang.mailbox.toggle_all }}</a>
|
||||
<a class="btn btn-sm btn-xs-half btn-secondary dropdown-toggle" data-bs-toggle="dropdown" href="#">{{ lang.mailbox.quick_actions }}</a>
|
||||
<ul class="dropdown-menu top33">
|
||||
<li><a class="dropdown-item" data-action="edit_selected" data-id="alias" data-api-url='edit/alias' data-api-attr='{"active":"1"}' href="#">{{ lang.mailbox.activate }}</a></li>
|
||||
<li><a class="dropdown-item" data-action="edit_selected" data-id="alias" data-api-url='edit/alias' data-api-attr='{"active":"0"}' href="#">{{ lang.mailbox.deactivate }}</a></li>
|
||||
<li><hr class="dropdown-divider"></li>
|
||||
<li><a class="dropdown-item" data-action="delete_selected" data-id="alias" data-api-url='delete/alias' href="#">{{ lang.mailbox.remove }}</a></li>
|
||||
<li class="table_collapse_option"><hr class="dropdown-divider"></li>
|
||||
<li class="table_collapse_option"><a class="dropdown-item" data-datatables-expand="alias_table">{{ lang.datatables.expand_all }}</a></li>
|
||||
<li class="table_collapse_option"><a class="dropdown-item" data-datatables-collapse="alias_table">{{ lang.datatables.collapse_all }}</a></li>
|
||||
{% if not skip_sogo %}
|
||||
<li><hr class="dropdown-divider"></li>
|
||||
<li><a class="dropdown-item" data-action="edit_selected" data-id="alias" data-api-url='edit/alias' data-api-attr='{"sogo_visible":"1"}' href="#">{{ lang.mailbox.sogo_visible_y }}</a></li>
|
||||
<li><a class="dropdown-item" data-action="edit_selected" data-id="alias" data-api-url='edit/alias' data-api-attr='{"sogo_visible":"0"}' href="#">{{ lang.mailbox.sogo_visible_n }}</a></li>
|
||||
{% endif %}
|
||||
</ul>
|
||||
<a class="btn btn-sm btn-secondary" data-action="edit_selected" data-id="alias" data-api-url='edit/alias' data-api-attr='{"expand_alias":true}' ><i class="bi bi-arrows-angle-expand"></i> {{ lang.mailbox.add_alias_expand }}</a>
|
||||
<a class="btn btn-sm btn-success" href="#" data-bs-toggle="modal" data-bs-target="#addAliasModal"><i class="bi bi-plus-lg"></i> {{ lang.mailbox.add_alias }}</a>
|
||||
</div>
|
||||
</div>
|
||||
<p class="text-muted">{{ lang.mailbox.alias_domain_alias_hint|raw }}</p>
|
||||
<table id="alias_table" class="table table-striped dt-responsive w-100"></table>
|
||||
<div class="mass-actions-mailbox mt-4">
|
||||
<div class="btn-group">
|
||||
<a class="btn btn-sm btn-xs-lg btn-xs-half btn-secondary" id="toggle_multi_select_all" data-id="alias" href="#"><i class="bi bi-check-all"></i> {{ lang.mailbox.toggle_all }}</a>
|
||||
<a class="btn btn-sm btn-xs-lg btn-xs-half btn-secondary dropdown-toggle" data-bs-toggle="dropdown" href="#">{{ lang.mailbox.quick_actions }}</a>
|
||||
<ul class="dropdown-menu top33">
|
||||
<li><a class="dropdown-item" data-action="edit_selected" data-id="alias" data-api-url='edit/alias' data-api-attr='{"active":"1"}' href="#">{{ lang.mailbox.activate }}</a></li>
|
||||
<li><a class="dropdown-item" data-action="edit_selected" data-id="alias" data-api-url='edit/alias' data-api-attr='{"active":"0"}' href="#">{{ lang.mailbox.deactivate }}</a></li>
|
||||
<li><hr class="dropdown-divider"></li>
|
||||
<li><a class="dropdown-item" data-action="delete_selected" data-id="alias" data-api-url='delete/alias' href="#">{{ lang.mailbox.remove }}</a></li>
|
||||
<li class="table_collapse_option"><hr class="dropdown-divider"></li>
|
||||
<li class="table_collapse_option"><a class="dropdown-item" data-datatables-expand="alias_table">{{ lang.datatables.expand_all }}</a></li>
|
||||
<li class="table_collapse_option"><a class="dropdown-item" data-datatables-collapse="alias_table">{{ lang.datatables.collapse_all }}</a></li>
|
||||
{% if not skip_sogo %}
|
||||
<li><hr class="dropdown-divider"></li>
|
||||
<li><a class="dropdown-item" data-action="edit_selected" data-id="alias" data-api-url='edit/alias' data-api-attr='{"sogo_visible":"1"}' href="#">{{ lang.mailbox.sogo_visible_y }}</a></li>
|
||||
<li><a class="dropdown-item" data-action="edit_selected" data-id="alias" data-api-url='edit/alias' data-api-attr='{"sogo_visible":"0"}' href="#">{{ lang.mailbox.sogo_visible_n }}</a></li>
|
||||
{% endif %}
|
||||
</ul>
|
||||
<a class="btn btn-sm btn-xs-lg btn-secondary" data-action="edit_selected" data-id="alias" data-api-url='edit/alias' data-api-attr='{"expand_alias":true}' ><i class="bi bi-arrows-angle-expand"></i> {{ lang.mailbox.add_alias_expand }}</a>
|
||||
<a class="btn btn-sm btn-xs-lg btn-success" href="#" data-bs-toggle="modal" data-bs-target="#addAliasModal"><i class="bi bi-plus-lg"></i> {{ lang.mailbox.add_alias }}</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
53
data/web/templates/mailbox/tab-resources.twig
Executable file
53
data/web/templates/mailbox/tab-resources.twig
Executable file
|
|
@ -0,0 +1,53 @@
|
|||
<div class="tab-pane fade" id="tab-resources" role="tabpanel" aria-labelledby="tab-resources">
|
||||
<div class="card mb-4">
|
||||
<div class="card-header d-flex fs-5">
|
||||
<button class="btn d-md-none flex-grow-1 text-start" data-bs-target="#collapse-tab-resources" data-bs-toggle="collapse" aria-controls="collapse-tab-resources">
|
||||
{{ lang.mailbox.resources }} <span class="badge bg-info table-lines"></span>
|
||||
</button>
|
||||
<span class="d-none d-md-block">{{ lang.mailbox.resources }} <span class="badge bg-info table-lines"></span></span>
|
||||
|
||||
<div class="btn-group ms-auto d-flex">
|
||||
<button class="btn btn-xs btn-secondary refresh_table" data-draw="draw_resource_table" data-table="resource_table">{{ lang.admin.refresh }}</button>
|
||||
</div>
|
||||
</div>
|
||||
<div id="collapse-tab-resources" class="card-body collapse" data-bs-parent="#mail-content">
|
||||
<div class="mass-actions-mailbox mb-4 d-none d-sm-block">
|
||||
<div class="btn-group">
|
||||
<a class="btn btn-sm btn-xs-half btn-secondary" id="toggle_multi_select_all" data-id="resource" href="#"><i class="bi bi-check-all"></i> {{ lang.mailbox.toggle_all }}</a>
|
||||
<a class="btn btn-sm btn-xs-half btn-secondary dropdown-toggle" data-bs-toggle="dropdown" href="#">{{ lang.mailbox.quick_actions }}</a>
|
||||
<ul class="dropdown-menu">
|
||||
<li><a class="dropdown-item" data-action="edit_selected" data-id="resource" data-api-url='edit/resource' data-api-attr='{"active":"1"}' href="#">{{ lang.mailbox.activate }}</a></li>
|
||||
<li><a class="dropdown-item" data-action="edit_selected" data-id="resource" data-api-url='edit/resource' data-api-attr='{"active":"0"}' href="#">{{ lang.mailbox.deactivate }}</a></li>
|
||||
<li><hr class="dropdown-divider"></li>
|
||||
<li><a class="dropdown-item" data-action="delete_selected" data-id="resource" data-api-url='delete/resource' href="#">{{ lang.mailbox.remove }}</a></li>
|
||||
<li class="table_collapse_option"><hr class="dropdown-divider"></li>
|
||||
<li class="table_collapse_option"><a class="dropdown-item" data-datatables-expand="resource_table">{{ lang.datatables.expand_all }}</a></li>
|
||||
<li class="table_collapse_option"><a class="dropdown-item" data-datatables-collapse="resource_table">{{ lang.datatables.collapse_all }}</a></li>
|
||||
</ul>
|
||||
<a class="btn btn-sm btn-success" href="#" data-bs-toggle="modal" data-bs-target="#addResourceModal"><i class="bi bi-plus-lg"></i> {{ lang.mailbox.add_resource }}</a>
|
||||
</div>
|
||||
</div>
|
||||
<p><span class="badge fs-6 bg-success">{{ lang.mailbox.booking_0_short }}</span> - {{ lang.mailbox.booking_null }}</p>
|
||||
<p><span class="badge fs-6 bg-warning">{{ lang.mailbox.booking_lt0_short }}</span> - {{ lang.mailbox.booking_ltnull }}</p>
|
||||
<p><span class="badge fs-6 bg-danger">{{ lang.mailbox.booking_custom_short }}</span> - {{ lang.mailbox.booking_custom }}</p>
|
||||
{#<div class="mass-actions-mailbox" data-actions-header="true"></div>#}
|
||||
<table id="resource_table" class="table table-striped dt-responsive w-100"></table>
|
||||
<div class="mass-actions-mailbox mt-4">
|
||||
<div class="btn-group">
|
||||
<a class="btn btn-sm btn-xs-lg btn-xs-half btn-secondary" id="toggle_multi_select_all" data-id="resource" href="#"><i class="bi bi-check-all"></i> {{ lang.mailbox.toggle_all }}</a>
|
||||
<a class="btn btn-sm btn-xs-lg btn-xs-half btn-secondary dropdown-toggle" data-bs-toggle="dropdown" href="#">{{ lang.mailbox.quick_actions }}</a>
|
||||
<ul class="dropdown-menu">
|
||||
<li><a class="dropdown-item" data-action="edit_selected" data-id="resource" data-api-url='edit/resource' data-api-attr='{"active":"1"}' href="#">{{ lang.mailbox.activate }}</a></li>
|
||||
<li><a class="dropdown-item" data-action="edit_selected" data-id="resource" data-api-url='edit/resource' data-api-attr='{"active":"0"}' href="#">{{ lang.mailbox.deactivate }}</a></li>
|
||||
<li><hr class="dropdown-divider"></li>
|
||||
<li><a class="dropdown-item" data-action="delete_selected" data-id="resource" data-api-url='delete/resource' href="#">{{ lang.mailbox.remove }}</a></li>
|
||||
<li class="table_collapse_option"><hr class="dropdown-divider"></li>
|
||||
<li class="table_collapse_option"><a class="dropdown-item" data-datatables-expand="resource_table">{{ lang.datatables.expand_all }}</a></li>
|
||||
<li class="table_collapse_option"><a class="dropdown-item" data-datatables-collapse="resource_table">{{ lang.datatables.collapse_all }}</a></li>
|
||||
</ul>
|
||||
<a class="btn btn-sm btn-xs-lg btn-success" href="#" data-bs-toggle="modal" data-bs-target="#addResourceModal"><i class="bi bi-plus-lg"></i> {{ lang.mailbox.add_resource }}</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
53
data/web/templates/mailbox/tab-syncjobs.twig
Executable file
53
data/web/templates/mailbox/tab-syncjobs.twig
Executable file
|
|
@ -0,0 +1,53 @@
|
|||
<div class="tab-pane fade" id="tab-syncjobs" role="tabpanel" aria-labelledby="tab-syncjobs">
|
||||
<div class="card mb-4">
|
||||
<div class="card-header d-flex fs-5">
|
||||
<button class="btn d-md-none flex-grow-1 text-start" data-bs-target="#collapse-tab-syncjobs" data-bs-toggle="collapse" aria-controls="collapse-tab-syncjobs">
|
||||
{{ lang.mailbox.sync_jobs }} <span class="badge bg-info table-lines"></span>
|
||||
</button>
|
||||
<span class="d-none d-md-block">{{ lang.mailbox.sync_jobs }} <span class="badge bg-info table-lines"></span></span>
|
||||
|
||||
<div class="btn-group ms-auto d-flex">
|
||||
<button class="btn btn-xs btn-secondary refresh_table" data-draw="draw_sync_job_table" data-table="sync_job_table">{{ lang.admin.refresh }}</button>
|
||||
</div>
|
||||
</div>
|
||||
<div id="collapse-tab-syncjobs" class="card-body collapse" data-bs-parent="#mail-content">
|
||||
<div class="mass-actions-mailbox mb-4 d-none d-sm-block">
|
||||
<div class="btn-group" data-acl="{{ acl.syncjobs }}">
|
||||
<a class="btn btn-sm btn-xs-half btn-secondary" id="toggle_multi_select_all" data-id="syncjob" href="#"><i class="bi bi-check-all"></i> {{ lang.mailbox.toggle_all }}</a>
|
||||
<a class="btn btn-sm btn-xs-half btn-secondary dropdown-toggle" data-bs-toggle="dropdown" href="#">{{ lang.mailbox.quick_actions }}</a>
|
||||
<ul class="dropdown-menu">
|
||||
<li><a class="dropdown-item" data-action="edit_selected" data-id="syncjob" data-api-url='edit/syncjob' data-api-attr='{"last_run":"","success":""}' href="#">{{ lang.mailbox.last_run_reset }}</a></li>
|
||||
<li><hr class="dropdown-divider"></li>
|
||||
<li><a class="dropdown-item" data-action="edit_selected" data-id="syncjob" data-api-url='edit/syncjob' data-api-attr='{"active":"1"}' href="#">{{ lang.mailbox.activate }}</a></li>
|
||||
<li><a class="dropdown-item" data-action="edit_selected" data-id="syncjob" data-api-url='edit/syncjob' data-api-attr='{"active":"0"}' href="#">{{ lang.mailbox.deactivate }}</a></li>
|
||||
<li><hr class="dropdown-divider"></li>
|
||||
<li><a class="dropdown-item" data-action="delete_selected" data-id="syncjob" data-api-url='delete/syncjob' href="#">{{ lang.mailbox.remove }}</a></li>
|
||||
<li class="table_collapse_option"><hr class="dropdown-divider"></li>
|
||||
<li class="table_collapse_option"><a class="dropdown-item" data-datatables-expand="sync_job_table">{{ lang.datatables.expand_all }}</a></li>
|
||||
<li class="table_collapse_option"><a class="dropdown-item" data-datatables-collapse="sync_job_table">{{ lang.datatables.collapse_all }}</a></li>
|
||||
</ul>
|
||||
<a class="btn btn-sm btn-success" href="#" data-bs-toggle="modal" data-bs-target="#addSyncJobModalAdmin"><i class="bi bi-plus-lg"></i> {{ lang.user.create_syncjob }}</a>
|
||||
</div>
|
||||
</div>
|
||||
<table id="sync_job_table" class="table table-striped dt-responsive w-100"></table>
|
||||
<div class="mass-actions-mailbox mt-4">
|
||||
<div class="btn-group" data-acl="{{ acl.syncjobs }}">
|
||||
<a class="btn btn-sm btn-xs-lg btn-xs-half btn-secondary" id="toggle_multi_select_all" data-id="syncjob" href="#"><i class="bi bi-check-all"></i> {{ lang.mailbox.toggle_all }}</a>
|
||||
<a class="btn btn-sm btn-xs-lg btn-xs-half btn-secondary dropdown-toggle" data-bs-toggle="dropdown" href="#">{{ lang.mailbox.quick_actions }}</a>
|
||||
<ul class="dropdown-menu">
|
||||
<li><a class="dropdown-item" data-action="edit_selected" data-id="syncjob" data-api-url='edit/syncjob' data-api-attr='{"last_run":"","success":""}' href="#">{{ lang.mailbox.last_run_reset }}</a></li>
|
||||
<li><hr class="dropdown-divider"></li>
|
||||
<li><a class="dropdown-item" data-action="edit_selected" data-id="syncjob" data-api-url='edit/syncjob' data-api-attr='{"active":"1"}' href="#">{{ lang.mailbox.activate }}</a></li>
|
||||
<li><a class="dropdown-item" data-action="edit_selected" data-id="syncjob" data-api-url='edit/syncjob' data-api-attr='{"active":"0"}' href="#">{{ lang.mailbox.deactivate }}</a></li>
|
||||
<li><hr class="dropdown-divider"></li>
|
||||
<li><a class="dropdown-item" data-action="delete_selected" data-id="syncjob" data-api-url='delete/syncjob' href="#">{{ lang.mailbox.remove }}</a></li>
|
||||
<li class="table_collapse_option"><hr class="dropdown-divider"></li>
|
||||
<li class="table_collapse_option"><a class="dropdown-item" data-datatables-expand="sync_job_table">{{ lang.datatables.expand_all }}</a></li>
|
||||
<li class="table_collapse_option"><a class="dropdown-item" data-datatables-collapse="sync_job_table">{{ lang.datatables.collapse_all }}</a></li>
|
||||
</ul>
|
||||
<a class="btn btn-sm btn-xs-lg btn-success" href="#" data-bs-toggle="modal" data-bs-target="#addSyncJobModalAdmin"><i class="bi bi-plus-lg"></i> {{ lang.user.create_syncjob }}</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
51
data/web/templates/mailbox/tab-templates-domains.twig
Executable file
51
data/web/templates/mailbox/tab-templates-domains.twig
Executable file
|
|
@ -0,0 +1,51 @@
|
|||
<div class="tab-pane fade" id="tab-templates-domains" role="tabpanel" aria-labelledby="tab-templates-domains">
|
||||
<div class="card mb-4">
|
||||
<div class="card-header d-flex fs-5">
|
||||
<button class="btn d-sm-block d-md-none flex-grow-1 text-start" data-bs-target="#collapse-tab-templates-domains" data-bs-toggle="collapse" aria-controls="collapse-tab-templates-domains">
|
||||
{{ lang.mailbox.domain_templates }} <span class="badge bg-info table-lines"></span>
|
||||
</button>
|
||||
<span class="d-none d-md-block">{{ lang.mailbox.domain_templates }} <span class="badge bg-info table-lines"></span></span>
|
||||
|
||||
<div class="btn-group ms-auto d-flex">
|
||||
<button class="btn btn-xs btn-secondary refresh_table" data-draw="draw_templates_domain_table" data-table="templates_domain_table">{{ lang.admin.refresh }}</button>
|
||||
</div>
|
||||
</div>
|
||||
<div id="collapse-tab-templates-domains" class="card-body collapse" data-bs-parent="#mail-content">
|
||||
<div class="mass-actions-mailbox mb-4 d-none d-sm-block">
|
||||
<div class="btn-group">
|
||||
<button class="btn btn-sm btn-xs-half btn-secondary" id="toggle_multi_select_all" data-id="domain_template" href="#"><i class="bi bi-check-all"></i> {{ lang.mailbox.toggle_all }}</button>
|
||||
<button class="btn btn-sm btn-xs-half btn-secondary dropdown-toggle" data-bs-toggle="dropdown" href="#">{{ lang.mailbox.quick_actions }}</button>
|
||||
<ul class="dropdown-menu">
|
||||
{% if mailcow_cc_role == 'admin' %}
|
||||
<li><a class="dropdown-item" data-action="delete_selected" data-id="domain_template" data-api-url='delete/domain/template' href="#">{{ lang.mailbox.remove }}</a></li>
|
||||
<li class="table_collapse_option"><hr class="dropdown-divider"></li>
|
||||
<li class="table_collapse_option"><a class="dropdown-item" data-datatables-expand="templates_domain_table">{{ lang.datatables.expand_all }}</a></li>
|
||||
<li class="table_collapse_option"><a class="dropdown-item" data-datatables-collapse="templates_domain_table">{{ lang.datatables.collapse_all }}</a></li>
|
||||
{% endif %}
|
||||
</ul>
|
||||
{% if mailcow_cc_role == 'admin' %}
|
||||
<button class="btn btn-sm btn-success" data-bs-toggle="modal" data-bs-target="#addDomainTemplateModal"><i class="bi bi-plus-lg"></i> {{ lang.mailbox.add_template }}</button>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
<table id="templates_domain_table" class="table table-striped dt-responsive w-100"></table>
|
||||
<div class="mass-actions-mailbox mt-4">
|
||||
<div class="btn-group">
|
||||
<button class="btn btn-sm btn-xs-lg btn-xs-half btn-secondary" id="toggle_multi_select_all" data-id="domain_template" href="#"><i class="bi bi-check-all"></i> {{ lang.mailbox.toggle_all }}</button>
|
||||
<button class="btn btn-sm btn-xs-lg btn-xs-half btn-secondary dropdown-toggle" data-bs-toggle="dropdown" href="#">{{ lang.mailbox.quick_actions }}</button>
|
||||
<ul class="dropdown-menu">
|
||||
{% if mailcow_cc_role == 'admin' %}
|
||||
<li><a class="dropdown-item" data-action="delete_selected" data-id="domain_template" data-api-url='delete/domain/template' href="#">{{ lang.mailbox.remove }}</a></li>
|
||||
<li class="table_collapse_option"><hr class="dropdown-divider"></li>
|
||||
<li class="table_collapse_option"><a class="dropdown-item" data-datatables-expand="templates_domain_table">{{ lang.datatables.expand_all }}</a></li>
|
||||
<li class="table_collapse_option"><a class="dropdown-item" data-datatables-collapse="templates_domain_table">{{ lang.datatables.collapse_all }}</a></li>
|
||||
{% endif %}
|
||||
</ul>
|
||||
{% if mailcow_cc_role == 'admin' %}
|
||||
<button class="btn btn-sm btn-xs-lg btn-success" href="#" data-bs-toggle="modal" data-bs-target="#addDomainTemplateModal"><i class="bi bi-plus-lg"></i> {{ lang.mailbox.add_template }}</button>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
51
data/web/templates/mailbox/tab-templates-mbox.twig
Executable file
51
data/web/templates/mailbox/tab-templates-mbox.twig
Executable file
|
|
@ -0,0 +1,51 @@
|
|||
<div class="tab-pane fade" id="tab-templates-mbox" role="tabpanel" aria-labelledby="tab-templates-mbox">
|
||||
<div class="card mb-4">
|
||||
<div class="card-header d-flex fs-5">
|
||||
<button class="btn d-sm-block d-md-none flex-grow-1 text-start" data-bs-target="#collapse-tab-templates-mbox" data-bs-toggle="collapse" aria-controls="collapse-tab-templates-mbox">
|
||||
{{ lang.mailbox.mailbox_templates }} <span class="badge bg-info table-lines"></span>
|
||||
</button>
|
||||
<span class="d-none d-md-block">{{ lang.mailbox.mailbox_templates }} <span class="badge bg-info table-lines"></span></span>
|
||||
|
||||
<div class="btn-group ms-auto d-flex">
|
||||
<button class="btn btn-xs btn-secondary refresh_table" data-draw="draw_templates_mbox_table" data-table="templates_mbox_table">{{ lang.admin.refresh }}</button>
|
||||
</div>
|
||||
</div>
|
||||
<div id="collapse-tab-templates-mbox" class="card-body collapse" data-bs-parent="#mail-content">
|
||||
<div class="mass-actions-mailbox mb-4 d-none d-sm-block">
|
||||
<div class="btn-group">
|
||||
<button class="btn btn-sm btn-xs-half btn-secondary" id="toggle_multi_select_all" data-id="mailbox_template" href="#"><i class="bi bi-check-all"></i> {{ lang.mailbox.toggle_all }}</button>
|
||||
<button class="btn btn-sm btn-xs-half btn-secondary dropdown-toggle" data-bs-toggle="dropdown" href="#">{{ lang.mailbox.quick_actions }}</button>
|
||||
<ul class="dropdown-menu">
|
||||
{% if mailcow_cc_role == 'admin' %}
|
||||
<li><a class="dropdown-item" data-action="delete_selected" data-id="mailbox_template" data-api-url='delete/mailbox/template' href="#">{{ lang.mailbox.remove }}</a></li>
|
||||
<li class="table_collapse_option"><hr class="dropdown-divider"></li>
|
||||
<li class="table_collapse_option"><a class="dropdown-item" data-datatables-expand="templates_mbox_table">{{ lang.datatables.expand_all }}</a></li>
|
||||
<li class="table_collapse_option"><a class="dropdown-item" data-datatables-collapse="templates_mbox_table">{{ lang.datatables.collapse_all }}</a></li>
|
||||
{% endif %}
|
||||
</ul>
|
||||
{% if mailcow_cc_role == 'admin' %}
|
||||
<button class="btn btn-sm btn-success" data-bs-toggle="modal" data-bs-target="#addMailboxTemplateModal"><i class="bi bi-plus-lg"></i> {{ lang.mailbox.add_template }}</button>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
<table id="templates_mbox_table" class="table table-striped dt-responsive w-100"></table>
|
||||
<div class="mass-actions-mailbox mt-4">
|
||||
<div class="btn-group">
|
||||
<button class="btn btn-sm btn-xs-lg btn-xs-half btn-secondary" id="toggle_multi_select_all" data-id="mailbox_template" href="#"><i class="bi bi-check-all"></i> {{ lang.mailbox.toggle_all }}</button>
|
||||
<button class="btn btn-sm btn-xs-lg btn-xs-half btn-secondary dropdown-toggle" data-bs-toggle="dropdown" href="#">{{ lang.mailbox.quick_actions }}</button>
|
||||
<ul class="dropdown-menu">
|
||||
{% if mailcow_cc_role == 'admin' %}
|
||||
<li><a class="dropdown-item" data-action="delete_selected" data-id="mailbox_template" data-api-url='delete/mailbox/template' href="#">{{ lang.mailbox.remove }}</a></li>
|
||||
<li class="table_collapse_option"><hr class="dropdown-divider"></li>
|
||||
<li class="table_collapse_option"><a class="dropdown-item" data-datatables-expand="templates_mbox_table">{{ lang.datatables.expand_all }}</a></li>
|
||||
<li class="table_collapse_option"><a class="dropdown-item" data-datatables-collapse="templates_mbox_table">{{ lang.datatables.collapse_all }}</a></li>
|
||||
{% endif %}
|
||||
</ul>
|
||||
{% if mailcow_cc_role == 'admin' %}
|
||||
<button class="btn btn-sm btn-xs-lg btn-success" data-bs-toggle="modal" data-bs-target="#addMailboxTemplateModal"><i class="bi bi-plus-lg"></i> {{ lang.mailbox.add_template }}</button>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
50
data/web/templates/mailbox/tab-tls-policy.twig
Executable file
50
data/web/templates/mailbox/tab-tls-policy.twig
Executable file
|
|
@ -0,0 +1,50 @@
|
|||
<div class="tab-pane fade{% if mailcow_cc_role != 'admin' %} d-none{% endif %}" id="tab-tls-policy" role="tabpanel" aria-labelledby="tab-tls-policy">
|
||||
<div class="card mb-4">
|
||||
<div class="card-header d-flex fs-5">
|
||||
<button class="btn d-md-none flex-grow-1 text-start" data-bs-target="#collapse-tab-tls-policy" data-bs-toggle="collapse" aria-controls="collapse-tab-tls-policy">
|
||||
{{ lang.mailbox.tls_policy_maps_long }} <span class="badge bg-info table-lines"></span>
|
||||
</button>
|
||||
<span class="d-none d-md-block">{{ lang.mailbox.tls_policy_maps_long }} <span class="badge bg-info table-lines"></span></span>
|
||||
|
||||
<div class="btn-group ms-auto d-flex">
|
||||
<button class="btn btn-xs btn-secondary refresh_table" data-draw="draw_tls_policy_table" data-table="tls_policy_table">{{ lang.admin.refresh }}</button>
|
||||
</div>
|
||||
</div>
|
||||
<div id="collapse-tab-tls-policy" class="card-body collapse" data-bs-parent="#mail-content">
|
||||
<div class="mass-actions-mailbox mb-4 d-none d-sm-block">
|
||||
<div class="btn-group">
|
||||
<a class="btn btn-sm btn-xs-half btn-secondary" id="toggle_multi_select_all" data-id="tls-policy-map" href="#"><i class="bi bi-check-all"></i> {{ lang.mailbox.toggle_all }}</a>
|
||||
<a class="btn btn-sm btn-xs-half btn-secondary dropdown-toggle" data-bs-toggle="dropdown" href="#">{{ lang.mailbox.quick_actions }}</a>
|
||||
<ul class="dropdown-menu">
|
||||
<li><a class="dropdown-item" data-action="edit_selected" data-id="tls-policy-map" data-api-url='edit/tls-policy-map' data-api-attr='{"active":"1"}' href="#">{{ lang.mailbox.activate }}</a></li>
|
||||
<li><a class="dropdown-item" data-action="edit_selected" data-id="tls-policy-map" data-api-url='edit/tls-policy-map' data-api-attr='{"active":"0"}' href="#">{{ lang.mailbox.deactivate }}</a></li>
|
||||
<li><hr class="dropdown-divider"></li>
|
||||
<li><a class="dropdown-item" data-action="delete_selected" data-id="tls-policy-map" data-api-url='delete/tls-policy-map' href="#">{{ lang.mailbox.remove }}</a></li>
|
||||
<li class="table_collapse_option"><hr class="dropdown-divider"></li>
|
||||
<li class="table_collapse_option"><a class="dropdown-item" data-datatables-expand="tls_policy_table">{{ lang.datatables.expand_all }}</a></li>
|
||||
<li class="table_collapse_option"><a class="dropdown-item" data-datatables-collapse="tls_policy_table">{{ lang.datatables.collapse_all }}</a></li>
|
||||
</ul>
|
||||
<a class="btn btn-sm btn-success" href="#" data-bs-toggle="modal" data-bs-target="#addTLSPolicyMapAdmin"><i class="bi bi-plus-lg"></i> {{ lang.mailbox.add_tls_policy_map }}</a>
|
||||
</div>
|
||||
</div>
|
||||
<p class="text-muted">{{ lang.mailbox.tls_policy_maps_info|raw }}</p>
|
||||
<table id="tls_policy_table" class="table table-striped dt-responsive w-100"></table>
|
||||
<div class="mass-actions-mailbox mt-4">
|
||||
<div class="btn-group">
|
||||
<a class="btn btn-sm btn-xs-lg btn-xs-half btn-secondary" id="toggle_multi_select_all" data-id="tls-policy-map" href="#"><i class="bi bi-check-all"></i> {{ lang.mailbox.toggle_all }}</a>
|
||||
<a class="btn btn-sm btn-xs-lg btn-xs-half btn-secondary dropdown-toggle" data-bs-toggle="dropdown" href="#">{{ lang.mailbox.quick_actions }}</a>
|
||||
<ul class="dropdown-menu">
|
||||
<li><a class="dropdown-item" data-action="edit_selected" data-id="tls-policy-map" data-api-url='edit/tls-policy-map' data-api-attr='{"active":"1"}' href="#">{{ lang.mailbox.activate }}</a></li>
|
||||
<li><a class="dropdown-item" data-action="edit_selected" data-id="tls-policy-map" data-api-url='edit/tls-policy-map' data-api-attr='{"active":"0"}' href="#">{{ lang.mailbox.deactivate }}</a></li>
|
||||
<li><hr class="dropdown-divider"></li>
|
||||
<li><a class="dropdown-item" data-action="delete_selected" data-id="tls-policy-map" data-api-url='delete/tls-policy-map' href="#">{{ lang.mailbox.remove }}</a></li>
|
||||
<li class="table_collapse_option"><hr class="dropdown-divider"></li>
|
||||
<li class="table_collapse_option"><a class="dropdown-item" data-datatables-expand="tls_policy_table">{{ lang.datatables.expand_all }}</a></li>
|
||||
<li class="table_collapse_option"><a class="dropdown-item" data-datatables-collapse="tls_policy_table">{{ lang.datatables.collapse_all }}</a></li>
|
||||
</ul>
|
||||
<a class="btn btn-sm btn-xs-lg btn-success" href="#" data-bs-toggle="modal" data-bs-target="#addTLSPolicyMapAdmin"><i class="bi bi-plus-lg"></i> {{ lang.mailbox.add_tls_policy_map }}</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
249
data/web/templates/modals/admin.twig
Executable file
249
data/web/templates/modals/admin.twig
Executable file
|
|
@ -0,0 +1,249 @@
|
|||
<!-- add settings rule modal -->
|
||||
<div class="modal fade" id="addRsettingModal" tabindex="-1" role="dialog" aria-hidden="false">
|
||||
<div class="modal-dialog modal-xl">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h3 class="modal-title">{{ lang.admin.add_settings_rule }}</h3>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<form class="form-horizontal" data-cached-form="true" data-id="rsetting" role="form" method="post">
|
||||
<div class="row mb-2">
|
||||
<label class="control-label col-sm-2 text-sm-end" for="desc">{{ lang.admin.rsetting_desc }}:</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="text" class="form-control" id="adminRspamdSettingsDesc" name="desc" required>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-4">
|
||||
<label class="control-label col-sm-2 text-sm-end" for="content">{{ lang.admin.rsetting_content }}:</label>
|
||||
<div class="col-sm-10">
|
||||
<textarea class="form-control" id="adminRspamdSettingsContent" name="content" rows="10"></textarea>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-2">
|
||||
<div class="offset-sm-2 col-sm-10">
|
||||
<div class="form-check">
|
||||
<label><input type="checkbox" class="form-check-input" value="1" name="active" checked> {{ lang.admin.active }}</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-4">
|
||||
<div class="offset-sm-2 col-sm-10">
|
||||
<button class="btn btn-xs-lg d-block d-sm-inline btn-success" data-action="add_item" data-id="rsetting" data-api-url='add/rsetting' data-api-attr='{}' href="#"><i class="bi bi-plus-lg"></i> {{ lang.admin.add }}</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
<hr>
|
||||
<p>{{ lang.admin.rspamd_com_settings | raw }}</p>
|
||||
<ul id="rspamd_presets"></ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div><!-- add settings rule modal -->
|
||||
<!-- add domain admin modal -->
|
||||
<div class="modal fade" id="addDomainAdminModal" tabindex="-1" role="dialog" aria-hidden="true">
|
||||
<div class="modal-dialog modal-xl">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h3 class="modal-title">{{ lang.admin.add_domain_admin }}</h3>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<form class="form-horizontal" data-cached-form="true" data-id="add_domain_admin" role="form" method="post" autocomplete="off">
|
||||
<div class="row mb-2">
|
||||
<label class="control-label col-sm-2 text-sm-end" for="username">{{ lang.admin.username }}:</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="text" class="form-control" name="username" onkeyup="this.value = this.value.toLowerCase();" required>
|
||||
↳ <kbd>a-z - _ .</kbd>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-4">
|
||||
<label class="control-label col-sm-2 text-sm-end" for="name">{{ lang.admin.admin_domains }}:</label>
|
||||
<div class="col-sm-10">
|
||||
<select title="{{ lang.admin.search_domain_da }}" class="full-width-select" name="domains" size="5" multiple>
|
||||
{% for domain in domains %}
|
||||
<option>{{ domain }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-2">
|
||||
<label class="control-label col-sm-2 text-sm-end" for="password">{{ lang.admin.password }} (<a href="#" class="generate_password">{{ lang.admin.generate }}</a>)</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="password" class="form-control" data-pwgen-field="true" data-hibp="true" name="password" placeholder="" autocomplete="new-password" required>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-4">
|
||||
<label class="control-label col-sm-2 text-sm-end" for="password2">{{ lang.admin.password_repeat }}:</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="password" class="form-control" data-pwgen-field="true" name="password2" placeholder="" autocomplete="new-password" required>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-2">
|
||||
<div class="offset-sm-2 col-sm-10">
|
||||
<div class="form-check">
|
||||
<label><input type="checkbox" class="form-check-input" value="1" name="active" checked> {{ lang.admin.active }}</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-4">
|
||||
<div class="offset-sm-2 col-sm-10">
|
||||
<button class="btn btn-xs-lg d-block d-sm-inline btn-success" data-action="add_item" data-id="add_domain_admin" data-api-url='add/domain-admin' data-api-attr='{}' href="#"><i class="bi bi-plus-lg"></i> {{ lang.admin.add }}</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div><!-- add domain admin modal -->
|
||||
<!-- change fido2 fn -->
|
||||
<div class="modal fade" id="fido2ChangeFn" tabindex="-1" role="dialog" aria-hidden="true">
|
||||
<div class="modal-dialog modal-xl">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h3 class="modal-title">{{ lang.fido2.set_fn }}</h3>
|
||||
<p class="text-muted" style="word-break:break-all" id="fido2_subject_desc" data-fido2-subject=""></p>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<form class="form-horizontal" data-cached-form="false" data-id="fido2ChangeFn" role="form" method="post" autocomplete="off">
|
||||
<input type="hidden" class="form-control" name="fido2_cid" id="fido2_cid">
|
||||
<div class="row mb-4">
|
||||
<label class="control-label col-sm-4" for="fido2_fn">{{ lang.fido2.fn }}:</label>
|
||||
<div class="col-sm-8">
|
||||
<input type="text" class="form-control" name="fido2_fn">
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-4">
|
||||
<div class="offset-sm-4 col-sm-8">
|
||||
<button class="btn btn-xs-lg d-block d-sm-inline btn-success" data-action="edit_selected" data-id="fido2ChangeFn" data-item="null" data-api-url='edit/fido2-fn' data-api-attr='{}' href="#">{{ lang.admin.save }}</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div><!-- add domain admin modal -->
|
||||
<!-- add oauth2 client modal -->
|
||||
<div class="modal fade" id="addOAuth2ClientModal" tabindex="-1" role="dialog" aria-hidden="true">
|
||||
<div class="modal-dialog modal-xl">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h3 class="modal-title">OAuth2</h3>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<form class="form-horizontal" data-cached-form="true" data-id="add_oauth2_client" role="form" method="post">
|
||||
<div class="row mb-4">
|
||||
<label class="control-label col-sm-2 text-sm-end" for="redirect_uri">{{ lang.admin.oauth2_redirect_uri }}:</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="text" class="form-control" name="redirect_uri" required>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-4">
|
||||
<div class="offset-sm-2 col-sm-10">
|
||||
<button class="btn btn-xs-lg d-block d-sm-inline btn-success" data-action="add_item" data-id="add_oauth2_client" data-api-url='add/oauth2-client' data-api-attr='{}' href="#"><i class="bi bi-plus-lg"></i> {{ lang.admin.add }}</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div><!-- add domain admin modal -->
|
||||
<!-- add admin modal -->
|
||||
<div class="modal fade" id="addAdminModal" tabindex="-1" role="dialog" aria-hidden="true">
|
||||
<div class="modal-dialog modal-xl">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h3 class="modal-title">{{ lang.admin.add_admin }}</h3>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<form class="form-horizontal" data-cached-form="true" data-id="add_admin" role="form" method="post" autocomplete="off">
|
||||
<div class="row mb-4">
|
||||
<label class="control-label col-sm-2 text-sm-end" for="username">{{ lang.admin.username }}:</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="text" class="form-control" name="username" onkeyup="this.value = this.value.toLowerCase();" required>
|
||||
↳ <kbd>a-z - _ .</kbd>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-2">
|
||||
<label class="control-label col-sm-2 text-sm-end" for="password">{{ lang.admin.password }} (<a href="#" class="generate_password">{{ lang.admin.generate }}</a>):</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="password" class="form-control" data-pwgen-field="true" data-hibp="true" name="password" placeholder="" autocomplete="new-password" required>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-4">
|
||||
<label class="control-label col-sm-2 text-sm-end" for="password2">{{ lang.admin.password_repeat }}:</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="password" class="form-control" data-pwgen-field="true" name="password2" placeholder="" autocomplete="new-password" required>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-2">
|
||||
<div class="offset-sm-2 col-sm-10">
|
||||
<div class="form-check">
|
||||
<label><input type="checkbox" class="form-check-input" value="1" name="active" checked> {{ lang.admin.active }}</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-4">
|
||||
<div class="offset-sm-2 col-sm-10">
|
||||
<button class="btn btn-xs-lg d-block d-sm-inline btn-success" data-action="add_item" data-id="add_admin" data-api-url='add/admin' data-api-attr='{}' href="#"><i class="bi bi-plus-lg"></i> {{ lang.admin.add }}</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div><!-- add admin modal -->
|
||||
<!-- test transport modal -->
|
||||
<div class="modal fade" id="testTransportModal" tabindex="-1" role="dialog" aria-hidden="true">
|
||||
<div class="modal-dialog modal-xl">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h3 class="modal-title"><i class="bi bi-info-circle-fill"></i> Transport</h3>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<form class="form-horizontal" data-cached-form="true" id="test_transport_form" role="form" method="post">
|
||||
<input type="hidden" class="form-control" name="transport_id" id="transport_id">
|
||||
<input type="hidden" class="form-control" name="transport_type" id="transport_type">
|
||||
<div class="row mb-2">
|
||||
<label class="control-label col-sm-2 text-sm-end" for="mail_from">{{ lang.admin.relay_from }}</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="text" class="form-control" name="mail_from" placeholder="relay@example.org">
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-4">
|
||||
<label class="control-label col-sm-2 text-sm-end" for="mail_rcpt">{{ lang.admin.relay_rcpt }}</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="text" class="form-control" name="mail_rcpt" placeholder="null@hosted.mailcow.de" value="null@hosted.mailcow.de">
|
||||
<p class="text-muted">{{ lang.admin.transport_test_rcpt_info|raw }}</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-4">
|
||||
<div class="offset-sm-2 col-sm-10">
|
||||
<button class="btn btn-xs-lg d-block d-sm-inline btn-secondary" id="test_transport" href="#">{{ lang.admin.relay_run }}</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
<hr>
|
||||
<div id="test_transport_result" style="font-size:10pt">-</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div><!-- test transport modal -->
|
||||
<!-- priv key modal -->
|
||||
<div class="modal fade" id="showDKIMprivKey" tabindex="-1" role="dialog" aria-hidden="true">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h3 class="modal-title"><i class="bi bi-key-fill"></i> Private key</h3>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<pre id="priv_key_pre"></pre>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div><!-- priv key modal -->
|
||||
365
data/web/templates/modals/footer.twig
Executable file
365
data/web/templates/modals/footer.twig
Executable file
|
|
@ -0,0 +1,365 @@
|
|||
{% if mailcow_cc_role %}
|
||||
<div class="modal fade" id="YubiOTPModal" tabindex="-1" role="dialog" aria-labelledby="YubiOTPModalLabel">
|
||||
<div class="modal-dialog" role="document">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h3 class="modal-title">{{ lang.tfa.yubi_otp }}</h3>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<form role="form" method="post">
|
||||
<div class="mb-4">
|
||||
<input type="text" class="form-control" name="key_id" placeholder="{{ lang.tfa.key_id }}" autocomplete="off" required>
|
||||
</div>
|
||||
<hr>
|
||||
<p class="text-muted">{{ lang.tfa.api_register|format(ui_texts.main_name)|raw }}</p>
|
||||
<div class="mb-2">
|
||||
<input type="text" class="form-control" name="yubico_id" placeholder="Yubico API ID" autocomplete="off" required>
|
||||
</div>
|
||||
<div class="mb-4">
|
||||
<input type="text" class="form-control" name="yubico_key" placeholder="Yubico API Key" autocomplete="off" required>
|
||||
</div>
|
||||
<hr>
|
||||
<div class="mb-4">
|
||||
<input type="password" class="form-control" name="confirm_password" placeholder="{{ lang.user.password_now }}" autocomplete="off" required>
|
||||
</div>
|
||||
<div class="mb-4">
|
||||
<div class="input-group">
|
||||
<span class="input-group-text" id="yubi-addon"><img alt="Yubicon Icon" src="/img/yubi.ico"></span>
|
||||
<input type="text" name="otp_token" class="form-control" placeholder="Touch Yubikey" aria-describedby="yubi-addon">
|
||||
<input type="hidden" name="tfa_method" value="yubi_otp">
|
||||
</div>
|
||||
</div>
|
||||
<button class="btn btn-sm d-block d-sm-inline btn-success" type="submit" name="set_tfa">{{ lang.user.save_changes }}</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="modal fade" id="WebAuthnModal" tabindex="-1" role="dialog" aria-labelledby="WebAuthnModalLabel">
|
||||
<div class="modal-dialog" role="document">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h3 class="modal-title">{{ lang.tfa.webauthn }}</h3>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<form class="d-flex flex-column" role="form" method="post" id="webauthn_reg_form">
|
||||
<div class="mb-2">
|
||||
<input type="text" class="form-control" name="key_id" placeholder="{{ lang.tfa.key_id }}" autocomplete="off" required>
|
||||
</div>
|
||||
<div class="mb-4">
|
||||
<input type="password" class="form-control" name="confirm_password" placeholder="{{ lang.user.password_now }}" autocomplete="off" required>
|
||||
</div>
|
||||
<hr>
|
||||
<div class="text-center">
|
||||
<div style="cursor:pointer" id="start_webauthn_register">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="64" height="64" viewBox="0 0 24 24">
|
||||
<path d="M17.81 4.47c-.08 0-.16-.02-.23-.06C15.66 3.42 14 3 12.01 3c-1.98 0-3.86.47-5.57 1.41-.24.13-.54.04-.68-.2-.13-.24-.04-.55.2-.68C7.82 2.52 9.86 2 12.01 2c2.13 0 3.99.47 6.03 1.52.25.13.34.43.21.67-.09.18-.26.28-.44.28zM3.5 9.72c-.1 0-.2-.03-.29-.09-.23-.16-.28-.47-.12-.7.99-1.4 2.25-2.5 3.75-3.27C9.98 4.04 14 4.03 17.15 5.65c1.5.77 2.76 1.86 3.75 3.25.16.22.11.54-.12.7-.23.16-.54.11-.7-.12-.9-1.26-2.04-2.25-3.39-2.94-2.87-1.47-6.54-1.47-9.4.01-1.36.7-2.5 1.7-3.4 2.96-.08.14-.23.21-.39.21zm6.25 12.07c-.13 0-.26-.05-.35-.15-.87-.87-1.34-1.43-2.01-2.64-.69-1.23-1.05-2.73-1.05-4.34 0-2.97 2.54-5.39 5.66-5.39s5.66 2.42 5.66 5.39c0 .28-.22.5-.5.5s-.5-.22-.5-.5c0-2.42-2.09-4.39-4.66-4.39-2.57 0-4.66 1.97-4.66 4.39 0 1.44.32 2.77.93 3.85.64 1.15 1.08 1.64 1.85 2.42.19.2.19.51 0 .71-.11.1-.24.15-.37.15zm7.17-1.85c-1.19 0-2.24-.3-3.1-.89-1.49-1.01-2.38-2.65-2.38-4.39 0-.28.22-.5.5-.5s.5.22.5.5c0 1.41.72 2.74 1.94 3.56.71.48 1.54.71 2.54.71.24 0 .64-.03 1.04-.1.27-.05.53.13.58.41.05.27-.13.53-.41.58-.57.11-1.07.12-1.21.12zM14.91 22c-.04 0-.09-.01-.13-.02-1.59-.44-2.63-1.03-3.72-2.1-1.4-1.39-2.17-3.24-2.17-5.22 0-1.62 1.38-2.94 3.08-2.94 1.7 0 3.08 1.32 3.08 2.94 0 1.07.93 1.94 2.08 1.94s2.08-.87 2.08-1.94c0-3.77-3.25-6.83-7.25-6.83-2.84 0-5.44 1.58-6.61 4.03-.39.81-.59 1.76-.59 2.8 0 .78.07 2.01.67 3.61.1.26-.03.55-.29.64-.26.1-.55-.04-.64-.29-.49-1.31-.73-2.61-.73-3.96 0-1.2.23-2.29.68-3.24 1.33-2.79 4.28-4.6 7.51-4.6 4.55 0 8.25 3.51 8.25 7.83 0 1.62-1.38 2.94-3.08 2.94s-3.08-1.32-3.08-2.94c0-1.07-.93-1.94-2.08-1.94s-2.08.87-2.08 1.94c0 1.71.66 3.31 1.87 4.51.95.94 1.86 1.46 3.27 1.85.27.07.42.35.35.61-.05.23-.26.38-.47.38z"></path>
|
||||
</svg>
|
||||
<p>{{ lang.tfa.start_webauthn_validation }}</p>
|
||||
</div>
|
||||
</div>
|
||||
<hr>
|
||||
<p id="webauthn_status_reg"></p>
|
||||
<div class="alert alert-danger" style="display:none" id="webauthn_return_code"></div>
|
||||
<input type="hidden" name="token" id="webauthn_register_data"/>
|
||||
<input type="hidden" name="tfa_method" value="webauthn">
|
||||
<input type="hidden" name="set_tfa"/><br/>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="modal fade" id="TOTPModal" tabindex="-1" role="dialog" aria-labelledby="TOTPModalLabel">
|
||||
<div class="modal-dialog" role="document">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h3 class="modal-title">{{ lang.tfa.totp }}</h3>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<form role="form" method="post">
|
||||
<div class="mb-2">
|
||||
<input type="text" class="form-control" name="key_id" placeholder="{{ lang.tfa.key_id_totp }}" autocomplete="off" required>
|
||||
</div>
|
||||
<div class="mb-4">
|
||||
<input type="password" class="form-control" name="confirm_password" placeholder="{{ lang.user.password_now }}" autocomplete="off" required>
|
||||
</div>
|
||||
<hr>
|
||||
<input type="hidden" value="{{ totp_secret }}" name="totp_secret">
|
||||
<input type="hidden" name="tfa_method" value="totp">
|
||||
<ol class="mb-4">
|
||||
<li>
|
||||
<p>{{ lang.tfa.scan_qr_code }}</p>
|
||||
<img id="tfa-qr-img" data-totp-secret="{{ totp_secret }}" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkYAAAAAYAAjCB0C8AAAAASUVORK5CYII=">
|
||||
<p class="text-muted">{{ lang.tfa.enter_qr_code }}:<br />
|
||||
<code>{{ totp_secret }}</code>
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>{{ lang.tfa.confirm_totp_token }}:</p>
|
||||
<p><input type="number" style="width:33%" class="form-control" name="totp_confirm_token" autocomplete="off" required></p>
|
||||
<p><button class="btn btn-sm d-block d-sm-inline btn-success" type="submit" name="set_tfa">{{ lang.tfa.confirm }}</button></p>
|
||||
</li>
|
||||
</ol>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="modal fade" id="DisableTFAModal" tabindex="-1" role="dialog" aria-labelledby="DisableTFAModalLabel">
|
||||
<div class="modal-dialog" role="document">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h3 class="modal-title">{{ lang.tfa.delete_tfa }}</h3>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<form role="form" method="post">
|
||||
<div class="input-group">
|
||||
<input type="password" class="form-control" name="confirm_password" placeholder="{{ lang.user.password_now }}" autocomplete="off" required>
|
||||
<button class="btn btn-sm d-block d-sm-inline btn-danger" type="submit" name="set_tfa">{{ lang.tfa.delete_tfa|replace({" ": " "})|raw }}</button>
|
||||
</div>
|
||||
<input type="hidden" name="tfa_method" value="none">
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% if pending_tfa_methods %}
|
||||
<div class="modal fade" id="ConfirmTFAModal" tabindex="-1" role="dialog" aria-labelledby="ConfirmTFAModalLabel">
|
||||
<div class="modal-dialog" role="document">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h3 class="modal-title">{{ lang.tfa.tfa }}</h3>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="modal-body p-0 pt-4">
|
||||
<ul class="nav nav-tabs px-1" id="tabContent">
|
||||
{% if pending_tfa_authmechs["webauthn"] is defined and pending_tfa_authmechs["u2f"] is not defined %}
|
||||
<li class="nav-item"><a class="nav-link active" href="#tfa_tab_webauthn" data-bs-toggle="tab" id="pending_tfa_tab_webauthn"><i class="bi bi-fingerprint"></i> WebAuthn</a></li>
|
||||
{% endif %}
|
||||
|
||||
{% if pending_tfa_authmechs["yubi_otp"] is defined and pending_tfa_authmechs["u2f"] is not defined %}
|
||||
<li class="nav-item">
|
||||
<a class="nav-link {% if pending_tfa_authmechs["yubi_otp"] %}active{% endif %}" href="#tfa_tab_yubi_otp" data-bs-toggle="tab" id="pending_tfa_tab_yubi_otp"><i class="bi bi-usb-drive"></i> Yubi OTP</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
|
||||
{% if pending_tfa_authmechs["totp"] is defined and pending_tfa_authmechs["u2f"] is not defined %}
|
||||
<li class="nav-item">
|
||||
<a class="nav-link {% if pending_tfa_authmechs["totp"] %}active{% endif %}" href="#tfa_tab_totp" data-bs-toggle="tab" id="pending_tfa_tab_totp"><i class="bi bi-clock-history"></i> Time-based OTP</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
|
||||
<!-- <li class="nav-item"><a class="nav-link" href="#tfa_tab_hotp" data-bs-toggle="tab">HOTP</a></li> -->
|
||||
{% if pending_tfa_authmechs["u2f"] is defined %}
|
||||
<li class="nav-item"><a class="nav-link active" href="#tfa_tab_u2f" data-bs-toggle="tab"><i class="bi bi-x-octagon"></i> U2F</a></li>
|
||||
{% endif %}
|
||||
</ul>
|
||||
|
||||
<div class="tab-content">
|
||||
{% if pending_tfa_authmechs["webauthn"] is defined and pending_tfa_authmechs["u2f"] is not defined %}
|
||||
<div role="tabpanel" class="tab-pane active" id="tfa_tab_webauthn">
|
||||
<div class="card border-0" style="margin-bottom: 0px;">
|
||||
<div class="card-body">
|
||||
<form role="form" method="post" id="webauthn_auth_form">
|
||||
<legend class="mt-2 mb-2">
|
||||
<i class="bi bi-shield-fill-check"></i>
|
||||
{{ lang.tfa.authenticators }}
|
||||
<hr />
|
||||
</legend>
|
||||
<div class="list-group">
|
||||
{% for authenticator in pending_tfa_methods %}
|
||||
{% if authenticator["authmech"] == "webauthn" %}
|
||||
<a href="#" class="list-group-item webauthn-authenticator-selection">
|
||||
<i class="bi bi-key-fill" style="margin-right: 5px"></i>
|
||||
<span>{{ authenticator["key_id"] }}</span>
|
||||
<input type="hidden" value="{{ authenticator["id"] }}" /><br/>
|
||||
</a>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</div>
|
||||
<div class="collapse pending-tfa-collapse" id="collapseWebAuthnTFA">
|
||||
<div class="row mt-4 mb-4">
|
||||
<div class="col-12">
|
||||
<div class="mt-4 d-flex align-items-center" id="webauthn_status_auth">
|
||||
<div class="spinner-border me-2" role="status">
|
||||
<span class="visually-hidden">Loading...</span>
|
||||
</div>
|
||||
{{ lang.tfa.init_webauthn }}
|
||||
</div>
|
||||
<div class="mt-4 alert alert-danger" style="display:none" id="webauthn_return_code"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<input type="hidden" name="token" id="webauthn_auth_data"/>
|
||||
<input type="hidden" name="tfa_method" value="webauthn">
|
||||
<input type="hidden" name="verify_tfa_login"/>
|
||||
<input type="hidden" name="id" id="webauthn_selected_id" /><br/>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% if pending_tfa_authmechs["yubi_otp"] is defined and pending_tfa_authmechs["u2f"] is not defined %}
|
||||
<div role="tabpanel" class="tab-pane {% if pending_tfa_authmechs["yubi_otp"] %}active{% endif %}" id="tfa_tab_yubi_otp">
|
||||
<div class="card border-0" style="margin-bottom: 0px;">
|
||||
<div class="card-body">
|
||||
<form role="form" method="post">
|
||||
<legend class="mt-2 mb-2">
|
||||
<i class="bi bi-shield-fill-check"></i>
|
||||
{{ lang.tfa.authenticators }}
|
||||
<hr />
|
||||
</legend>
|
||||
<div class="collapse show pending-tfa-collapse" id="collapseYubiTFA">
|
||||
<div class="row mt-4 mb-4">
|
||||
<div class="col-12">
|
||||
<div class="input-group mt-4">
|
||||
<span class="input-group-text" id="yubi-addon"><img alt="Yubicon Icon" src="/img/yubi.ico"></span>
|
||||
<input type="text" name="token" class="form-control" autocomplete="off" placeholder="Touch Yubikey" aria-describedby="yubi-addon">
|
||||
<input type="hidden" name="tfa_method" value="yubi_otp">
|
||||
<input type="hidden" name="id" id="yubi_selected_id" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<button class="btn btn-sm visible-xs-block visible-sm-inline visible-md-inline visible-lg-inline btn-secondary" type="submit" name="verify_tfa_login">{{ lang.login.login }}</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% if pending_tfa_authmechs["totp"] is defined and pending_tfa_authmechs["u2f"] is not defined %}
|
||||
<div role="tabpanel" class="tab-pane {% if pending_tfa_authmechs["totp"] %}active{% endif %}" id="tfa_tab_totp">
|
||||
<div class="card border-0" style="margin-bottom: 0px;">
|
||||
<div class="card-body">
|
||||
<form role="form" method="post">
|
||||
<legend class="mt-2 mb-2">
|
||||
<i class="bi bi-shield-fill-check"></i>
|
||||
{{ lang.tfa.authenticators }}
|
||||
<hr />
|
||||
</legend>
|
||||
<div class="list-group">
|
||||
{% for authenticator in pending_tfa_methods %}
|
||||
{% if authenticator["authmech"] == "totp" %}
|
||||
<a href="#" class="list-group-item totp-authenticator-selection">
|
||||
<i class="bi bi-key-fill" style="margin-right: 5px"></i>
|
||||
<span>{{ authenticator["key_id"] }}</span>
|
||||
<input type="hidden" value="{{ authenticator["id"] }}" />
|
||||
</a>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</div>
|
||||
<div class="collapse pending-tfa-collapse" id="collapseTotpTFA">
|
||||
<div class="row mt-4 mb-4">
|
||||
<div class="col-12">
|
||||
<div class="input-group mt-4">
|
||||
<span class="input-group-text" id="tfa-addon"><i class="bi bi-shield-lock-fill"></i></span>
|
||||
<input type="number" min="000000" max="999999" name="token" class="form-control" placeholder="123456" autocomplete="one-time-code" aria-describedby="tfa-addon">
|
||||
<input type="hidden" name="tfa_method" value="totp">
|
||||
<input type="hidden" name="id" id="totp_selected_id" /><br/>
|
||||
</div>
|
||||
<button class="mt-4 btn btn-sm visible-xs-block visible-sm-inline visible-md-inline visible-lg-inline btn-secondary" type="submit" name="verify_tfa_login">{{ lang.login.login }}</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
<!--
|
||||
<div role="tabpanel" class="tab-pane" id="tfa_tab_hotp">
|
||||
<div class="card" style="margin-bottom: 0px;">
|
||||
<div class="card-body">
|
||||
<div class="empty"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
-->
|
||||
{% if pending_tfa_authmechs["u2f"] is defined %}
|
||||
<div role="tabpanel" class="tab-pane active" id="tfa_tab_u2f">
|
||||
<div class="card border-0" style="margin-bottom: 0px;">
|
||||
<div class="card-body">
|
||||
{# leave this here to inform users that u2f is deprecated #}
|
||||
<form role="form" method="post" id="u2f_auth_form">
|
||||
<div>
|
||||
<p>{{ lang.tfa.u2f_deprecated }}</p>
|
||||
<p><b>{{ lang.tfa.u2f_deprecated_important }}</b></p>
|
||||
<input type="hidden" name="token" value="destroy" />
|
||||
<input type="hidden" name="tfa_method" value="u2f">
|
||||
<input type="hidden" name="verify_tfa_login"/><br/>
|
||||
<button type="submit" class="btn btn-xs-lg btn-success" value="Login">{{ lang.login.login }}</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% if mailcow_cc_role == 'admin' %}
|
||||
<div id="RestartContainer" class="modal fade" role="dialog">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h4 class="modal-title">{{ lang.footer.restart_container }} (<code id="containerName"></code>)</h4>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<p>{{ lang.footer.restart_container_info|raw }}</p>
|
||||
<hr>
|
||||
<button class="btn btn-md d-block d-sm-inline btn-primary" id="triggerRestartContainer">{{ lang.footer.restart_now }}</button>
|
||||
<br><br>
|
||||
<div id="statusTriggerRestartContainer"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
<div id="ConfirmDeleteModal" class="modal fade" role="dialog">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h3 class="modal-title">{{ lang.footer.confirm_delete }}</h3>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<p id="DeleteText">{{ lang.footer.delete_these_items }}</p>
|
||||
<ul id="ItemsToDelete"></ul>
|
||||
<hr>
|
||||
<button class="btn btn-sm btn-xs-half d-block d-sm-inline btn-danger" id="IsConfirmed">{{ lang.footer.delete_now }}</button>
|
||||
<button class="btn btn-sm btn-xs-half d-block d-sm-inline btn-secondary" id="isCanceled">{{ lang.footer.cancel }}</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- version modal -->
|
||||
<div class="modal fade" id="showVersionModal" tabindex="-1" role="dialog" aria-hidden="true">
|
||||
<div class="modal-dialog modal-lg">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title"></h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
|
||||
</div>
|
||||
<div class="modal-body d-flex flex-column mt-2 p-4">
|
||||
<div class="spinner-border mx-auto" role="status">
|
||||
<span class="visually-hidden">Loading...</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div><!-- version modal -->
|
||||
1274
data/web/templates/modals/mailbox.twig
Executable file
1274
data/web/templates/modals/mailbox.twig
Executable file
File diff suppressed because it is too large
Load diff
68
data/web/templates/modals/quarantine.twig
Executable file
68
data/web/templates/modals/quarantine.twig
Executable file
|
|
@ -0,0 +1,68 @@
|
|||
<div class="modal fade" id="qidDetailModal" tabindex="-1" role="dialog" aria-hidden="true">
|
||||
<div class="modal-dialog modal-xl">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h3 class="modal-title"><i class="bi bi-info-circle-fill"></i> {{ lang.quarantine.qitem }}</h3>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div id="qid_error" style="display:none" class="alert alert-danger"></div>
|
||||
<div>
|
||||
<label for="qid_detail_symbols"><h4>{{ lang.quarantine.rspamd_result }}:</h4></label>
|
||||
<p>{{ lang.quarantine.spam_score }}: <span id="qid_detail_score"></span></p>
|
||||
<hr>
|
||||
<p id="qid_detail_symbols"></p>
|
||||
</div>
|
||||
<div>
|
||||
<label for="qid_detail_subj"><h4>{{ lang.quarantine.subj }}:</h4></label>
|
||||
<p id="qid_detail_subj"></p>
|
||||
</div>
|
||||
<div>
|
||||
<label for="qid_detail_recipients"><h4>{{ lang.quarantine.recipients }}:</h4></label>
|
||||
<p id="qid_detail_recipients"></p>
|
||||
</div>
|
||||
<div>
|
||||
<label for="qid_detail_hfrom"><h4>{{ lang.quarantine.sender_header }}:</h4></label>
|
||||
<p><span class="mail-address-item" id="qid_detail_hfrom"></span></p>
|
||||
</div>
|
||||
<div>
|
||||
<label for="qid_detail_efrom"><h4>{{ lang.quarantine.sender }}:</h4></label>
|
||||
<p><span class="mail-address-item" id="qid_detail_efrom"></span></p>
|
||||
</div>
|
||||
<div>
|
||||
<label for="qid_detail_fuzzy"><h4>Fuzzy Hashes:</h4></label>
|
||||
<p id="qid_detail_fuzzy"></p>
|
||||
</div>
|
||||
<div id="qTextPlain">
|
||||
<label for="qid_detail_text"><h4>{{ lang.quarantine.text_plain_content }}:</h4></label>
|
||||
<pre id="qid_detail_text"></pre>
|
||||
</div>
|
||||
<div id="qTextHtml">
|
||||
<label for="qid_detail_text_from_html"><h4>{{ lang.quarantine.text_from_html_content }}:</h4></label>
|
||||
<pre id="qid_detail_text_from_html"></pre>
|
||||
</div>
|
||||
{% if acl.quarantine_attachments == 1 %}
|
||||
<div>
|
||||
<label for="qid_detail_atts"><h4>{{ lang.quarantine.atts }}:</h4></label>
|
||||
<div id="qid_detail_atts">-</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
<div class="btn-group dropup" data-acl="{{ acl.quarantine }}">
|
||||
<a class="btn btn-sm btn-secondary dropdown-toggle" data-bs-toggle="dropdown" href="#">{{ lang.quarantine.quick_actions }}</a>
|
||||
<ul class="dropdown-menu">
|
||||
<li><a class="dropdown-item" data-action="edit_selected" data-id="qitems_single" data-item="" data-api-url='edit/qitem' data-api-attr='{"action":"release"}' href="#">{{ lang.quarantine.deliver_inbox }}</a></li>
|
||||
<li><hr class="dropdown-divider"></li>
|
||||
<li><a class="dropdown-item" data-action="edit_selected" data-id="qitems_single" data-item="" data-api-url='edit/qitem' data-api-attr='{"action":"learnspam"}' href="#">{{ lang.quarantine.learn_spam_delete }}</a></li>
|
||||
<li><hr class="dropdown-divider"></li>
|
||||
<li><a class="dropdown-item" data-id="qitems_single" data-item="" id="quick_download_link" href="#">{{ lang.quarantine.download_eml }}</a></li>
|
||||
<li><hr class="dropdown-divider"></li>
|
||||
<li><a class="dropdown-item" data-id="qitems_single" data-item="" id="quick_release_link" href="#">{{ lang.quarantine.quick_release_link }}</a></li>
|
||||
<li><a class="dropdown-item" data-id="qitems_single" data-item="" id="quick_delete_link" href="#">{{ lang.quarantine.quick_delete_link }}</a></li>
|
||||
<li><hr class="dropdown-divider"></li>
|
||||
<li><a class="dropdown-item" data-action="delete_selected" data-id="qitems_single" data-item="" data-api-url='delete/qitem' href="#">{{ lang.quarantine.remove }}</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
14
data/web/templates/modals/queue.twig
Executable file
14
data/web/templates/modals/queue.twig
Executable file
|
|
@ -0,0 +1,14 @@
|
|||
<!-- show queue item modal -->
|
||||
<div class="modal fade" id="showQueuedMsg" tabindex="-1" role="dialog" aria-hidden="true">
|
||||
<div class="modal-dialog modal-xl">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h3 class="modal-title"><i class="bi bi-card-checklist" style="font-size:18px"></i> ID <span id="queue_id"></span></h3>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<textarea class="form-control" id="queue_msg_content" name="content" rows="40"></textarea>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div><!-- show queue item modal -->
|
||||
388
data/web/templates/modals/user.twig
Executable file
388
data/web/templates/modals/user.twig
Executable file
|
|
@ -0,0 +1,388 @@
|
|||
<!-- change fido2 fn -->
|
||||
<div class="modal fade" id="fido2ChangeFn" tabindex="-1" role="dialog" aria-hidden="true">
|
||||
<div class="modal-dialog modal-lg">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h3 class="modal-title">{{ lang.fido2.set_fn }}</h3>
|
||||
<p class="text-muted" style="word-break:break-all" id="fido2_subject_desc" data-fido2-subject=""></p>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<form class="form-horizontal" data-cached-form="false" data-id="fido2ChangeFn" role="form" method="post" autocomplete="off">
|
||||
<input type="hidden" class="form-control" name="fido2_cid" id="fido2_cid">
|
||||
<div class="row mb-4">
|
||||
<label class="control-label col-sm-4 text-end" for="fido2_fn">{{ lang.fido2.fn }}:</label>
|
||||
<div class="col-sm-8">
|
||||
<input type="text" class="form-control" name="fido2_fn">
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="offset-sm-4 col-sm-8">
|
||||
<button class="btn btn-xs-lg d-block d-sm-inline btn-success" data-action="edit_selected" data-id="fido2ChangeFn" data-item="null" data-api-url='edit/fido2-fn' data-api-attr='{}' href="#">{{ lang.admin.save }}</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div><!-- add domain admin modal -->
|
||||
<!-- add sync job modal -->
|
||||
<div class="modal fade" id="addSyncJobModal" tabindex="-1" role="dialog" aria-hidden="true">
|
||||
<div class="modal-dialog modal-xl">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h3 class="modal-title">{{ lang.add.syncjob }}</h3>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<p>{{ lang.add.syncjob_hint }}</p>
|
||||
<form class="form-horizontal" data-cached-form="true" role="form" data-id="add_syncjob">
|
||||
<div class="row mb-2">
|
||||
<label class="control-label col-sm-2" for="host1">{{ lang.add.hostname }}</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="text" class="form-control" name="host1" required>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-4">
|
||||
<label class="control-label col-sm-2" for="port1">{{ lang.add.port }}</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="number" class="form-control" name="port1" min="1" max="65535" value="143" required>
|
||||
<small class="text-muted">1-65535</small>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-2">
|
||||
<label class="control-label col-sm-2" for="user1">{{ lang.add.username }}</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="text" class="form-control" name="user1" required>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-4">
|
||||
<label class="control-label col-sm-2" for="password1">{{ lang.add.password }}</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="password" class="form-control" name="password1" data-hibp="true" required>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-2">
|
||||
<label class="control-label col-sm-2" for="enc1">{{ lang.add.enc_method }}</label>
|
||||
<div class="col-sm-10">
|
||||
<select name="enc1" title="{{ lang.add.select }}" required>
|
||||
<option value="SSL" selected>SSL</option>
|
||||
<option value="TLS">STARTTLS</option>
|
||||
<option value="PLAIN">PLAIN</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-2">
|
||||
<label class="control-label col-sm-2" for="mins_interval">{{ lang.add.mins_interval }}</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="number" class="form-control" name="mins_interval" min="1" max="43800" value="20" required>
|
||||
<small class="text-muted">1-43800</small>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-2">
|
||||
<label class="control-label col-sm-2" for="subfolder2">{{ lang.edit.subfolder2|raw }}</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="text" class="form-control" name="subfolder2" value="">
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-2">
|
||||
<label class="control-label col-sm-2" for="maxage">{{ lang.edit.maxage|raw }}</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="number" class="form-control" name="maxage" min="0" max="32000" value="0">
|
||||
<small class="text-muted">0-32000</small>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-2">
|
||||
<label class="control-label col-sm-2" for="maxbytespersecond">{{ lang.edit.maxbytespersecond|raw }}</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="number" class="form-control" name="maxbytespersecond" min="0" max="125000000" value="0">
|
||||
<small class="text-muted">0-125000000</small>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-2">
|
||||
<label class="control-label col-sm-2" for="timeout1">{{ lang.edit.timeout1 }}</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="number" class="form-control" name="timeout1" min="1" max="32000" value="600">
|
||||
<small class="text-muted">1-32000</small>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-2">
|
||||
<label class="control-label col-sm-2" for="timeout2">{{ lang.edit.timeout2 }}</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="number" class="form-control" name="timeout2" min="1" max="32000" value="600">
|
||||
<small class="text-muted">1-32000</small>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-2">
|
||||
<label class="control-label col-sm-2" for="exclude">{{ lang.add.exclude }}</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="text" class="form-control" name="exclude" value="(?i)spam|(?i)junk">
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-4">
|
||||
<label class="control-label col-sm-2" for="custom_params">{{ lang.add.custom_params }}</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="text" class="form-control" name="custom_params" placeholder="--delete2folders --otheroption">
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-2">
|
||||
<div class="offset-sm-2 col-sm-10">
|
||||
<div class="form-check">
|
||||
<label><input type="checkbox" class="form-check-input" value="1" name="delete2duplicates" checked> {{ lang.add.delete2duplicates }} (--delete2duplicates)</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-2">
|
||||
<div class="offset-sm-2 col-sm-10">
|
||||
<div class="form-check">
|
||||
<label><input type="checkbox" class="form-check-input" value="1" name="delete1"> {{ lang.add.delete1 }} (--delete1)</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-2">
|
||||
<div class="offset-sm-2 col-sm-10">
|
||||
<div class="form-check">
|
||||
<label><input type="checkbox" class="form-check-input" value="1" name="delete2"> {{ lang.add.delete2 }} (--delete2)</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-2">
|
||||
<div class="offset-sm-2 col-sm-10">
|
||||
<div class="form-check">
|
||||
<label><input type="checkbox" class="form-check-input" value="1" name="automap" checked> {{ lang.add.automap }} (--automap)</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-2">
|
||||
<div class="offset-sm-2 col-sm-10">
|
||||
<div class="form-check">
|
||||
<label><input type="checkbox" class="form-check-input" value="1" name="skipcrossduplicates"> {{ lang.add.skipcrossduplicates }} (--skipcrossduplicates)</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-2">
|
||||
<div class="offset-sm-2 col-sm-10">
|
||||
<div class="form-check">
|
||||
<label><input type="checkbox" class="form-check-input" value="1" name="subscribeall" checked> {{ lang.add.subscribeall }} (--subscribeall)</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-2">
|
||||
<div class="offset-sm-2 col-sm-10">
|
||||
<div class="form-check">
|
||||
<label><input type="checkbox" class="form-check-input" value="1" name="dry" checked> {{ lang.add.dry }} (--dry)</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-4">
|
||||
<div class="offset-sm-2 col-sm-10">
|
||||
<div class="form-check">
|
||||
<label><input type="checkbox" class="form-check-input" value="1" name="active" checked> {{ lang.add.active }}</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-2">
|
||||
<div class="offset-sm-2 col-sm-10">
|
||||
<button class="btn btn-xs-lg d-block d-sm-inline btn-success" data-action="add_item" data-id="add_syncjob" data-api-url='add/syncjob' data-api-attr='{}' href="#">{{ lang.admin.add }}</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div><!-- add sync job modal -->
|
||||
<!-- app passwd modal -->
|
||||
<div class="modal fade" id="addAppPasswdModal" tabindex="-1" role="dialog" aria-hidden="true">
|
||||
<div class="modal-dialog modal-lg">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h3 class="modal-title">{{ lang.add.app_password }}</h3>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<form class="form-horizontal" data-cached-form="true" role="form" data-pwgen-length="32" data-id="add_apppasswd">
|
||||
<div class="row mb-2">
|
||||
<label class="control-label col-sm-2" for="app_name">{{ lang.add.app_name }}</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="text" class="form-control" name="app_name" required>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-4">
|
||||
<label class="control-label col-sm-2" for="app_passwd">{{ lang.user.password }} (<a href="#" class="generate_password">{{ lang.user.generate }}</a>)</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="password" data-pwgen-field="true" data-hibp="true" class="form-control" name="app_passwd" autocomplete="new-password" required>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-2">
|
||||
<label class="control-label col-sm-2" for="app_passwd2">{{ lang.user.password_repeat }}</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="password" data-pwgen-field="true" class="form-control" name="app_passwd2" autocomplete="new-password" required>
|
||||
<p class="text-muted">{{ lang.user.new_password_description }}</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-4">
|
||||
<label class="control-label col-sm-2" for="protocols">{{ lang.add.app_passwd_protocols }}</label>
|
||||
<div class="col-sm-10">
|
||||
<select class="full-width-select" data-live-search="true" id="protocols" name="protocols" multiple>
|
||||
<option value="imap_access" selected>IMAP</option>
|
||||
<option value="smtp_access" selected>SMTP</option>
|
||||
<option value="eas_access" selected>EAS/ActiveSync</option>
|
||||
<option value="dav_access" selected>CardDAV/CalDAV</option>
|
||||
<option value="pop3_access" selected>POP3</option>
|
||||
<option value="sieve_access" selected>Sieve</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-2">
|
||||
<div class="offset-sm-2 col-sm-10">
|
||||
<div class="form-check">
|
||||
<label><input type="checkbox" class="form-check-input" value="1" name="active" checked> {{ lang.add.active }}</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-2">
|
||||
<div class="offset-sm-2 col-sm-10">
|
||||
<button class="btn btn-xs-lg d-block d-sm-inline btn-success" data-action="add_item" data-id="add_apppasswd" data-api-url='add/app-passwd' data-api-attr='{}' href="#">{{ lang.admin.add }}</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div><!-- add app passwd modal -->
|
||||
<!-- log modal -->
|
||||
<div class="modal fade" id="syncjobLogModal" tabindex="-1" role="dialog" aria-labelledby="syncjobLogModalLabel">
|
||||
<div class="modal-dialog modal-xl" role="document">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h3 class="modal-title">Log</h3>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<textarea class="form-control textarea-code" rows="20" id="logText" spellcheck="false"></textarea>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div><!-- log modal -->
|
||||
<!-- pw change modal -->
|
||||
<div class="modal fade" id="pwChangeModal" tabindex="-1" role="dialog" aria-labelledby="pwChangeModalLabel">
|
||||
<div class="modal-dialog modal-lg" role="document">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h3 class="modal-title">{{ lang.user.change_password }}</h3>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<form class="form-horizontal" data-cached-form="false" data-id="pwchange" role="form" method="post" autocomplete="off">
|
||||
<div class="row">
|
||||
<label class="control-label col-sm-3" for="user_new_pass">{{ lang.user.new_password }} (<a href="#" class="generate_password">{{ lang.user.generate }}</a>)</label>
|
||||
<div class="col-sm-9">
|
||||
<input type="password" data-pwgen-field="true" data-hibp="true" class="form-control" name="user_new_pass" autocomplete="new-password" required>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<label class="control-label col-sm-3" for="user_new_pass2">{{ lang.user.new_password_repeat }}</label>
|
||||
<div class="col-sm-9">
|
||||
<input type="password" data-pwgen-field="true" class="form-control" name="user_new_pass2" autocomplete="new-password" required>
|
||||
<p class="text-muted">{{ lang.user.new_password_description }}</p>
|
||||
</div>
|
||||
</div>
|
||||
<hr>
|
||||
<div class="row mb-4">
|
||||
<label class="control-label col-sm-3" for="user_old_pass">{{ lang.user.password_now }}</label>
|
||||
<div class="col-sm-9">
|
||||
<input type="password" class="form-control" name="user_old_pass" autocomplete="off" required>
|
||||
{% if number_of_app_passwords > 0 %}
|
||||
<div class="invalid-feedback d-block">
|
||||
{{ lang.user.change_password_hint_app_passwords|format(number_of_app_passwords) }}
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="offset-sm-3 col-sm-9">
|
||||
<button class="btn btn-xs-lg d-block d-sm-inline btn-success" data-action="edit_selected" data-id="pwchange" data-item="null" data-api-url='edit/self' data-api-attr='{}' href="#">{{ lang.user.change_password }}</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div><!-- pw change modal -->
|
||||
<!-- pw recovery email modal -->
|
||||
<div class="modal fade" id="pwRecoveryEmailModal" tabindex="-1" role="dialog" aria-labelledby="pwRecoveryEmailModalLabel">
|
||||
<div class="modal-dialog modal-lg" role="document">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h3 class="modal-title">{{ lang.user.pw_recovery_email }}</h3>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<form class="form-horizontal" data-cached-form="false" data-id="pw_recovery_change" role="form" method="post" autocomplete="off">
|
||||
<div class="row mb-4">
|
||||
<label class="control-label col-sm-3" for="pw_recovery_email">{{ lang.user.email }}</label>
|
||||
<div class="col-sm-9">
|
||||
<input type="email" class="form-control" name="pw_recovery_email" value="{{ mailboxdata.attributes.recovery_email }}">
|
||||
<small class="text-muted">{{ lang.user.password_reset_info }}</small>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="offset-sm-3 col-sm-9">
|
||||
<button class="btn btn-xs-lg d-block d-sm-inline btn-success" data-action="edit_selected" data-id="pw_recovery_change" data-item="null" data-api-url='edit/self' data-api-attr='{}' href="#">{{ lang.user.save }}</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div><!-- pw recovery email modal -->
|
||||
<!-- temp alias modal -->
|
||||
<div class="modal fade" id="tempAliasModal" tabindex="-1" role="dialog" aria-labelledby="tempAliasModalLabel">
|
||||
<div class="modal-dialog modal-lg" role="document">
|
||||
<div class="modal-content">
|
||||
<div class="modal-body">
|
||||
<form class="form-horizontal" data-cached-form="false" data-id="pwchange" role="form" method="post" autocomplete="off">
|
||||
<div class="row">
|
||||
<label class="control-label col-sm-3" for="user_new_pass">{{ lang.user.new_password }} (<a href="#" class="generate_password">{{ lang.user.generate }}</a>)</label>
|
||||
<div class="col-sm-5">
|
||||
<input type="password" data-pwgen-field="true" data-hibp="true" class="form-control" name="user_new_pass" autocomplete="new-password" required>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<label class="control-label col-sm-3" for="user_new_pass2">{{ lang.user.new_password_repeat }}</label>
|
||||
<div class="col-sm-5">
|
||||
<input type="password" data-pwgen-field="true" class="form-control" name="user_new_pass2" autocomplete="new-password" required>
|
||||
<p class="text-muted">{{ lang.user.new_password_description }}</p>
|
||||
</div>
|
||||
</div>
|
||||
<hr>
|
||||
<div class="row">
|
||||
<label class="control-label col-sm-3" for="user_old_pass">{{ lang.user.password_now }}</label>
|
||||
<div class="col-sm-5">
|
||||
<input type="password" class="form-control" name="user_old_pass" autocomplete="off" required>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="offset-sm-3 col-sm-9">
|
||||
<button class="btn btn-xs-lg d-block d-sm-inline btn-success" data-action="edit_selected" data-id="pwchange" data-item="null" data-api-url='edit/self' data-api-attr='{}' href="#">{{ lang.user.change_password }}</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div><!-- temp alias modal -->
|
||||
<!-- sieve filter modal -->
|
||||
<div class="modal fade" id="userFilterModal" tabindex="-1" role="dialog">
|
||||
<div class="modal-dialog modal-lg" role="document">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h3 class="modal-title">{{ lang.user.active_sieve }}</h3>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<pre id="user_sieve_filter"></pre>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div><!-- sieve filter modal -->
|
||||
27
data/web/templates/oauth/authorize.twig
Executable file
27
data/web/templates/oauth/authorize.twig
Executable file
|
|
@ -0,0 +1,27 @@
|
|||
{% extends 'base.twig' %}
|
||||
|
||||
{% block content %}
|
||||
<div class="card">
|
||||
<div class="card-header">{{ lang.oauth2.authorize_app }}</div>
|
||||
<div class="card-body">
|
||||
{% if mailcow_cc_role == 'user' %}
|
||||
<p>{{ lang.oauth2.scope_ask_permission }}:</p>
|
||||
<dl class="dl-horizontal">
|
||||
<dt>{{ lang.oauth2.profile }}</dt>
|
||||
<dd>{{ lang.oauth2.profile_desc }}</dd>
|
||||
</dl>
|
||||
<form class="form-horizontal" autocapitalize="none" autocorrect="off" role="form" method="post">
|
||||
<div class="row">
|
||||
<div class="col-sm-10 text-center">
|
||||
<button class="btn btn-success" name="authorized" type="submit" value="1">{{ lang.oauth2.permit }}</button>
|
||||
<a href="#" class="btn btn-secondary" onclick="window.history.back()" role="button">{{ lang.oauth2.deny }}</a>
|
||||
<input type="hidden" name="csrf_token" value="{{ csrf_token }}">
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
{% else %}
|
||||
<p>{{ lang.oauth2.access_denied }}</p>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
83
data/web/templates/qhandler.twig
Executable file
83
data/web/templates/qhandler.twig
Executable file
|
|
@ -0,0 +1,83 @@
|
|||
{% extends 'base.twig' %}
|
||||
|
||||
{% block content %}
|
||||
<div class="row">
|
||||
{% if quick_release or quick_delete %}
|
||||
<div class="offset-md-2 col-md-8">
|
||||
<div class="card">
|
||||
<div class="card-header"><i class="bi bi-patch-exclamation-fill"></i> {{ lang.header.quarantine }}</div>
|
||||
<div class="card-body">
|
||||
<legend>
|
||||
{% if quick_release %}
|
||||
{{ lang.quarantine.release }}
|
||||
{% else %}
|
||||
{{ lang.quarantine.remove }}
|
||||
{% endif %}
|
||||
</legend>
|
||||
<hr />
|
||||
<p>{{ lang.quarantine.qhandler_success }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% else %}
|
||||
{% if is_action_release_delete and is_hash_present %}
|
||||
<div class="-offset-md-2 col-md-8">
|
||||
<div class="card">
|
||||
<div class="card-header"><i class="bi bi-patch-exclamation-fill"></i> {{ lang.header.quarantine }}</div>
|
||||
<div class="card-body">
|
||||
{% if action == 'release' %}
|
||||
<legend id="qtitle" data-hash="{{ hash }}">{{ lang.quarantine.release }}</legend><hr />
|
||||
{% endif %}
|
||||
{% if action == 'delete' %}
|
||||
<legend id="qtitle" data-hash="{{ hash }}">{{ lang.quarantine.remove }}</legend><hr />
|
||||
{% endif %}
|
||||
<div id="qid_error" style="display:none" class="alert alert-danger"></div>
|
||||
<div>
|
||||
<label for="qid_detail_symbols"><h4>{{ lang.quarantine.rspamd_result }}:</h4></label>
|
||||
<p>{{ lang.quarantine.spam_score }}: <span id="qid_detail_score"></span></p>
|
||||
<p id="qid_detail_symbols"></p>
|
||||
</div>
|
||||
<div>
|
||||
<label for="qid_detail_subj"><h4>{{ lang.quarantine.subj }}:</h4></label>
|
||||
<p id="qid_detail_subj"></p>
|
||||
</div>
|
||||
<div>
|
||||
<label for="qid_detail_hfrom"><h4>{{ lang.quarantine.sender_header }}:</h4></label>
|
||||
<p><span class="mail-address-item" id="qid_detail_hfrom"></span></p>
|
||||
</div>
|
||||
<div>
|
||||
<label for="qid_detail_efrom"><h4>{{ lang.quarantine.sender }}:</h4></label>
|
||||
<p><span class="mail-address-item" id="qid_detail_efrom"></span></p>
|
||||
</div>
|
||||
<div>
|
||||
<label for="qid_detail_recipients"><h4>{{ lang.quarantine.recipients }}:</h4></label>
|
||||
<p id="qid_detail_recipients"></p>
|
||||
</div>
|
||||
<div>
|
||||
<label for="qid_detail_fuzzy"><h4>Fuzzy Hashes:</h4></label>
|
||||
<p id="qid_detail_fuzzy"></p>
|
||||
</div>
|
||||
<div id="qactions">
|
||||
<form method="post" autofill="off">
|
||||
<div>
|
||||
{% if action == 'release' %}
|
||||
<button type="submit" class="btn btn-success" name="quick_release" value="{{ hash }}">{{ lang.quarantine.confirm }}</button>
|
||||
{% endif %}
|
||||
{% if action == 'delete' %}
|
||||
<button type="submit" class="btn btn-success" name="quick_delete" value="{{ hash }}">{{ lang.quarantine.confirm }}</button>
|
||||
{% endif %}
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
</div> <!-- /row -->
|
||||
|
||||
|
||||
<script type='text/javascript'>
|
||||
var lang = {{ lang_quarantine|raw }};
|
||||
</script>
|
||||
{% endblock %}
|
||||
72
data/web/templates/quarantine.twig
Executable file
72
data/web/templates/quarantine.twig
Executable file
|
|
@ -0,0 +1,72 @@
|
|||
{% extends 'base.twig' %}
|
||||
|
||||
{% block content %}
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<div class="card card-xs-lg">
|
||||
<div class="card-header d-flex">
|
||||
{{ lang.quarantine.quarantine }} <span class="badge bg-info table-lines"></span>
|
||||
<div class="btn-group ms-auto">
|
||||
<button class="btn btn-xs btn-xs-lg btn-secondary refresh_table" data-draw="draw_quarantine_table" data-table="quarantinetable">{{ lang.quarantine.refresh }}</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="mass-actions-quarantine mb-4">
|
||||
<div class="btn-group" data-acl="{{ acl.quarantine }}">
|
||||
<a class="btn btn-sm btn-xs-half d-block d-sm-inline btn-secondary" id="toggle_multi_select_all" data-id="qitems" href="#"><i class="bi bi-check-all"></i> {{ lang.quarantine.toggle_all }}</a>
|
||||
<a class="btn btn-sm btn-xs-half d-block d-sm-inline btn-secondary dropdown-toggle" data-bs-toggle="dropdown" href="#">{{ lang.quarantine.quick_actions }}</a>
|
||||
<ul class="dropdown-menu">
|
||||
<li class="table_collapse_option"><a class="dropdown-item" data-datatables-expand="quarantinetable" data-table="quarantinetable" href="#">{{ lang.datatables.expand_all }}</a></li>
|
||||
<li class="table_collapse_option"><a class="dropdown-item" data-datatables-collapse="quarantinetable" data-table="quarantinetable" href="#">{{ lang.datatables.collapse_all }}</a></li>
|
||||
<li class="table_collapse_option"><hr class="dropdown-divider"></li>
|
||||
<li><a class="dropdown-item" data-action="edit_selected" data-id="qitems" data-api-url='edit/qitem' data-api-attr='{"action":"release"}' href="#">{{ lang.quarantine.deliver_inbox }}</a></li>
|
||||
<li><hr class="dropdown-divider"></li>
|
||||
<li><a class="dropdown-item" data-action="edit_selected" data-id="qitems" data-api-url='edit/qitem' data-api-attr='{"action":"learnspam"}' href="#">{{ lang.quarantine.learn_spam_delete }}</a></li>
|
||||
<li><hr class="dropdown-divider"></li>
|
||||
<li><a class="dropdown-item" data-action="delete_selected" data-id="qitems" data-api-url='delete/qitem' href="#">{{ lang.quarantine.remove }}</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<p class="text-muted">{{ lang.quarantine.qinfo|raw }}</p>
|
||||
<p>
|
||||
{% if not quarantine_settings.retention_size or not quarantine_settings.max_size %}
|
||||
<div class="alert alert-info">{{ lang.quarantine.disabled_by_config }}</div>
|
||||
{% else %}
|
||||
<p style="margin:10px" class="text-muted">
|
||||
{{ lang.quarantine.settings_info|format(quarantine_settings.retention_size, quarantine_settings.max_size)|raw }}
|
||||
</p>
|
||||
{% endif %}
|
||||
</p>
|
||||
<table id="quarantinetable" class="table table-striped w-100"></table>
|
||||
<div class="mass-actions-quarantine mt-4">
|
||||
<div class="btn-group" data-acl="{{ acl.quarantine }}">
|
||||
<a class="btn btn-sm btn-xs-half d-block d-sm-inline btn-secondary" id="toggle_multi_select_all" data-id="qitems" href="#"><i class="bi bi-check-all"></i> {{ lang.quarantine.toggle_all }}</a>
|
||||
<a class="btn btn-sm btn-xs-half d-block d-sm-inline btn-secondary dropdown-toggle" data-bs-toggle="dropdown" href="#">{{ lang.quarantine.quick_actions }}</a>
|
||||
<ul class="dropdown-menu">
|
||||
<li class="table_collapse_option"><a class="dropdown-item" data-datatables-expand="quarantinetable" data-table="quarantinetable" href="#">{{ lang.datatables.expand_all }}</a></li>
|
||||
<li class="table_collapse_option"><a class="dropdown-item" data-datatables-collapse="quarantinetable" data-table="quarantinetable" href="#">{{ lang.datatables.collapse_all }}</a></li>
|
||||
<li class="table_collapse_option"><hr class="dropdown-divider"></li>
|
||||
<li><a class="dropdown-item" data-action="edit_selected" data-id="qitems" data-api-url='edit/qitem' data-api-attr='{"action":"release"}' href="#">{{ lang.quarantine.deliver_inbox }}</a></li>
|
||||
<li><hr class="dropdown-divider"></li>
|
||||
<li><a class="dropdown-item" data-action="edit_selected" data-id="qitems" data-api-url='edit/qitem' data-api-attr='{"action":"learnspam"}' href="#">{{ lang.quarantine.learn_spam_delete }}</a></li>
|
||||
<li><hr class="dropdown-divider"></li>
|
||||
<li><a class="dropdown-item" data-action="delete_selected" data-id="qitems" data-api-url='delete/qitem' href="#">{{ lang.quarantine.remove }}</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div> <!-- /col-md-12 -->
|
||||
</div> <!-- /row -->
|
||||
|
||||
{% include 'modals/quarantine.twig' %}
|
||||
|
||||
<script type='text/javascript'>
|
||||
var acl = '{{ acl_json|raw }}';
|
||||
var lang = {{ lang_quarantine|raw }};
|
||||
var lang_datatables = {{ lang_datatables|raw }};
|
||||
var csrf_token = '{{ csrf_token }}';
|
||||
var pagination_size = Math.trunc('{{ pagination_size }}');
|
||||
var role = '{{ role }}';
|
||||
</script>
|
||||
{% endblock %}
|
||||
61
data/web/templates/queue.twig
Executable file
61
data/web/templates/queue.twig
Executable file
|
|
@ -0,0 +1,61 @@
|
|||
{% extends 'base.twig' %}
|
||||
|
||||
{% block content %}
|
||||
<div class="card mb-4">
|
||||
<div class="card-header d-flex fs-5">
|
||||
<span>{{ lang.queue.queue_manager }} <span class="badge bg-info table-lines"></span></span>
|
||||
<div class="btn-group ms-auto">
|
||||
<button class="btn btn-xs btn-secondary refresh_table" data-draw="draw_queue" data-table="queuetable">{{ lang.admin.refresh }}</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<p class="text-muted">{{ lang.queue.info|raw }}</p>
|
||||
<p class="text-muted"><b>{{ lang.queue.legend|raw }}</b></p>
|
||||
<ul class="text-muted">
|
||||
<li>{{ lang.queue.deliver_mail }} | {{ lang.queue.deliver_mail_legend }}</li>
|
||||
<li>{{ lang.queue.unhold_mail }} | {{ lang.queue.unhold_mail_legend }}</li>
|
||||
<li>{{ lang.queue.hold_mail }} | {{ lang.queue.hold_mail_legend }}</li>
|
||||
</ul>
|
||||
<table id="queuetable" class="table table-striped dt-responsive w-100"></table>
|
||||
<div class="mass-actions-admin">
|
||||
<div class="btn-group">
|
||||
<a class="btn btn-sm btn-xs-half d-block d-sm-inline btn-secondary" id="toggle_multi_select_all" data-id="mailqitems" href="#"><i class="bi bi-check-all"></i> {{ lang.mailbox.toggle_all }}</a>
|
||||
<a class="btn btn-sm btn-xs-half d-block d-sm-inline btn-secondary dropdown-toggle" data-bs-toggle="dropdown" href="#">{{ lang.mailbox.quick_actions }}</a>
|
||||
<ul class="dropdown-menu">
|
||||
<li><a class="dropdown-item" data-bs-toggle="tooltip" title="postqueue -i" data-action="edit_selected" data-id="mailqitems" data-api-url='edit/mailq' data-api-attr='{"action":"deliver"}' href="#">{{ lang.queue.deliver_mail }}</a></li>
|
||||
<li><a class="dropdown-item" data-bs-toggle="tooltip" title="postsuper -H" data-action="edit_selected" data-id="mailqitems" data-api-url='edit/mailq' data-api-attr='{"action":"unhold"}' href="#">{{ lang.queue.unhold_mail }}</a></li>
|
||||
<li><a class="dropdown-item" data-bs-toggle="tooltip" title="postsuper -h" data-action="edit_selected" data-id="mailqitems" data-api-url='edit/mailq' data-api-attr='{"action":"hold"}' href="#">{{ lang.queue.hold_mail }}</a></li>
|
||||
<li><hr class="dropdown-divider"></li>
|
||||
<li><a class="dropdown-item" data-bs-toggle="tooltip" title="postsuper -d" data-action="delete_selected" data-id="mailqitems" data-api-url='delete/mailq' href="#">{{ lang.mailbox.remove }}</a></li>
|
||||
</ul>
|
||||
<a class="btn btn-sm d-block d-sm-inline btn-primary"
|
||||
data-action="edit_selected"
|
||||
data-item="mailqitems-all"
|
||||
data-api-url='edit/mailq'
|
||||
data-api-attr='{"action":"flush"}'
|
||||
data-bs-toggle="tooltip" title="postqueue -f"
|
||||
href="#"><i class="bi bi-check-all"></i> {{ lang.queue.flush }}</a>
|
||||
<a class="btn btn-sm d-block d-sm-inline btn-danger"
|
||||
id="super_delete"
|
||||
data-action="edit_selected"
|
||||
data-item="mailqitems-all"
|
||||
data-api-url='edit/mailq'
|
||||
data-api-attr='{"action":"super_delete"}'
|
||||
data-bs-toggle="tooltip" title="postsuper -d ALL"
|
||||
href="#"><i class="bi bi-trash"></i> {{ lang.queue.delete }}</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% include 'modals/queue.twig' %}
|
||||
|
||||
<script type='text/javascript'>
|
||||
var lang_admin = {{ lang_admin|raw }};
|
||||
var lang = {{ lang_queue|raw }};
|
||||
var lang_datatables = {{ lang_datatables|raw }};
|
||||
var csrf_token = '{{ csrf_token }}';
|
||||
var pagination_size = Math.trunc('{{ pagination_size }}');
|
||||
var table_for_domain = '{{ domain }}';
|
||||
</script>
|
||||
{% endblock %}
|
||||
57
data/web/templates/reset-password.twig
Executable file
57
data/web/templates/reset-password.twig
Executable file
|
|
@ -0,0 +1,57 @@
|
|||
{% extends 'base.twig' %}
|
||||
|
||||
{% block navbar %}{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="row mb-4" style="margin-top: 60px">
|
||||
<div class="col-12 col-md-7 col-lg-6 col-xl-5 ms-auto me-auto">
|
||||
<div class="card">
|
||||
<div class="card-header d-flex align-items-center">
|
||||
<i class="bi bi-person-fill me-2"></i> {{ lang.login.reset_password }}
|
||||
<div class="ms-auto form-check form-switch my-auto d-flex align-items-center">
|
||||
<label class="form-check-label"><i class="bi bi-moon-fill"></i></label>
|
||||
<input class="form-check-input ms-2" type="checkbox" id="dark-mode-toggle">
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="text-center mailcow-logo mb-4">
|
||||
<img class="main-logo" src="{{ logo|default('/img/cow_mailcow.svg') }}" alt="mailcow">
|
||||
<img class="main-logo-dark" src="{{ logo_dark|default('/img/cow_mailcow.svg') }}" alt="mailcow-logo-dark">
|
||||
</div>
|
||||
<legend>{{ ui_texts.main_name|raw }}</legend><hr />
|
||||
|
||||
{% if is_reset_token_valid %}
|
||||
<form method="post" autofill="off">
|
||||
<input type="hidden" name="token" value="{{ reset_token }}" />
|
||||
<input type="password" autocorrect="off" autocapitalize="none" class="form-control mb-2" name="new_password" placeholder="{{ lang.login.new_password }}" />
|
||||
<input type="password" autocorrect="off" autocapitalize="none" class="form-control mb-2" name="new_password2" placeholder="{{ lang.login.new_password_confirm }}" />
|
||||
|
||||
<small id="mismatch_alert" class="text-danger d-none">{{ lang.login.password_mismatch }}</small>
|
||||
<div class="d-flex justify-content-end mt-4" style="position: relative">
|
||||
<button type="submit" class="btn btn-xs-lg d-block d-sm-inline btn-success" name="pw_reset">{{ lang.login.reset_password }}</button>
|
||||
</div>
|
||||
</form>
|
||||
{% elseif reset_token is null %}
|
||||
<form method="post" autofill="off">
|
||||
<input type="text" autocorrect="off" autocapitalize="none" class="form-control mb-2" name="username" placeholder="{{ lang.login.username }}" />
|
||||
|
||||
<div class="d-flex justify-content-end mt-4" style="position: relative">
|
||||
<button type="submit" class="btn btn-xs-lg d-block d-sm-inline btn-success" name="pw_reset_request">{{ lang.login.request_reset_password }}</button>
|
||||
</div>
|
||||
</form>
|
||||
{% else %}
|
||||
<p class="text-center">{{ lang.login.invalid_pass_reset_token|raw }}</p>
|
||||
<a href="/">{{ lang.login.back_to_mailcow }}</a>
|
||||
{% endif %}
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script type='text/javascript'>
|
||||
var csrf_token = '{{ csrf_token }}';
|
||||
var mailcow_cc_username = '{{ mailcow_cc_username }}';
|
||||
</script>
|
||||
{% endblock %}
|
||||
15
data/web/templates/tfa_keys.twig
Executable file
15
data/web/templates/tfa_keys.twig
Executable file
|
|
@ -0,0 +1,15 @@
|
|||
<div id="tfa_keys">
|
||||
{% if tfa_data.additional %}
|
||||
{% for key_info in tfa_data.additional %}
|
||||
<form style="display:inline;" method="post">
|
||||
<input type="hidden" name="unset_tfa_key" value="{{ key_info.id }}">
|
||||
<div class="d-flex flex-column">
|
||||
<span style="padding:4px;margin:4px" class="me-auto badge fs-6 bg-{% if tfa_id == key_info.id %}success{% else %}dark{% endif %}">
|
||||
{{ key_info.key_id }}
|
||||
<a href="#" class="btn p-0 text-white" style="font-size: 12px; line-height: 1rem;" onClick='return confirm("{{ lang.admin.ays }}")?$(this).closest("form").submit():"";'>[{{ lang.admin.remove }}]</a>
|
||||
</span>
|
||||
</div>
|
||||
</form>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
</div>
|
||||
49
data/web/templates/user.twig
Executable file
49
data/web/templates/user.twig
Executable file
|
|
@ -0,0 +1,49 @@
|
|||
{% extends 'base.twig' %}
|
||||
|
||||
{% block content %}
|
||||
<div id="user-content" class="responsive-tabs">
|
||||
<!-- Nav tabs -->
|
||||
<ul class="nav nav-tabs" role="tablist">
|
||||
<li class="nav-item dropdown" role="presentation">
|
||||
<a class="nav-link dropdown-toggle active" data-bs-toggle="dropdown" href="#" role="button" aria-expanded="false">{{ lang.user.mailbox }}</a>
|
||||
<ul class="dropdown-menu">
|
||||
<li><button class="dropdown-item active" role="tab" aria-selected="true" aria-controls="tab-user-auth" data-bs-toggle="tab" data-bs-target="#tab-user-auth">{{ lang.user.mailbox_general }}</button></li>
|
||||
<li><button class="dropdown-item" role="tab" aria-selected="false" aria-controls="tab-config-fwdhosts" data-bs-toggle="tab" data-bs-target="#tab-user-details">{{ lang.user.mailbox_details }}</button></li>
|
||||
<li><button class="dropdown-item" role="tab" aria-selected="false" aria-controls="tab-config-f2b" data-bs-toggle="tab" data-bs-target="#tab-user-settings">{{ lang.user.mailbox_settings }}</button></li>
|
||||
</ul>
|
||||
</li>
|
||||
{% if acl.spam_alias == 1 %}
|
||||
<li class="nav-item" role="presentation"><button class="nav-link" role="tab" aria-selected="false" aria-controls="SpamAliases" role="tab" data-bs-toggle="tab" data-bs-target="#SpamAliases">{{ lang.user.spam_aliases }}</button></li>
|
||||
{% endif %}
|
||||
{% if acl.spam_score == 1 %}
|
||||
<li class="nav-item" role="presentation"><button class="nav-link" role="tab" aria-selected="false" aria-controls="Spamfilter" role="tab" data-bs-toggle="tab" data-bs-target="#Spamfilter">{{ lang.user.spamfilter }}</button></li>
|
||||
{% endif %}
|
||||
{% if acl.syncjobs == 1 %}
|
||||
<li class="nav-item" role="presentation"><button class="nav-link" role="tab" aria-selected="false" aria-controls="Syncjobs" role="tab" data-bs-toggle="tab" data-bs-target="#Syncjobs">{{ lang.user.sync_jobs }}</button></li>
|
||||
{% endif %}
|
||||
{% if acl.app_passwds == 1 %}
|
||||
<li class="nav-item" role="presentation"><button class="nav-link" role="tab" aria-selected="false" aria-controls="AppPasswds" role="tab" data-bs-toggle="tab" data-bs-target="#AppPasswds">{{ lang.user.app_passwds }}</button></li>
|
||||
{% endif %}
|
||||
{% if acl.pushover == 1 %}
|
||||
<li class="nav-item" role="presentation"><button class="nav-link" role="tab" aria-selected="false" aria-controls="Pushover" role="tab" data-bs-toggle="tab" data-bs-target="#Pushover">Pushover API</button></li>
|
||||
{% endif %}
|
||||
</ul>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<div class="tab-content" style="padding-top:20px">
|
||||
{% include 'user/tab-user-auth.twig' %}
|
||||
{% include 'user/tab-user-details.twig' %}
|
||||
{% include 'user/tab-user-settings.twig' %}
|
||||
{% if acl.spam_alias == 1 %}{% include 'user/SpamAliases.twig' %}{% endif %}
|
||||
{% if acl.spam_score == 1 %}{% include 'user/Spamfilter.twig' %}{% endif %}
|
||||
{% if acl.syncjobs == 1 %}{% include 'user/Syncjobs.twig' %}{% endif %}
|
||||
{% if acl.app_passwds == 1 %}{% include 'user/AppPasswds.twig' %}{% endif %}
|
||||
{% if acl.pushover == 1 %}{% include 'user/Pushover.twig' %}{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div style="margin-bottom:200px;"></div>
|
||||
{% include 'user_domainadmin_common.twig' %}
|
||||
</div>
|
||||
{% endblock %}
|
||||
54
data/web/templates/user/AppPasswds.twig
Executable file
54
data/web/templates/user/AppPasswds.twig
Executable file
|
|
@ -0,0 +1,54 @@
|
|||
<div class="tab-pane fade" id="AppPasswds" role="tabpanel" aria-labelledby="AppPasswds">
|
||||
<div class="card mb-4">
|
||||
<div class="card-header d-flex fs-5">
|
||||
<button class="btn d-md-none flex-grow-1 text-start" data-bs-target="#collapse-tab-AppPasswds" data-bs-toggle="collapse" aria-controls="collapse-tab-AppPasswds">
|
||||
{{ lang.user.app_passwds }}
|
||||
</button>
|
||||
<span class="d-none d-md-block">{{ lang.user.app_passwds }}</span>
|
||||
</div>
|
||||
<div id="collapse-tab-AppPasswds" class="card-body collapse" data-bs-parent="#user-content">
|
||||
<div class="mass-actions-user mb-4">
|
||||
<div class="btn-group" data-acl="{{ acl.app_passwds }}">
|
||||
<div class="btn-group">
|
||||
<a class="btn btn-sm btn-xs-half d-block d-sm-inline btn-secondary" id="toggle_multi_select_all" data-id="apppasswd" href="#"><i class="bi bi-check-all"></i> {{ lang.mailbox.toggle_all }}</a>
|
||||
<a class="btn btn-sm btn-xs-half d-block d-sm-inline btn-secondary dropdown-toggle" data-bs-toggle="dropdown" href="#">{{ lang.mailbox.quick_actions }}</a>
|
||||
<ul class="dropdown-menu">
|
||||
<li><a class="dropdown-item" data-action="edit_selected" data-id="apppasswd" data-api-url='edit/app-passwd' data-api-attr='{"active":"1"}' href="#">{{ lang.mailbox.activate }}</a></li>
|
||||
<li><a class="dropdown-item" data-action="edit_selected" data-id="apppasswd" data-api-url='edit/app-passwd' data-api-attr='{"active":"0"}' href="#">{{ lang.mailbox.deactivate }}</a></li>
|
||||
<li><hr class="dropdown-divider"></li>
|
||||
<li><a class="dropdown-item" data-datatables-expand="app_passwd_table" data-table="app_passwd_table" href="#">{{ lang.datatables.expand_all }}</a></li>
|
||||
<li><a class="dropdown-item" data-datatables-collapse="app_passwd_table" data-table="app_passwd_table" href="#">{{ lang.datatables.collapse_all }}</a></li>
|
||||
<li><hr class="dropdown-divider"></li>
|
||||
<li><a class="dropdown-item" data-action="delete_selected" data-id="apppasswd" data-api-url='delete/app-passwd' href="#">{{ lang.mailbox.remove }}</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="btn-group">
|
||||
<a class="btn btn-sm d-block d-sm-inline btn-success" href="#" data-bs-toggle="modal" data-bs-target="#addAppPasswdModal"><i class="bi bi-plus-lg"></i> {{ lang.user.create_app_passwd }}</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<p>{{ lang.user.app_hint|raw }}</p>
|
||||
<table id="app_passwd_table" class="table table-striped dt-responsive w-100"></table>
|
||||
<div class="mass-actions-user mt-4">
|
||||
<div class="btn-group" data-acl="{{ acl.app_passwds }}">
|
||||
<div class="btn-group">
|
||||
<a class="btn btn-sm btn-xs-half d-block d-sm-inline btn-secondary" id="toggle_multi_select_all" data-id="apppasswd" href="#"><i class="bi bi-check-all"></i> {{ lang.mailbox.toggle_all }}</a>
|
||||
<a class="btn btn-sm btn-xs-half d-block d-sm-inline btn-secondary dropdown-toggle" data-bs-toggle="dropdown" href="#">{{ lang.mailbox.quick_actions }}</a>
|
||||
<ul class="dropdown-menu">
|
||||
<li><a class="dropdown-item" data-action="edit_selected" data-id="apppasswd" data-api-url='edit/app-passwd' data-api-attr='{"active":"1"}' href="#">{{ lang.mailbox.activate }}</a></li>
|
||||
<li><a class="dropdown-item" data-action="edit_selected" data-id="apppasswd" data-api-url='edit/app-passwd' data-api-attr='{"active":"0"}' href="#">{{ lang.mailbox.deactivate }}</a></li>
|
||||
<li><hr class="dropdown-divider"></li>
|
||||
<li><a class="dropdown-item" data-datatables-expand="app_passwd_table" data-table="app_passwd_table" href="#">{{ lang.datatables.expand_all }}</a></li>
|
||||
<li><a class="dropdown-item" data-datatables-collapse="app_passwd_table" data-table="app_passwd_table" href="#">{{ lang.datatables.collapse_all }}</a></li>
|
||||
<li><hr class="dropdown-divider"></li>
|
||||
<li><a class="dropdown-item" data-action="delete_selected" data-id="apppasswd" data-api-url='delete/app-passwd' href="#">{{ lang.mailbox.remove }}</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="btn-group">
|
||||
<a class="btn btn-sm d-block d-sm-inline btn-success" href="#" data-bs-toggle="modal" data-bs-target="#addAppPasswdModal"><i class="bi bi-plus-lg"></i> {{ lang.user.create_app_passwd }}</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
118
data/web/templates/user/Pushover.twig
Executable file
118
data/web/templates/user/Pushover.twig
Executable file
|
|
@ -0,0 +1,118 @@
|
|||
<div class="tab-pane fade" id="Pushover" role="tabpanel" aria-labelledby="Pushover">
|
||||
<div class="card mb-4">
|
||||
<div class="card-header d-flex fs-5">
|
||||
<button class="btn d-md-none flex-grow-1 text-start" data-bs-target="#collapse-tab-Pushover" data-bs-toggle="collapse" aria-controls="collapse-tab-Pushover">
|
||||
Pushover API
|
||||
</button>
|
||||
<span class="d-none d-md-block">Pushover API</span>
|
||||
</div>
|
||||
<div id="collapse-tab-Pushover" class="card-body collapse" data-bs-parent="#user-content">
|
||||
<form data-id="pushover" class="form well" method="post">
|
||||
<input type="hidden" value="0" name="evaluate_x_prio">
|
||||
<input type="hidden" value="0" name="only_x_prio">
|
||||
<input type="hidden" value="0" name="active">
|
||||
<div class="row">
|
||||
<div class="col-sm-1">
|
||||
<p class="text-muted"><a href="https://pushover.net" target="_blank"><img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAMAAABg3Am1AAACglBMVEUAAAAAAAEAAAAilecFGigAAAAAAAAAAAAAAAANj+c3n+Ypm+oeYI4KWI4MieAtkdQbleoJcLcjmeswmN4Rit4KgdMKUYQJKUAQSnILL0kMNlMSTngimOoNPF0hlOQBBgkNOlkRS3MHIjUhk+IPf8wKLUYsjM0AAAASTngAAAAAAAAPfckbdLIbdrYUWIgegsgce70knfEAAAAknfENOVkGHi8YaaIjnvEdgMUhkuAQSG8aca0hleQUh9YLjOM4nOEMgtMcbaYWa6YemO02ltkKhNktgLodYZEPXJEyi8kKesktfLUzj84cWYMiluckZ5YJXJYeW4Y0k9YKfs4yjs0pc6YHZaUviskLfMkqmugak+cqkNcViNcqeK4Iaq4XRmYGPmYMKDsFJTstgr0LdL0ti84CCQ4BCQ4Qgc8rlt8XjN8shcQsi8wZSGgEP2cRMEUDKkUAAAD///8dmvEamfExo/EXmPEWl/ERlvElnvEsofEjnfETl/Enn/Ezo/E4pvEvovEfm/E1pPEzpPEvofEOlfEpoPEamPEQlfEYmfE6p/EgnPEVlvEroPE3pfE2pfENk/Ern/E3pPEcmfEfmvEnnvBlufT6/P0soPAknPDd7/zs9vzo9PxBqfItofAqoPD9/f3B4/q43/mx2/l/xfZ6w/Vxv/VtvfVgt/RXtPNTsfNEq/L3+/31+v3a7fvR6vvH5fqs2vmc0/jx+P3v9/3h8fzW7PvV7PvL5/q13fmo1/mh1PiY0fiNy/aHyfZ2wfVou/Vdt/RPsPM3oeoQkuowmeAgjdgcgMQbeLrw9/3k8vy74Pm63/mX0PdYtfNNr/Ikm+4wnOchkuAVjOAfdrMVcrOdoJikAAAAcnRSTlMAIQ8IzzweFwf+/fvw8P79+/Xt7e3p6eji4d7U08y8qZyTiIWDgn53bWxqaWBKQ0JBOjUwMCkoJCEfHBkT/vz8/Pv7+vr69/b29PTy7ezm5ubm5N7e29vQ0M/Pv7+4uLW1pqaWloWDg3x7e21mUVFFRUXdPracAAAEbElEQVRIx4WUZbvaQBCFF+ru7u7u7u7u7t4mvVwSoBC0JIUCLRQolLq7u7vr/+nMLkmQyvlwyfPcd86e3ZldUqwyQ/p329J+XfutPQYOLUP+q55rFtQJRvY79+xxlZTUWbKpz7/xrrMr2+3BoNPpdLn2lJQ4HEeqLOr1d7z7XNkesQed4A848G63Oy4Gmg/6Mz542QvZbqe8C/Ig73CLYiYTrtLmT3zfqbIcAR7y4wIqH/B6M9Fo0+Ldb6sM9ph/v4ozPuz12mxRofaAAr7jCNkuoz/jNf9AGHibkBCm51fsGKvxsAGWx4H+jBcEi6V2birDpCL/9Klrd1KHbiSvPWP8V0tTnTfO03iXi57P6WNHOVUf44IFdFDRz6pV5fw8Zy5z3JVH5+R48OwxqDiGvKJIY9R+9JsCuJ5HPg74OVEMpz+nbdEPUHEWeEk6IDUnTC1l5r+f8uffc0cfxc8fS17kLso24SwUPFDA/6DE82xKDOPliJ7n/GGOOyWK9zD9CdjvOfg9Dv6AH+AX04LW9gj2i8W/APx1UbxwCAu+wPmcpgUKL/EHdvtq4uwaZwCuznPJVY5LHhED15G/isd5Hz4eKui/e/du02YoKFeD5mHzHIN/nxEDe25gQQwKorAid04CfyzwL4XutXvl1Pt1guMOwwKPkU8mYIFT8JHK+vv8prpDScUVL+j8s3lOctw1GIhbWHAS+HgKPk7xPM/4UtNAYmzizJkf6NgTb/gM8jePQLsewMdthS3g95tMpT1IhVm6v1s8fYmLeb13Odwp8Fh5KY048y/d14WUrwrb1e/X/rNp73nkD8kWS+wi/MZ4XuetG4mhKubJm3/WNEvi8SHwB56nPKjUam0LBdp9ARwupFemTYudvgN/L1+A/Ko/LGBuS8pPy+YR1fuCTWNKnUyoeUyYx2o2dyEVGmr5xTD42xzvkD16+Pb9WIIH6fmt1r3mbsTY7Bvw+n23naT8BUWh86bz6G/e259UXPUK3gfAxQDlo7Rpx3Geqb2e3wp83SGEdKpB7zvwYbzvT2n65xLwbH6YP+M9C8vA8E1wxLU8gkCbdhXGUyrMgwVrcbzLHonr78lzDvWM3q/C/HtDlXoSUIe3YkblhRPIX4E8Oo/9siLv8dRjV7SBlkdgTXvKS7nzsA/9AfeEuhKq9T8zWIDv1Sd6ETAP4D6/H/1V+1BojvruNa4SZXz4JhY84dV5MOF5agUvu5OsOo+KRpG30KalEnoeDccFlutPZYs38D5n3zcpr1/0fBhfb3DOY1z2tSAgLxWezz6zuoHhfUmOejf6blHQH/sFuJYfcMZX307ytKvRa3ifoV/586P5j+tICtS77BuJxzxYAPZsntX8k3eSIhlajK4p8b7iefCEKs03kD/I2LnxL9ovH+43y4fAv1YrI/mzDBsavAX/UppfzVOrZT/ydxk6lJ047MfLfVbcb6hS9ZEzWxekKQ5WrtPqZg3rV6tWrX6Tle3KQZj/q6KxQnmDoXwFY0VSrN9e8FRXBCTAvwAAAABJRU5ErkJggg==" class="img img-fluid"></a></p>
|
||||
</div>
|
||||
<div class="col-sm-10">
|
||||
<p class="text-muted">{{ lang.user.pushover_info|format(mailcow_cc_username)|raw }}</p>
|
||||
<p class="text-muted">{{ lang.edit.pushover_vars|raw }}: <code>{SUBJECT}</code>, <code>{SENDER}</code>, <code>{SENDER_ADDRESS}</code>, <code>{SENDER_NAME}</code>, <code>{TO_NAME}</code>, <code>{TO_ADDRESS}</code>, <code>{MSG_ID}</code></p>
|
||||
<div class="row">
|
||||
<div class="col-sm-6 mb-2">
|
||||
<div class="form-group">
|
||||
<label for="token">API Token/Key (Application)</label>
|
||||
<input type="text" class="form-control" name="token" maxlength="30" value="{{ pushover_data.token }}" required>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-6 mb-2">
|
||||
<div class="form-group">
|
||||
<label for="key">User/Group Key</label>
|
||||
<input type="text" class="form-control" name="key" maxlength="30" value="{{ pushover_data.key }}" required>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-6 mb-2">
|
||||
<div class="form-group">
|
||||
<label for="title">{{ lang.user.pushover_title }}</label>
|
||||
<input type="text" class="form-control" name="title" value="{{ pushover_data.title }}" placeholder="Mail">
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-6 mb-2">
|
||||
<div class="form-group">
|
||||
<label for="text">{{ lang.user.pushover_text }}</label>
|
||||
<input type="text" class="form-control" name="text" value="{{ pushover_data.text }}" placeholder="You've got mail 📧">
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-12 mb-4">
|
||||
<div class="form-group">
|
||||
<label for="text">{{ lang.user.pushover_sender_array|raw }}</label>
|
||||
<input type="text" class="form-control" name="senders" value="{{ pushover_data.senders }}" placeholder="sender1@example.com, sender2@example.com">
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-12 mb-2">
|
||||
<div class="form-group">
|
||||
<label for="sound">{{ lang.edit.pushover_sound }}</label><br>
|
||||
<select name="sound" class="form-control">
|
||||
<option value="pushover"{% if pushover_data.attributes.sound == 'pushover' %} selected{% endif %}>Pushover (default)</option>
|
||||
<option value="bike"{% if pushover_data.attributes.sound == 'bike' %} selected{% endif %}>Bike</option>
|
||||
<option value="bugle"{% if pushover_data.attributes.sound == 'bugle' %} selected{% endif %}>Bugle</option>
|
||||
<option value="cashregister"{% if pushover_data.attributes.sound == 'cashregister' %} selected{% endif %}>Cash Register</option>
|
||||
<option value="classical"{% if pushover_data.attributes.sound == 'classical' %} selected{% endif %}>Classical</option>
|
||||
<option value="cosmic"{% if pushover_data.attributes.sound == 'cosmic' %} selected{% endif %}>Cosmic</option>
|
||||
<option value="falling"{% if pushover_data.attributes.sound == 'falling' %} selected{% endif %}>Falling</option>
|
||||
<option value="gamelan"{% if pushover_data.attributes.sound == 'gamelan' %} selected{% endif %}>Gamelan</option>
|
||||
<option value="incoming"{% if pushover_data.attributes.sound == 'incoming' %} selected{% endif %}>Incoming</option>
|
||||
<option value="intermission"{% if pushover_data.attributes.sound == 'intermission' %} selected{% endif %}>Intermission</option>
|
||||
<option value="magic"{% if pushover_data.attributes.sound == 'magic' %} selected{% endif %}>Magic</option>
|
||||
<option value="mechanical"{% if pushover_data.attributes.sound == 'mechanical' %} selected{% endif %}>Mechanical</option>
|
||||
<option value="pianobar"{% if pushover_data.attributes.sound == 'pianobar' %} selected{% endif %}>Piano Bar</option>
|
||||
<option value="siren"{% if pushover_data.attributes.sound == 'siren' %} selected{% endif %}>Siren</option>
|
||||
<option value="spacealarm"{% if pushover_data.attributes.sound == 'spacealarm' %} selected{% endif %}>Space Alarm</option>
|
||||
<option value="tugboat"{% if pushover_data.attributes.sound == 'tugboat' %} selected{% endif %}>Tug Boat</option>
|
||||
<option value="alien"{% if pushover_data.attributes.sound == 'alien' %} selected{% endif %}>Alien Alarm (long)</option>
|
||||
<option value="climb"{% if pushover_data.attributes.sound == 'climb' %} selected{% endif %}>Climb (long)</option>
|
||||
<option value="persistent"{% if pushover_data.attributes.sound == 'persistent' %} selected{% endif %}>Persistent (long)</option>
|
||||
<option value="echo"{% if pushover_data.attributes.sound == 'echo' %} selected{% endif %}>Pushover Echo (long)</option>
|
||||
<option value="updown"{% if pushover_data.attributes.sound == 'updown' %} selected{% endif %}>Up Down (long)</option>
|
||||
<option value="vibrate"{% if pushover_data.attributes.sound == 'vibrate' %} selected{% endif %}>Vibrate Only</option>
|
||||
<option value="none"{% if pushover_data.attributes.sound == 'none' %} selected{% endif %}> None (silent) </option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-12">
|
||||
<div class="form-check">
|
||||
<label><input type="checkbox" class="form-check-input" value="1" name="active"{% if pushover_data.active == '1' %} checked{% endif %}> {{ lang.user.active }}</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-12">
|
||||
<legend style="cursor:pointer;margin-top:10px" data-bs-target="#po_advanced" unselectable="on" data-bs-toggle="collapse">
|
||||
<i style="font-size:10pt;" class="bi bi-plus-square"></i> {{ lang.user.advanced_settings }}
|
||||
</legend>
|
||||
<hr />
|
||||
</div>
|
||||
<div class="col-sm-12 mb-4">
|
||||
<div id="po_advanced" class="collapse">
|
||||
<div class="form-group">
|
||||
<label for="text">{{ lang.user.pushover_sender_regex }}</label>
|
||||
<input type="text" class="form-control mb-4" name="senders_regex" value="{{ pushover_data.senders_regex }}" placeholder="/(.*@example\.org$|^foo@example\.com$)/i" regex="true">
|
||||
<div class="form-check">
|
||||
<label><input type="checkbox" class="form-check-input" value="1" name="evaluate_x_prio"{% if pushover_data.attributes.evaluate_x_prio == '1' %} checked{% endif %}> {{ lang.user.pushover_evaluate_x_prio|raw }}</label>
|
||||
</div>
|
||||
<div class="form-check">
|
||||
<label><input type="checkbox" class="form-check-input" value="1" name="only_x_prio"{% if pushover_data.attributes.only_x_prio == '1' %} checked{% endif %}> {{ lang.user.pushover_only_x_prio|raw }}</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="btn-group mass-actions-user mb-2" data-acl="{{ acl.pushover }}">
|
||||
<a class="btn btn-sm btn-xs-half d-block d-sm-inline btn-success" data-action="edit_selected" data-id="pushover" data-item="{{ mailcow_cc_username }}" data-api-url='edit/pushover' data-api-attr='{}' href="#">{{ lang.user.save }}</a>
|
||||
<a class="btn btn-sm btn-xs-half d-block d-sm-inline btn-secondary" data-action="edit_selected" data-id="pushover-test" data-item="{{ mailcow_cc_username }}" data-api-url='edit/pushover-test' data-api-attr='{}' href="#"><i class="bi bi-check-all"></i> {{ lang.user.pushover_verify }}</a>
|
||||
<a id="pushover_delete" class="btn btn-sm d-block d-sm-inline btn-danger" data-action="edit_selected" data-id="pushover-delete" data-item="{{ mailcow_cc_username }}" data-api-url='edit/pushover' data-api-attr='{"delete":"true"}' href="#"><i class="bi bi-trash"></i> {{ lang.user.remove }}</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
47
data/web/templates/user/SpamAliases.twig
Executable file
47
data/web/templates/user/SpamAliases.twig
Executable file
|
|
@ -0,0 +1,47 @@
|
|||
<div class="tab-pane fade" id="SpamAliases" role="tabpanel" aria-labelledby="SpamAliases">
|
||||
<div class="card mb-4">
|
||||
<div class="card-header d-flex fs-5">
|
||||
<button class="btn d-md-none flex-grow-1 text-start" data-bs-target="#collapse-tab-SpamAliases" data-bs-toggle="collapse" aria-controls="collapse-tab-SpamAliases">
|
||||
{{ lang.user.spam_aliases }}
|
||||
</button>
|
||||
<span class="d-none d-md-block">{{ lang.user.spam_aliases }}</span>
|
||||
</div>
|
||||
<div id="collapse-tab-SpamAliases" class="card-body collapse" data-bs-parent="#user-content">
|
||||
<div class="row">
|
||||
<div class="col-md-12 col-sm-12 col-12">
|
||||
<table id="tla_table" class="table table-striped dt-responsive w-100"></table>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mass-actions-user">
|
||||
<div class="btn-group" data-acl="{{ acl.spam_alias }}">
|
||||
<div class="btn-group">
|
||||
<a class="btn btn-sm btn-xs-half d-block d-sm-inline btn-secondary" id="toggle_multi_select_all" data-id="tla" href="#"><i class="bi bi-check-all"></i> {{ lang.mailbox.toggle_all }}</a>
|
||||
<a class="btn btn-sm btn-xs-half d-block d-sm-inline btn-secondary dropdown-toggle" data-bs-toggle="dropdown" href="#">{{ lang.mailbox.quick_actions }}</a>
|
||||
<ul class="dropdown-menu">
|
||||
<li><a class="dropdown-item" data-action="edit_selected" data-id="tla" data-api-url='edit/time_limited_alias' data-api-attr='{"validity":"1"}' href="#">{{ lang.user.expire_in }} 1 {{ lang.user.hour }}</a></li>
|
||||
<li><a class="dropdown-item" data-action="edit_selected" data-id="tla" data-api-url='edit/time_limited_alias' data-api-attr='{"validity":"24"}' href="#">{{ lang.user.expire_in }} 1 {{ lang.user.day }}</a></li>
|
||||
<li><a class="dropdown-item" data-action="edit_selected" data-id="tla" data-api-url='edit/time_limited_alias' data-api-attr='{"validity":"168"}' href="#">{{ lang.user.expire_in }} 1 {{ lang.user.week }}</a></li>
|
||||
<li><a class="dropdown-item" data-action="edit_selected" data-id="tla" data-api-url='edit/time_limited_alias' data-api-attr='{"validity":"744"}' href="#">{{ lang.user.expire_in }} 1 {{ lang.user.month }}</a></li>
|
||||
<li><a class="dropdown-item" data-action="edit_selected" data-id="tla" data-api-url='edit/time_limited_alias' data-api-attr='{"validity":"8760"}' href="#">{{ lang.user.expire_in }} 1 {{ lang.user.year }}</a></li>
|
||||
<li><a class="dropdown-item" data-action="edit_selected" data-id="tla" data-api-url='edit/time_limited_alias' data-api-attr='{"validity":"87600"}' href="#">{{ lang.user.expire_in }} 10 {{ lang.user.years }}</a></li>
|
||||
<li><hr class="dropdown-divider"></li>
|
||||
<li><a class="dropdown-item" data-action="delete_selected" data-id="tla" data-api-url='delete/time_limited_alias' href="#">{{ lang.mailbox.remove }}</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="btn-group">
|
||||
<a class="btn btn-sm d-block d-sm-inline btn-success dropdown-toggle" data-bs-toggle="dropdown" href="#"><i class="bi bi-plus-lg"></i> {{ lang.user.alias_create_random }}, 1 {{ lang.user.year }}</a>
|
||||
<ul class="dropdown-menu">
|
||||
{% for domain in user_domains %}
|
||||
<li>
|
||||
<a class="dropdown-item" data-action="add_item" data-api-url='add/time_limited_alias' data-api-attr='{"domain":"{{ domain }}"}' href="#">
|
||||
@ {{ domain }}
|
||||
</a>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
89
data/web/templates/user/Spamfilter.twig
Executable file
89
data/web/templates/user/Spamfilter.twig
Executable file
|
|
@ -0,0 +1,89 @@
|
|||
<div class="tab-pane fade" id="Spamfilter" role="tabpanel" aria-labelledby="Spamfilter">
|
||||
<div class="card mb-4">
|
||||
<div class="card-header d-flex fs-5">
|
||||
<button class="btn d-md-none flex-grow-1 text-start" data-bs-target="#collapse-tab-Spamfilter" data-bs-toggle="collapse" aria-controls="collapse-tab-Spamfilter">
|
||||
{{ lang.user.spamfilter }}
|
||||
</button>
|
||||
<span class="d-none d-md-block">{{ lang.user.spamfilter }}</span>
|
||||
</div>
|
||||
<div id="collapse-tab-Spamfilter" class="card-body collapse" data-bs-parent="#user-content">
|
||||
<h4>{{ lang.user.spamfilter_behavior }}</h4>
|
||||
<div class="row">
|
||||
<div class="col-sm-12">
|
||||
<form class="form-horizontal" role="form" data-id="spam_score" method="post">
|
||||
<div class="row">
|
||||
<div class="col-sm-12">
|
||||
<div id="spam_score" data-provide="slider" data-acl="{{ acl.spam_score }}"></div>
|
||||
<input id="spam_score_value" name="spam_score" type="hidden" value="{{ user_spam_score }}">
|
||||
<ul class="list-group list-group-flush">
|
||||
<li class="list-group-item"><span class="label label-ham spam-ham-score"></span> {{ lang.user.spamfilter_green }}</li>
|
||||
<li class="list-group-item"><span class="label label-spam spam-spam-score"></span> {{ lang.user.spamfilter_yellow }}</li>
|
||||
<li class="list-group-item"><span class="label label-reject spam-reject-score"></span> {{ lang.user.spamfilter_red }}</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div class="btn-group mt-4" data-acl="{{ acl.spam_score }}">
|
||||
<a type="button" class="btn btn-sm btn-xs-half d-block d-sm-inline btn-success" data-action="edit_selected"
|
||||
data-item="{{ mailcow_cc_username }}"
|
||||
data-id="spam_score"
|
||||
data-api-url='edit/spam-score'
|
||||
data-api-attr='{}'><i class="bi bi-save"></i> {{ lang.user.save_changes }}</a>
|
||||
<a type="button" class="btn btn-sm btn-xs-half d-block d-sm-inline btn-secondary" data-action="edit_selected"
|
||||
data-item="{{ mailcow_cc_username }}"
|
||||
data-id="spam_score_reset"
|
||||
data-api-url='edit/spam-score'
|
||||
data-api-attr='{"spam_score":"default"}'>{{ lang.user.spam_score_reset }}</a>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<hr>
|
||||
<div class="row">
|
||||
<div class="col-lg-6 my-3">
|
||||
<h4>{{ lang.user.spamfilter_wl }}</h4>
|
||||
<p>{{ lang.user.spamfilter_wl_desc|raw }}</p>
|
||||
<form class="form-inline mb-4" data-id="add_wl_policy_mailbox">
|
||||
<div class="input-group" data-acl="{{ acl.spam_policy }}">
|
||||
<input type="text" class="form-control" name="object_from" placeholder="*@example.org" required>
|
||||
<button class="btn btn-secondary" data-action="add_item" data-id="add_wl_policy_mailbox" data-api-url='add/mailbox-policy' data-api-attr='{"username": {{ mailcow_cc_username|json_encode|raw }},"object_list":"wl"}' href="#"><i class="bi bi-plus-lg"></i> {{ lang.user.spamfilter_table_add }}</button>
|
||||
</div>
|
||||
</form>
|
||||
<table id="wl_policy_mailbox_table" class="table table-striped dt-responsive w-100"></table>
|
||||
<div class="mass-actions-user">
|
||||
<div class="btn-group" data-acl="{{ acl.spam_policy }}">
|
||||
<a class="btn btn-sm btn-xs-half d-block d-sm-inline btn-secondary" id="toggle_multi_select_all" data-id="policy_wl_mailbox" href="#"><i class="bi bi-check-all"></i> {{ lang.mailbox.toggle_all }}</a>
|
||||
<a class="btn btn-sm btn-xs-half d-block d-sm-inline btn-secondary dropdown-toggle" data-bs-toggle="dropdown" href="#">{{ lang.mailbox.quick_actions }}</a>
|
||||
<ul class="dropdown-menu">
|
||||
<li><a class="dropdown-item" data-datatables-expand="wl_policy_mailbox_table" data-table="wl_policy_mailbox_table" href="#">{{ lang.datatables.expand_all }}</a></li>
|
||||
<li><a class="dropdown-item" data-datatables-collapse="wl_policy_mailbox_table" data-table="wl_policy_mailbox_table" href="#">{{ lang.datatables.collapse_all }}</a></li>
|
||||
</ul>
|
||||
<a class="btn btn-sm btn-xs-half d-block d-sm-inline btn-danger" data-action="delete_selected" data-id="policy_wl_mailbox" data-api-url='delete/mailbox-policy' href="#">{{ lang.mailbox.remove }}</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-lg-6 my-3">
|
||||
<h4>{{ lang.user.spamfilter_bl }}</h4>
|
||||
<p>{{ lang.user.spamfilter_bl_desc|raw }}</p>
|
||||
<form class="form-inline mb-4" data-id="add_bl_policy_mailbox">
|
||||
<div class="input-group" data-acl="{{ acl.spam_policy }}">
|
||||
<input type="text" class="form-control" name="object_from" placeholder="*@example.org" required>
|
||||
<button class="btn btn-secondary" data-action="add_item" data-id="add_bl_policy_mailbox" data-api-url='add/mailbox-policy' data-api-attr='{"username": {{ mailcow_cc_username|json_encode|raw }},"object_list":"bl"}' href="#"><i class="bi bi-plus-lg"></i> {{ lang.user.spamfilter_table_add }}</button>
|
||||
</div>
|
||||
</form>
|
||||
<table id="bl_policy_mailbox_table" class="table table-striped dt-responsive w-100"></table>
|
||||
<div class="mass-actions-user">
|
||||
<div class="btn-group" data-acl="{{ acl.spam_policy }}">
|
||||
<a class="btn btn-sm btn-xs-half d-block d-sm-inline btn-secondary" id="toggle_multi_select_all" data-id="policy_bl_mailbox" href="#"><i class="bi bi-check-all"></i> {{ lang.mailbox.toggle_all }}</a>
|
||||
<a class="btn btn-sm btn-xs-half d-block d-sm-inline btn-secondary dropdown-toggle" data-bs-toggle="dropdown" href="#">{{ lang.mailbox.quick_actions }}</a>
|
||||
<ul class="dropdown-menu">
|
||||
<li><a class="dropdown-item" data-datatables-expand="bl_policy_mailbox_table" data-table="bl_policy_mailbox_table" href="#">{{ lang.datatables.expand_all }}</a></li>
|
||||
<li><a class="dropdown-item" data-datatables-collapse="bl_policy_mailbox_table" data-table="bl_policy_mailbox_table" href="#">{{ lang.datatables.collapse_all }}</a></li>
|
||||
</ul>
|
||||
<a class="btn btn-sm btn-xs-half d-block d-sm-inline btn-danger" data-action="delete_selected" data-id="policy_bl_mailbox" data-api-url='delete/mailbox-policy' href="#">{{ lang.mailbox.remove }}</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
53
data/web/templates/user/Syncjobs.twig
Executable file
53
data/web/templates/user/Syncjobs.twig
Executable file
|
|
@ -0,0 +1,53 @@
|
|||
<div class="tab-pane fade" id="Syncjobs" role="tabpanel" aria-labelledby="Syncjobs">
|
||||
<div class="card mb-4">
|
||||
<div class="card-header d-flex fs-5">
|
||||
<button class="btn d-md-none flex-grow-1 text-start" data-bs-target="#collapse-tab-Syncjobs" data-bs-toggle="collapse" aria-controls="collapse-tab-Syncjobs">
|
||||
{{ lang.user.sync_jobs }}
|
||||
</button>
|
||||
<span class="d-none d-md-block">{{ lang.user.sync_jobs }}</span>
|
||||
</div>
|
||||
<div id="collapse-tab-Syncjobs" class="card-body collapse" data-bs-parent="#user-content">
|
||||
<div class="mass-actions-user mb-4">
|
||||
<div class="btn-group" data-acl="{{ acl.syncjobs }}">
|
||||
<div class="btn-group">
|
||||
<a class="btn btn-sm btn-xs-half d-block d-sm-inline btn-secondary" id="toggle_multi_select_all" data-id="syncjob" href="#"><i class="bi bi-check-all"></i> {{ lang.mailbox.toggle_all }}</a>
|
||||
<a class="btn btn-sm btn-xs-half d-block d-sm-inline btn-secondary dropdown-toggle" data-bs-toggle="dropdown" href="#">{{ lang.mailbox.quick_actions }}</a>
|
||||
<ul class="dropdown-menu">
|
||||
<li><a class="dropdown-item" data-action="edit_selected" data-id="syncjob" data-api-url='edit/syncjob' data-api-attr='{"active":"1"}' href="#">{{ lang.mailbox.activate }}</a></li>
|
||||
<li><a class="dropdown-item" data-action="edit_selected" data-id="syncjob" data-api-url='edit/syncjob' data-api-attr='{"active":"0"}' href="#">{{ lang.mailbox.deactivate }}</a></li>
|
||||
<li><hr class="dropdown-divider"></li>
|
||||
<li><a class="dropdown-item" data-datatables-expand="sync_job_table" data-table="sync_job_table" href="#">{{ lang.datatables.expand_all }}</a></li>
|
||||
<li><a class="dropdown-item" data-datatables-collapse="sync_job_table" data-table="sync_job_table" href="#">{{ lang.datatables.collapse_all }}</a></li>
|
||||
<li><hr class="dropdown-divider"></li>
|
||||
<li><a class="dropdown-item" data-action="delete_selected" data-id="syncjob" data-api-url='delete/syncjob' href="#">{{ lang.mailbox.remove }}</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="btn-group">
|
||||
<a class="btn btn-sm d-block d-sm-inline btn-success" href="#" data-bs-toggle="modal" data-bs-target="#addSyncJobModal"><i class="bi bi-plus-lg"></i> {{ lang.user.create_syncjob }}</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<table id="sync_job_table" class="table table-striped dt-responsive w-100"></table>
|
||||
<div class="mass-actions-user mt-4">
|
||||
<div class="btn-group" data-acl="{{ acl.syncjobs }}">
|
||||
<div class="btn-group">
|
||||
<a class="btn btn-sm btn-xs-half d-block d-sm-inline btn-secondary" id="toggle_multi_select_all" data-id="syncjob" href="#"><i class="bi bi-check-all"></i> {{ lang.mailbox.toggle_all }}</a>
|
||||
<a class="btn btn-sm btn-xs-half d-block d-sm-inline btn-secondary dropdown-toggle" data-bs-toggle="dropdown" href="#">{{ lang.mailbox.quick_actions }}</a>
|
||||
<ul class="dropdown-menu">
|
||||
<li><a class="dropdown-item" data-action="edit_selected" data-id="syncjob" data-api-url='edit/syncjob' data-api-attr='{"active":"1"}' href="#">{{ lang.mailbox.activate }}</a></li>
|
||||
<li><a class="dropdown-item" data-action="edit_selected" data-id="syncjob" data-api-url='edit/syncjob' data-api-attr='{"active":"0"}' href="#">{{ lang.mailbox.deactivate }}</a></li>
|
||||
<li><hr class="dropdown-divider"></li>
|
||||
<li><a class="dropdown-item" data-datatables-expand="sync_job_table" data-table="sync_job_table" href="#">{{ lang.datatables.expand_all }}</a></li>
|
||||
<li><a class="dropdown-item" data-datatables-collapse="sync_job_table" data-table="sync_job_table" href="#">{{ lang.datatables.collapse_all }}</a></li>
|
||||
<li><hr class="dropdown-divider"></li>
|
||||
<li><a class="dropdown-item" data-action="delete_selected" data-id="syncjob" data-api-url='delete/syncjob' href="#">{{ lang.mailbox.remove }}</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="btn-group">
|
||||
<a class="btn btn-sm d-block d-sm-inline btn-success" href="#" data-bs-toggle="modal" data-bs-target="#addSyncJobModal"><i class="bi bi-plus-lg"></i> {{ lang.user.create_syncjob }}</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
167
data/web/templates/user/tab-user-auth.twig
Executable file
167
data/web/templates/user/tab-user-auth.twig
Executable file
|
|
@ -0,0 +1,167 @@
|
|||
<div class="tab-pane fade in active show" id="tab-user-auth" role="tabpanel" aria-labelledby="tab-user-auth">
|
||||
<div class="card mb-4">
|
||||
<div class="card-header d-flex fs-5">
|
||||
<button class="btn d-md-none flex-grow-1 text-start" data-bs-target="#collapse-tab-user-auth" data-bs-toggle="collapse" aria-controls="collapse-tab-user-auth">
|
||||
{{ lang.user.mailbox_general }}
|
||||
</button>
|
||||
<span class="d-none d-md-block">{{ lang.user.mailbox_general }}</span>
|
||||
</div>
|
||||
<div id="collapse-tab-user-auth" class="card-body collapse" data-bs-parent="#user-content">
|
||||
{% if mailboxdata.attributes.force_pw_update == '1' %}
|
||||
<div class="alert alert-danger">{{ lang.user.force_pw_update|raw }}</div>
|
||||
{% endif %}
|
||||
{% if not skip_sogo %}
|
||||
<div class="row">
|
||||
<div class="hidden-xs col-md-3 col-xs-5 text-right"></div>
|
||||
<div class="col-md-3 col-xs-12">
|
||||
{% if dual_login and allow_admin_email_login == 'n' or mailboxdata.attributes.force_pw_update == '1' %}
|
||||
<button disabled class="btn btn-secondary btn-block btn-xs-lg">
|
||||
<i class="bi bi-inbox-fill"></i> {{ lang.user.open_webmail_sso }}
|
||||
</button>
|
||||
{% else %}
|
||||
<a target="_blank" href="/sogo-auth.php?login={{ mailcow_cc_username }}" role="button" class="btn btn-secondary btn-block btn-xs-lg">
|
||||
<i class="bi bi-inbox-fill"></i> {{ lang.user.open_webmail_sso }}
|
||||
</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
<hr>
|
||||
<div class="row">
|
||||
<div class="d-none d-sm-flex col-md-3 col-5 text-end"></div>
|
||||
<div class="col-md-9 col-12">
|
||||
<p class="text-muted text-muted-mt-0">{{ lang.user.direct_protocol_access|raw }}</p>
|
||||
{% if mailboxdata.attributes.imap_access == 1 %}<div class="badge fs-6 bg-success mb-2">IMAP <i class="bi bi-check-lg"></i></div>{% else %}<div class="badge fs-6 bg-danger">IMAP <i class="bi bi-x-lg"></i></div>{% endif %}
|
||||
{% if mailboxdata.attributes.smtp_access == 1 %}<div class="badge fs-6 bg-success mb-2">SMTP <i class="bi bi-check-lg"></i></div>{% else %}<div class="badge fs-6 bg-danger">SMTP <i class="bi bi-x-lg"></i></div>{% endif %}
|
||||
{% if mailboxdata.attributes.sieve_access == 1 %}<div class="badge fs-6 bg-success mb-2">Sieve <i class="bi bi-check-lg"></i></div>{% else %}<div class="badge fs-6 bg-danger">Sieve <i class="bi bi-x-lg"></i></div>{% endif %}
|
||||
{% if mailboxdata.attributes.pop3_access == 1 %}<div class="badge fs-6 bg-success mb-2">POP3 <i class="bi bi-check-lg"></i></div>{% else %}<div class="badge fs-6 bg-danger">POP3 <i class="bi bi-x-lg"></i></div>{% endif %}
|
||||
{% if mailboxdata.attributes.sogo_access == 1 %}<div class="badge fs-6 bg-success mb-2">SOGo <i class="bi bi-check-lg"></i></div>{% else %}<div class="badge fs-6 bg-danger">SOGo <i class="bi bi-x-lg"></i></div>{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
<hr>
|
||||
{% endif %}
|
||||
<div class="row">
|
||||
<div class="col-md-3 col-12 text-sm-end text-start mb-4">{{ lang.user.in_use }}:</div>
|
||||
<div class="col-md-5 col-12">
|
||||
<div class="progress">
|
||||
<div class="progress-bar bg-{{ mailboxdata.percent_class }}" role="progressbar" aria-valuenow="{{ mailboxdata.percent_in_use }}" aria-valuemin="0" aria-valuemax="100" style="min-width:2em;width: {{ mailboxdata.percent_in_use }}%;">
|
||||
{{ mailboxdata.percent_in_use }}%
|
||||
</div>
|
||||
</div>
|
||||
<p>{{ mailboxdata.quota_used|formatBytes(2) }} / {% if mailboxdata.quota == 0 %}∞{% else %}{{ mailboxdata.quota|formatBytes(2) }}{% endif %}<br>{{ mailboxdata.messages }} {{ lang.user.messages }}</p>
|
||||
<hr>
|
||||
<p><a href="#pwChangeModal" data-bs-toggle="modal"><i class="bi bi-pencil-fill"></i> {{ lang.user.change_password }}</a></p>
|
||||
{% if acl.pw_reset == 1 %}<p><a href="#pwRecoveryEmailModal" data-bs-toggle="modal"><i class="bi bi-pencil-fill"></i> {{ lang.user.pw_recovery_email }}</a></p>{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
<hr>
|
||||
{# TFA #}
|
||||
<div class="row">
|
||||
<div class="col-sm-3 col-xs-5 text-right">{{ lang.tfa.tfa }}:</div>
|
||||
<div class="col-sm-9 col-xs-7">
|
||||
<p id="tfa_pretty">{{ tfa_data.pretty }}</p>
|
||||
{% include 'tfa_keys.twig' %}
|
||||
<br>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-sm-3 col-xs-5 text-right">{{ lang.tfa.set_tfa }}:</div>
|
||||
<div class="col-sm-9 col-xs-7">
|
||||
<select data-style="btn btn-sm dropdown-toggle bs-placeholder btn-secondary" data-width="fit" id="selectTFA" class="selectpicker" title="{{ lang.tfa.select }}">
|
||||
<option value="yubi_otp">{{ lang.tfa.yubi_otp }}</option>
|
||||
<option value="webauthn">{{ lang.tfa.webauthn }}</option>
|
||||
<option value="totp">{{ lang.tfa.totp }}</option>
|
||||
<option value="none">{{ lang.tfa.none }}</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<hr>
|
||||
{# FIDO2 #}
|
||||
<div class="row">
|
||||
<div class="col-sm-3 col-12 text-sm-end text-start">
|
||||
<p><i class="bi bi-shield-fill-check"></i> {{ lang.fido2.fido2_auth }}</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-sm-3 col-12 text-sm-end text-start mb-4">
|
||||
{{ lang.fido2.known_ids }}:
|
||||
</div>
|
||||
<div class="col-sm-9 col-12">
|
||||
<div class="table-responsive">
|
||||
<table class="table table-striped table-hover table-condensed" id="fido2_keys">
|
||||
<tr>
|
||||
<th>ID</th>
|
||||
<th style="min-width:240px;text-align: right">{{ lang.admin.action }}</th>
|
||||
</tr>
|
||||
{% include 'fido2.twig' %}
|
||||
</table>
|
||||
</div>
|
||||
<br>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="offset-sm-3 col-sm-9">
|
||||
<div class="btn-group nowrap">
|
||||
<button class="btn btn-sm btn-primary d-block d-sm-inline" id="register-fido2">{{ lang.fido2.set_fido2 }}</button>
|
||||
<button type="button" class="btn btn-sm btn-xs-lg btn-primary dropdown-toggle" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false"></button>
|
||||
<ul class="dropdown-menu">
|
||||
<li><a class="dropdown-item" href="#" id="register-fido2-touchid"><i class="bi bi-apple"></i> {{ lang.fido2.set_fido2_touchid }}</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<br>
|
||||
<div class="row" id="status-fido2">
|
||||
<div class="col-sm-3 col-5 text-end">{{ lang.fido2.register_status }}:</div>
|
||||
<div class="col-sm-9 col-7">
|
||||
<div id="fido2-alerts">-</div>
|
||||
</div>
|
||||
<br>
|
||||
</div>
|
||||
<hr>
|
||||
<div class="row">
|
||||
<div class="col-md-3 col-12 text-sm-end text-start mb-4"><i class="bi bi-file-earmark-text"></i> {{ lang.user.apple_connection_profile }}:</div>
|
||||
<div class="col-md-9 col-12">
|
||||
<p><i class="bi bi-file-earmark-post"></i> <a href="/mobileconfig.php?only_email">{{ lang.user.email }}</a> <small>IMAP, SMTP</small></p>
|
||||
<p class="text-muted">{{ lang.user.apple_connection_profile_mailonly }}</p>
|
||||
{% if not skip_sogo %}
|
||||
<p><i class="bi bi-file-earmark-post"></i> <a href="/mobileconfig.php">{{ lang.user.email_and_dav }}</a> <small>IMAP, SMTP, Cal/CardDAV</small></p>
|
||||
<p class="text-muted">{{ lang.user.apple_connection_profile_complete }}</p>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-3 col-12 text-sm-end text-start mb-4"><i class="bi bi-file-earmark-text"></i> {{ lang.user.apple_connection_profile }}<br class="d-none d-lg-block" />{{ lang.user.with_app_password }}:</div>
|
||||
<div class="col-md-9 col-12">
|
||||
<p><i class="bi bi-file-earmark-post"></i> <a href="/mobileconfig.php?only_email&app_password">{{ lang.user.email }}</a> <small>IMAP, SMTP</small></p>
|
||||
<p class="text-muted">{{ lang.user.apple_connection_profile_mailonly }}<br /> {{ lang.user.apple_connection_profile_with_app_password }}</p>
|
||||
{% if not skip_sogo %}
|
||||
<p><i class="bi bi-file-earmark-post"></i> <a href="/mobileconfig.php?app_password">{{ lang.user.email_and_dav }}</a> <small>IMAP, SMTP, Cal/CardDAV</small></p>
|
||||
<p class="text-muted">{{ lang.user.apple_connection_profile_complete }}<br /> {{ lang.user.apple_connection_profile_with_app_password }}</p>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
<hr>
|
||||
<div class="row">
|
||||
<div class="offset-sm-3 col-sm-9">
|
||||
<p><a target="_blank" href="https://docs.mailcow.email/client/client/#{{ clientconfigstr }}">[{{ lang.user.client_configuration }}]</a></p>
|
||||
<p><a href="#userFilterModal" data-bs-toggle="modal">[{{ lang.user.show_sieve_filters }}]</a></p>
|
||||
<hr>
|
||||
<h4 class="recent-login-success">{{ lang.user.recent_successful_connections }}</h4>
|
||||
<div class="dropdown mt-2">
|
||||
<button class="btn btn-secondary btn-xs btn-xs-lg dropdown-toggle" type="button" id="history_sasl_days" data-bs-toggle="dropdown">{{ lang.user.login_history }}</button>
|
||||
<ul class="dropdown-menu">
|
||||
<li class="login-history" data-days="1"><a class="dropdown-item" href="#">1 {{ lang.user.day }}</a></li>
|
||||
<li class="login-history" data-days="7"><a class="dropdown-item active" href="#">1 {{ lang.user.week }}</a></li>
|
||||
<li class="login-history" data-days="14"><a class="dropdown-item" href="#">2 {{ lang.user.weeks }}</a></li>
|
||||
<li class="login-history" data-days="31"><a class="dropdown-item" href="#">1 {{ lang.user.month }}</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="last-login mt-4" id="recent-logins"></div>
|
||||
<span class="clear-last-logins mt-2">
|
||||
{{ lang.user.clear_recent_successful_connections }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
72
data/web/templates/user/tab-user-details.twig
Executable file
72
data/web/templates/user/tab-user-details.twig
Executable file
|
|
@ -0,0 +1,72 @@
|
|||
<div class="tab-pane fade" id="tab-user-details" role="tabpanel" aria-labelledby="tab-user-details">
|
||||
<div class="card mb-4">
|
||||
<div class="card-header d-flex fs-5">
|
||||
<button class="btn d-md-none flex-grow-1 text-start" data-bs-target="#collapse-tab-user-details" data-bs-toggle="collapse" aria-controls="collapse-tab-user-details">
|
||||
{{ lang.user.mailbox_details }}
|
||||
</button>
|
||||
<span class="d-none d-md-block">{{ lang.user.mailbox_details }}</span>
|
||||
</div>
|
||||
<div id="collapse-tab-user-details" class="card-body collapse" data-bs-parent="#user-content">
|
||||
<div class="row">
|
||||
<div class="col-sm-4 col-md-3 col-12 text-sm-end text-start"><i class="bi bi-pin-angle"></i> {{ lang.user.direct_aliases }}:
|
||||
<p class="small">{{ lang.user.direct_aliases_desc }}</p>
|
||||
</div>
|
||||
<div class="col-sm-8 col-md-9 col-12">
|
||||
{% for direct_alias, direct_alias_meta in user_get_alias_details.direct_aliases %}
|
||||
{% if direct_alias_meta.public_comment %}
|
||||
{{ direct_alias }} — <i class="bi bi-chat-left"></i> {{ direct_alias_meta.public_comment }}<br>
|
||||
{% else %}
|
||||
{{ direct_alias }}<br>
|
||||
{% endif %}
|
||||
{% else %}
|
||||
<i class="bi bi-x-lg"></i>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
<br>
|
||||
<div class="row">
|
||||
<div class="col-sm-4 col-md-3 col-12 text-sm-end text-start"><i class="bi bi-share"></i> {{ lang.user.shared_aliases }}:
|
||||
<p class="small">{{ lang.user.shared_aliases_desc }}</p>
|
||||
</div>
|
||||
<div class="col-sm-8 col-md-9 col-12">
|
||||
{% for shared_alias, shared_alias_meta in user_get_alias_details.shared_aliases %}
|
||||
{% if shared_alias_meta.public_comment %}
|
||||
{{ shared_alias }} — <i class="bi bi-chat-left"></i> {{ shared_alias_meta.public_comment }}<br>
|
||||
{% else %}
|
||||
{{ shared_alias }}<br>
|
||||
{% endif %}
|
||||
{% else %}
|
||||
<i class="bi bi-x-lg"></i>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
<hr>
|
||||
<div class="row">
|
||||
<div class="col-sm-4 col-md-3 col-12 text-sm-end text-start mb-4">{{ lang.user.aliases_also_send_as }}:</div>
|
||||
<div class="col-sm-8 col-md-9 col-12">
|
||||
<p>
|
||||
{% if user_get_alias_details.aliases_also_send_as == '*' %}
|
||||
{{ lang.user.sender_acl_disabled | raw }}
|
||||
{% elseif user_get_alias_details.aliases_also_send_as %}
|
||||
{{ user_get_alias_details.aliases_also_send_as }}
|
||||
{% else %}
|
||||
<i class="bi bi-x-lg"></i>
|
||||
{% endif %}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-sm-4 col-md-3 col-12 text-sm-end text-start mb-4">{{ lang.user.aliases_send_as_all }}:</div>
|
||||
<div class="col-sm-8 col-md-9 col-12">
|
||||
<p>{% if not user_get_alias_details.aliases_send_as_all %}<i class="bi bi-x-lg"></i>{% else %}{{ user_get_alias_details.aliases_send_as_all }}{% endif %}</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-sm-4 col-md-3 col-12 text-sm-end text-start mb-4">{{ lang.user.is_catch_all }}:</div>
|
||||
<div class="col-sm-8 col-md-9 col-12">
|
||||
<p>{% if not user_get_alias_details.is_catch_all %}<i class="bi bi-x-lg"></i>{% else %}{{ user_get_alias_details.is_catch_all }}{% endif %}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
137
data/web/templates/user/tab-user-settings.twig
Executable file
137
data/web/templates/user/tab-user-settings.twig
Executable file
|
|
@ -0,0 +1,137 @@
|
|||
<div class="tab-pane fade" id="tab-user-settings" role="tabpanel" aria-labelledby="tab-user-settings">
|
||||
<div class="card mb-4">
|
||||
<div class="card-header d-flex fs-5">
|
||||
<button class="btn d-md-none flex-grow-1 text-start" data-bs-target="#collapse-tab-user-settings" data-bs-toggle="collapse" aria-controls="collapse-tab-user-settings">
|
||||
{{ lang.user.mailbox_settings }}
|
||||
</button>
|
||||
<span class="d-none d-md-block">{{ lang.user.mailbox_settings }}</span>
|
||||
</div>
|
||||
<div id="collapse-tab-user-settings" class="card-body collapse" data-bs-parent="#user-content">
|
||||
{# Show tagging options #}
|
||||
<div class="row">
|
||||
<div class="col-sm-3 col-12 text-sm-end text-start text-xs-bold mb-4">{{ lang.user.tag_handling }}:</div>
|
||||
<div class="col-sm-9 col-12">
|
||||
<div class="btn-group" data-acl="{{ acl.delimiter_action }}">
|
||||
<button type="button" class="btn btn-sm btn-xs-third d-block d-sm-inline{% if get_tagging_options == 'subfolder' %} btn-dark{% else %} btn-light{% endif %}"
|
||||
data-action="edit_selected"
|
||||
data-item="{{ mailcow_cc_username }}"
|
||||
data-id="delimiter_action"
|
||||
data-api-url='edit/delimiter_action'
|
||||
data-api-attr='{"tagged_mail_handler":"subfolder"}'>{{ lang.user.tag_in_subfolder }}</button>
|
||||
<button type="button" class="btn btn-sm btn-xs-third d-block d-sm-inline{% if get_tagging_options == 'subject' %} btn-dark{% else %} btn-light{% endif %}"
|
||||
data-action="edit_selected"
|
||||
data-item="{{ mailcow_cc_username }}"
|
||||
data-id="delimiter_action"
|
||||
data-api-url='edit/delimiter_action'
|
||||
data-api-attr='{"tagged_mail_handler":"subject"}'>{{ lang.user.tag_in_subject }}</button>
|
||||
<button type="button" class="btn btn-sm btn-xs-third d-block d-sm-inline{% if get_tagging_options == 'none' %} btn-dark{% else %} btn-light{% endif %}"
|
||||
data-action="edit_selected"
|
||||
data-item="{{ mailcow_cc_username }}"
|
||||
data-id="delimiter_action"
|
||||
data-api-url='edit/delimiter_action'
|
||||
data-api-attr='{"tagged_mail_handler":"none"}'>{{ lang.user.tag_in_none }}</button>
|
||||
</div>
|
||||
<p class="text-muted">{{ lang.user.tag_help_explain|raw }}</p>
|
||||
<p class="text-muted">{{ lang.user.tag_help_example|raw }}</p>
|
||||
</div>
|
||||
</div>
|
||||
{# Show TLS policy options #}
|
||||
<div class="row">
|
||||
<div class="col-sm-3 col-12 text-sm-end text-start text-xs-bold mb-4">{{ lang.user.tls_policy }}:</div>
|
||||
<div class="col-sm-9 col-12">
|
||||
<div class="btn-group" data-acl="{{ acl.tls_policy }}">
|
||||
<button type="button" class="btn btn-sm btn-xs-half d-block d-sm-inline{% if get_tls_policy.tls_enforce_in == '1' %} btn-dark"{% else %} btn-light{% endif %}"
|
||||
data-action="edit_selected"
|
||||
data-item="{{ mailcow_cc_username }}"
|
||||
data-id="tls_policy"
|
||||
data-api-url='edit/tls_policy'
|
||||
data-api-attr='{"tls_enforce_in": {% if get_tls_policy.tls_enforce_in == '1' %}0{% else %}1{% endif %} }'>{{ lang.user.tls_enforce_in }}</button>
|
||||
<button type="button" class="btn btn-sm btn-xs-half d-block d-sm-inline{% if get_tls_policy.tls_enforce_out == '1' %} btn-dark{% else %} btn-light{% endif %}"
|
||||
data-action="edit_selected"
|
||||
data-item="{{ mailcow_cc_username }}"
|
||||
data-id="tls_policy"
|
||||
data-api-url='edit/tls_policy'
|
||||
data-api-attr='{"tls_enforce_out": {% if get_tls_policy.tls_enforce_out == '1' %}0{% else %}1{% endif %} }'>{{ lang.user.tls_enforce_out }}</button>
|
||||
</div>
|
||||
<p class="text-muted">{{ lang.user.tls_policy_warning|raw }}</p>
|
||||
</div>
|
||||
</div>
|
||||
{# Show quarantine_notification options #}
|
||||
<div class="row">
|
||||
<div class="col-sm-3 col-12 text-sm-end text-start text-xs-bold mb-4">{{ lang.user.quarantine_notification }}:</div>
|
||||
<div class="col-sm-9 col-12">
|
||||
<div class="btn-group" data-acl="{{ acl.quarantine_notification }}">
|
||||
<button type="button" class="btn btn-sm btn-xs-quart d-block d-sm-inline{% if quarantine_notification == 'never' %} btn-dark{% else %} btn-light{% endif %}"
|
||||
data-action="edit_selected"
|
||||
data-item="{{ mailcow_cc_username }}"
|
||||
data-id="quarantine_notification"
|
||||
data-api-url='edit/quarantine_notification'
|
||||
data-api-attr='{"quarantine_notification":"never"}'>{{ lang.user.never }}</button>
|
||||
<button type="button" class="btn btn-sm btn-xs-quart d-block d-sm-inline{% if quarantine_notification == 'hourly' %} btn-dark{% else %} btn-light{% endif %}"
|
||||
data-action="edit_selected"
|
||||
data-item="{{ mailcow_cc_username }}"
|
||||
data-id="quarantine_notification"
|
||||
data-api-url='edit/quarantine_notification'
|
||||
data-api-attr='{"quarantine_notification":"hourly"}'>{{ lang.user.hourly }}</button>
|
||||
<button type="button" class="btn btn-sm btn-xs-quart d-block d-sm-inline{% if quarantine_notification == 'daily' %} btn-dark{% else %} btn-light{% endif %}"
|
||||
data-action="edit_selected"
|
||||
data-item="{{ mailcow_cc_username }}"
|
||||
data-id="quarantine_notification"
|
||||
data-api-url='edit/quarantine_notification'
|
||||
data-api-attr='{"quarantine_notification":"daily"}'>{{ lang.user.daily }}</button>
|
||||
<button type="button" class="btn btn-sm btn-xs-quart d-block d-sm-inline{% if quarantine_notification == 'weekly' %} btn-dark{% else %} btn-light{% endif %}"
|
||||
data-action="edit_selected"
|
||||
data-item="{{ mailcow_cc_username }}"
|
||||
data-id="quarantine_notification"
|
||||
data-api-url='edit/quarantine_notification'
|
||||
data-api-attr='{"quarantine_notification":"weekly"}'>{{ lang.user.weekly }}</button>
|
||||
</div>
|
||||
<p class="text-muted">{{ lang.user.quarantine_notification_info }}</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-sm-3 col-12 text-sm-end text-start text-xs-bold mb-4">{{ lang.user.quarantine_category }}:</div>
|
||||
<div class="col-sm-9 col-12">
|
||||
<div class="btn-group" data-acl="{{ acl.quarantine_category }}">
|
||||
<button type="button" class="btn btn-sm btn-xs-third d-block d-sm-inline{% if quarantine_category == 'reject' %} btn-dark{% else %} btn-light{% endif %}"
|
||||
data-action="edit_selected"
|
||||
data-item="{{ mailcow_cc_username }}"
|
||||
data-id="quarantine_category"
|
||||
data-api-url='edit/quarantine_category'
|
||||
data-api-attr='{"quarantine_category":"reject"}'>{{ lang.user.q_reject }}</button>
|
||||
<button type="button" class="btn btn-sm btn-xs-third d-block d-sm-inline{% if quarantine_category == 'add_header' %} btn-dark{% else %} btn-light{% endif %}"
|
||||
data-action="edit_selected"
|
||||
data-item="{{ mailcow_cc_username }}"
|
||||
data-id="quarantine_category"
|
||||
data-api-url='edit/quarantine_category'
|
||||
data-api-attr='{"quarantine_category":"add_header"}'>{{ lang.user.q_add_header }}</button>
|
||||
<button type="button" class="btn btn-sm btn-xs-third d-block d-sm-inline{% if quarantine_category == 'all' %} btn-dark{% else %} btn-light{% endif %}"
|
||||
data-action="edit_selected"
|
||||
data-item="{{ mailcow_cc_username }}"
|
||||
data-id="quarantine_category"
|
||||
data-api-url='edit/quarantine_category'
|
||||
data-api-attr='{"quarantine_category":"all"}'>{{ lang.user.q_all }}</button>
|
||||
</div>
|
||||
<p class="text-muted">{{ lang.user.quarantine_category_info }}</p>
|
||||
</div>
|
||||
</div>
|
||||
{% if not skip_sogo %}
|
||||
<hr>
|
||||
<div class="row">
|
||||
<div class="col-sm-3 col-12 text-sm-end text-start text-xs-bold mb-4">{{ lang.user.eas_reset }}:</div>
|
||||
<div class="col-sm-9 col-12">
|
||||
<button class="btn btn-sm d-block d-sm-inline btn-secondary" data-acl="{{ acl.eas_reset }}" data-action="delete_selected" data-text="{{ lang.user.eas_reset }}?" data-item="{{ mailcow_cc_username }}" data-id="eas_cache" data-api-url='delete/eas_cache' href="#">{{ lang.user.eas_reset_now }}</button>
|
||||
<p class="text-muted">{{ lang.user.eas_reset_help|raw }}</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-sm-3 col-12 text-sm-end text-start text-xs-bold mb-4">{{ lang.user.sogo_profile_reset }}:</div>
|
||||
<div class="col-sm-9 col-12">
|
||||
<button class="btn btn-sm d-block d-sm-inline btn-secondary" data-acl="{{ acl.sogo_profile_reset }}" data-action="delete_selected" data-text="{{ lang.user.sogo_profile_reset }}?" data-item="{{ mailcow_cc_username }}" data-id="sogo_profile" data-api-url='delete/sogo_profile' href="#">{{ lang.user.sogo_profile_reset_now }}</button>
|
||||
<p class="text-muted">{{ lang.user.sogo_profile_reset_help|raw }}</p>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
11
data/web/templates/user_domainadmin_common.twig
Executable file
11
data/web/templates/user_domainadmin_common.twig
Executable file
|
|
@ -0,0 +1,11 @@
|
|||
{% include 'modals/user.twig' %}
|
||||
|
||||
<script type='text/javascript'>
|
||||
var acl = '{{ acl_json|raw }}';
|
||||
var lang = {{ lang_user|raw }};
|
||||
var csrf_token = '{{ csrf_token }}';
|
||||
var pagination_size = Math.trunc('{{ pagination_size }}');
|
||||
var mailcow_cc_username = '{{ mailcow_cc_username }}';
|
||||
var user_spam_score = [{{ user_spam_score }}];
|
||||
var lang_datatables = {{ lang_datatables|raw }};
|
||||
</script>
|
||||
Loading…
Add table
Add a link
Reference in a new issue