[Web] Allow ratelimit time frame "day"; Allow to create announcements

master
andryyy 2020-05-11 11:52:02 +02:00
parent 02a74914b4
commit 767ae65946
No known key found for this signature in database
GPG Key ID: 8EC34FF2794E25EF
11 changed files with 116 additions and 70 deletions

View File

@ -1,7 +0,0 @@
#!/bin/bash
echo action=OK
exit
while read QUERY; do
logger -t last_login -p mail.info "$QUERY"
done
echo action=OK

View File

@ -117,10 +117,14 @@ if (!isset($_SESSION['gal']) && $license_cache = $redis->Get('LICENSE_STATUS_CAC
<span style="font-size:12px" class="arrow rotate glyphicon glyphicon-menu-down"></span> API
</legend>
<div id="admin_api" class="collapse">
<div class="row">
<?php
$api_ro = admin_api('ro', 'get');
$api_rw = admin_api('rw', 'get');
?>
<div class="col-lg-12">
<p class="help-block"><?=$lang['admin']['api_info'];?></p>
</div>
<div class="col-lg-6">
<div class="panel panel-default">
<div class="panel-heading">
@ -156,7 +160,6 @@ if (!isset($_SESSION['gal']) && $license_cache = $redis->Get('LICENSE_STATUS_CAC
</div>
<div class="form-group">
<div class="col-sm-offset-3 col-sm-9">
<p class="help-block"><?=$lang['admin']['api_info'];?></p>
<div class="btn-group">
<button class="btn btn-sm btn-success" name="admin_api[ro]" type="submit" href="#"><span class="glyphicon glyphicon-check"></span> <?=$lang['admin']['save'];?></button>
<button class="btn btn-sm btn-default admin-ays-dialog" name="admin_api_regen_key[ro]" type="submit" href="#"><?=$lang['admin']['regen_api_key'];?></button>
@ -202,7 +205,6 @@ if (!isset($_SESSION['gal']) && $license_cache = $redis->Get('LICENSE_STATUS_CAC
</div>
<div class="form-group">
<div class="col-sm-offset-3 col-sm-9">
<p class="help-block"><?=$lang['admin']['api_info'];?></p>
<div class="btn-group">
<button class="btn btn-sm btn-success" name="admin_api[rw]" type="submit" href="#"><span class="glyphicon glyphicon-check"></span> <?=$lang['admin']['save'];?></button>
<button class="btn btn-sm btn-default admin-ays-dialog" name="admin_api_regen_key[rw]" type="submit" href="#"><?=$lang['admin']['regen_api_key'];?></button>
@ -216,6 +218,7 @@ if (!isset($_SESSION['gal']) && $license_cache = $redis->Get('LICENSE_STATUS_CAC
</div>
</div>
</div>
</div>
<div class="panel panel-default">
<div class="panel-heading"><?=$lang['admin']['domain_admins'];?></div>
@ -294,7 +297,7 @@ if (!isset($_SESSION['gal']) && $license_cache = $redis->Get('LICENSE_STATUS_CAC
</div>
<div class="form-group">
<div class="col-sm-offset-3 col-sm-9">
<button type="submit" class="btn btn-default" id="rspamd_ui" name="rspamd_ui" href="#"><span class="glyphicon glyphicon-check"></span> <?=$lang['admin']['save'];?></button>
<button type="submit" class="btn btn-sm btn-success" id="rspamd_ui" name="rspamd_ui" href="#"><span class="glyphicon glyphicon-check"></span> <?=$lang['admin']['save'];?></button>
</div>
</div>
</form>
@ -703,7 +706,7 @@ if (!isset($_SESSION['gal']) && $license_cache = $redis->Get('LICENSE_STATUS_CAC
<textarea class="form-control" name="blacklist" rows="5"><?=$f2b_data['blacklist'];?></textarea>
</div>
<div class="btn-group">
<button class="btn btn-default" data-action="edit_selected" data-item="self" data-id="f2b" data-api-url='edit/fail2ban' data-api-attr='{}' href="#"><span class="glyphicon glyphicon-check"></span> <?=$lang['admin']['save'];?></button>
<button class="btn btn-success" data-action="edit_selected" data-item="self" data-id="f2b" data-api-url='edit/fail2ban' data-api-attr='{}' href="#"><span class="glyphicon glyphicon-check"></span> <?=$lang['admin']['save'];?></button>
<a href="#" role="button" class="btn btn-default" data-toggle="modal" data-container="netfilter-mailcow" data-target="#RestartContainer"><span class="glyphicon glyphicon-refresh"></span> <?= $lang['header']['restart_netfilter']; ?></a>
</div>
</form>
@ -840,7 +843,7 @@ if (!isset($_SESSION['gal']) && $license_cache = $redis->Get('LICENSE_STATUS_CAC
</div>
</div>
</div>
<button class="btn btn-default" data-action="edit_selected" data-item="self" data-id="quarantine" data-api-url='edit/quarantine' data-api-attr='{"action":"settings"}' href="#"><span class="glyphicon glyphicon-check"></span> <?=$lang['admin']['save'];?></button>
<button class="btn btn-sm btn-success" data-action="edit_selected" data-item="self" data-id="quarantine" data-api-url='edit/quarantine' data-api-attr='{"action":"settings"}' href="#"><span class="glyphicon glyphicon-check"></span> <?=$lang['admin']['save'];?></button>
</form>
</div>
</div>
@ -885,7 +888,7 @@ if (!isset($_SESSION['gal']) && $license_cache = $redis->Get('LICENSE_STATUS_CAC
data-item="quota_notification"
data-id="quota_notification"
data-api-url='edit/quota_notification'
data-api-attr='{}'><?=$lang['user']['save_changes'];?></a>
data-api-attr='{}'><span class="glyphicon glyphicon-check"></span> <?=$lang['user']['save_changes'];?></a>
</div>
</div>
</div>
@ -965,8 +968,8 @@ if (!isset($_SESSION['gal']) && $license_cache = $redis->Get('LICENSE_STATUS_CAC
<input type="checkbox" name="active" value="1" <?=($rsetting_details['active_int'] == 1) ? 'checked' : null;?>> <?=$lang['admin']['active'];?>
</label>
</div>
<button class="btn btn-default" data-action="edit_selected" data-item="<?=$rsetting_details['id'];?>" data-id="rsettings" data-api-url='edit/rsetting' data-api-attr='{}' href="#"><span class="glyphicon glyphicon-check"></span> <?=$lang['admin']['save'];?></button>
<button class="btn 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>
<button class="btn btn-sm btn-success" data-action="edit_selected" data-item="<?=$rsetting_details['id'];?>" data-id="rsettings" data-api-url='edit/rsetting' data-api-attr='{}' href="#"><span class="glyphicon glyphicon-check"></span> <?=$lang['admin']['save'];?></button>
<button class="btn btn-sm 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>
</form>
</div>
<?php
@ -1049,15 +1052,13 @@ if (!isset($_SESSION['gal']) && $license_cache = $redis->Get('LICENSE_STATUS_CAC
?>
</table>
<p><div class="btn-group">
<button class="btn btn-sm btn-default" data-action="edit_selected" data-item="admin" data-id="app_links" data-reload="no" data-api-url='edit/app_links' data-api-attr='{}' href="#"><span class="glyphicon glyphicon-check"></span> <?=$lang['admin']['save'];?></button>
<button class="btn btn-sm 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="#"><span class="glyphicon glyphicon-check"></span> <?=$lang['admin']['save'];?></button>
<button class="btn btn-sm btn-default" type="button" id="add_app_link_row"><?=$lang['admin']['add_row'];?></button>
</div></p>
</form>
<legend data-target="#ui_texts" style="padding-top:20px" unselectable="on"><?=$lang['admin']['ui_texts'];?></legend>
<div id="ui_texts">
<?php
$ui_texts = customize('get', 'ui_texts');
?>
<?php $ui_texts = customize('get', 'ui_texts'); ?>
<form class="form" data-id="uitexts" role="form" method="post">
<div class="form-group">
<label for="title_name"><?=$lang['admin']['title_name'];?>:</label>
@ -1075,11 +1076,24 @@ if (!isset($_SESSION['gal']) && $license_cache = $redis->Get('LICENSE_STATUS_CAC
<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'];?></textarea>
</div>
<hr>
<div class="form-group">
<p class="help-block"><?=$lang['admin']['ui_header_announcement_help'];?></p>
<label for="ui_announcement_type"><?=$lang['admin']['ui_header_announcement'];?>:</label>
<p><select multiple data-width="100%" name="ui_announcement_type" class="selectpicker show-tick" data-max-options="1" title="<?=$lang['admin']['ui_header_announcement_select'];?>">
<option <?=($ui_texts['ui_announcement_type'] == 'info') ? 'selected' : null;?> value="info"><?=$lang['admin']['ui_header_announcement_type_info'];?></option>
<option <?=($ui_texts['ui_announcement_type'] == 'warning') ? 'selected' : null;?> value="warning"><?=$lang['admin']['ui_header_announcement_type_warning'];?></option>
<option <?=($ui_texts['ui_announcement_type'] == 'danger') ? 'selected' : null;?> value="danger"><?=$lang['admin']['ui_header_announcement_type_danger'];?></option>
</select></p>
<p><textarea class="form-control" id="ui_announcement_text" name="ui_announcement_text" rows="7"><?=$ui_texts['ui_announcement_text'];?></textarea></p>
<p><input type="checkbox" name="ui_announcement_active" <?=($ui_texts['ui_announcement_active'] == 1) ? 'checked' : null;?>> <?=$lang['admin']['ui_header_announcement_active'];?></p>
</div>
<hr>
<div class="form-group">
<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-default" data-action="edit_selected" data-item="ui" data-id="uitexts" data-api-url='edit/ui_texts' data-api-attr='{}' href="#"><span class="glyphicon glyphicon-check"></span> <?=$lang['admin']['save'];?></button>
<button class="btn btn-sm btn-success" data-action="edit_selected" data-item="ui" data-id="uitexts" data-api-url='edit/ui_texts' data-api-attr='{}' href="#"><span class="glyphicon glyphicon-check"></span> <?=$lang['admin']['save'];?></button>
</form>
</div>
</div>

View File

@ -382,6 +382,7 @@ if (isset($_SESSION['mailcow_cc_role'])) {
<option value="s" <?=(isset($rl['frame']) && $rl['frame'] == 's') ? 'selected' : null;?>>msgs / second</option>
<option value="m" <?=(isset($rl['frame']) && $rl['frame'] == 'm') ? 'selected' : null;?>>msgs / minute</option>
<option value="h" <?=(isset($rl['frame']) && $rl['frame'] == 'h') ? 'selected' : null;?>>msgs / hour</option>
<option value="d" <?=(isset($rl['frame']) && $rl['frame'] == 'd') ? 'selected' : null;?>>msgs / day</option>
</select>
</div>
<div class="form-group">
@ -537,6 +538,7 @@ if (isset($_SESSION['mailcow_cc_role'])) {
<option value="s" <?=(isset($rl['frame']) && $rl['frame'] == 's') ? 'selected' : null;?>>msgs / second</option>
<option value="m" <?=(isset($rl['frame']) && $rl['frame'] == 'm') ? 'selected' : null;?>>msgs / minute</option>
<option value="h" <?=(isset($rl['frame']) && $rl['frame'] == 'h') ? 'selected' : null;?>>msgs / hour</option>
<option value="d" <?=(isset($rl['frame']) && $rl['frame'] == 'd') ? 'selected' : null;?>>msgs / day</option>
</select>
</div>
<div class="form-group">
@ -833,6 +835,7 @@ if (isset($_SESSION['mailcow_cc_role'])) {
<option value="s" <?=(isset($rl['frame']) && $rl['frame'] == 's') ? 'selected' : null;?>>msgs / second</option>
<option value="m" <?=(isset($rl['frame']) && $rl['frame'] == 'm') ? 'selected' : null;?>>msgs / minute</option>
<option value="h" <?=(isset($rl['frame']) && $rl['frame'] == 'h') ? 'selected' : null;?>>msgs / hour</option>
<option value="d" <?=(isset($rl['frame']) && $rl['frame'] == 'd') ? 'selected' : null;?>>msgs / day</option>
</select>
</div>
<div class="form-group">

View File

@ -182,13 +182,9 @@ $(document).ready(function() {
</script>
<div class="container footer">
<?php
if (!empty($UI_TEXTS['ui_footer'])):
?>
<?php if (!empty($UI_TEXTS['ui_footer'])) { ?>
<hr><?=$UI_TEXTS['ui_footer'];?>
<?php
endif;
?>
<?php } ?>
</div>
</body>
</html>

View File

@ -113,12 +113,18 @@ function customize($_action, $_item, $_data = null) {
$apps_name = $_data['apps_name'];
$help_text = $_data['help_text'];
$ui_footer = $_data['ui_footer'];
$ui_announcement_text = $_data['ui_announcement_text'];
$ui_announcement_type = (in_array($_data['ui_announcement_type'], array('info', 'warning', 'danger'))) ? $_data['ui_announcement_type'] : false;
$ui_announcement_active = (!empty($_data['ui_announcement_active']) ? 1 : 0);
try {
$redis->set('TITLE_NAME', htmlspecialchars($title_name));
$redis->set('MAIN_NAME', htmlspecialchars($main_name));
$redis->set('APPS_NAME', htmlspecialchars($apps_name));
$redis->set('HELP_TEXT', $help_text);
$redis->set('UI_FOOTER', $ui_footer);
$redis->set('UI_ANNOUNCEMENT_TEXT', $ui_announcement_text);
$redis->set('UI_ANNOUNCEMENT_TYPE', $ui_announcement_type);
$redis->set('UI_ANNOUNCEMENT_ACTIVE', $ui_announcement_active);
}
catch (RedisException $e) {
$_SESSION['return'][] = array(
@ -208,6 +214,9 @@ function customize($_action, $_item, $_data = null) {
$redis->del('UI_IMPRESS');
}
$data['ui_footer'] = ($ui_footer = $redis->get('UI_FOOTER')) ? $ui_footer : false;
$data['ui_announcement_text'] = ($ui_announcement_text = $redis->get('UI_ANNOUNCEMENT_TEXT')) ? $ui_announcement_text : false;
$data['ui_announcement_type'] = ($ui_announcement_type = $redis->get('UI_ANNOUNCEMENT_TYPE')) ? $ui_announcement_type : false;
$data['ui_announcement_active'] = ($redis->get('UI_ANNOUNCEMENT_ACTIVE') == 1) ? 1 : 0;
return $data;
}
catch (RedisException $e) {

View File

@ -25,7 +25,7 @@ function ratelimit($_action, $_scope, $_data = null) {
foreach ($objects as $object) {
$rl_value = intval($_data['rl_value']);
$rl_frame = $_data['rl_frame'];
if (!in_array($rl_frame, array('s', 'm', 'h'))) {
if (!in_array($rl_frame, array('s', 'm', 'h', 'd'))) {
$_SESSION['return'][] = array(
'type' => 'danger',
'log' => array(__FUNCTION__, $_action, $_scope, $_data_log),
@ -85,7 +85,7 @@ function ratelimit($_action, $_scope, $_data = null) {
foreach ($objects as $object) {
$rl_value = intval($_data['rl_value']);
$rl_frame = $_data['rl_frame'];
if (!in_array($rl_frame, array('s', 'm', 'h'))) {
if (!in_array($rl_frame, array('s', 'm', 'h', 'd'))) {
$_SESSION['return'][] = array(
'type' => 'danger',
'log' => array(__FUNCTION__, $_action, $_scope, $_data_log),

View File

@ -138,3 +138,11 @@
</div><!--/.container-fluid -->
</nav>
<form action="/" method="post" id="logout"><input type="hidden" name="logout"></form>
<?php if (!empty($UI_TEXTS['ui_announcement_text']) &&
in_array($UI_TEXTS['ui_announcement_type'], array('info', 'warning', 'danger')) &&
$UI_TEXTS['ui_announcement_active'] == 1 &&
parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH) != '/') { ?>
<div class="container">
<div class="alert alert-<?=$UI_TEXTS['ui_announcement_type'];?>"><?=$UI_TEXTS['ui_announcement_text'];?></div>
</div>
<?php } ?>

View File

@ -32,6 +32,9 @@ $_SESSION['index_query_string'] = $_SERVER['QUERY_STRING'];
<div class="panel-heading"><span class="glyphicon glyphicon-user" aria-hidden="true"></span> <?= $lang['login']['login']; ?></div>
<div class="panel-body">
<div class="text-center mailcow-logo"><img src="<?=($main_logo = customize('get', 'main_logo')) ? $main_logo : '/img/cow_mailcow.svg';?>" alt="mailcow"></div>
<?php if (!empty($UI_TEXTS['ui_announcement_text']) && in_array($UI_TEXTS['ui_announcement_type'], array('info', 'warning', 'danger')) && $UI_TEXTS['ui_announcement_active'] == 1) { ?>
<div class="alert alert-<?=$UI_TEXTS['ui_announcement_type'];?>"><?=$UI_TEXTS['ui_announcement_text'];?></div>
<?php } ?>
<legend><?= isset($_SESSION['oauth2_request']) ? $lang['oauth2']['authorize_app'] : $UI_TEXTS['main_name'];?></legend>
<?php
if (strpos($_SESSION['index_query_string'], 'mobileconfig') !== false) {

View File

@ -287,6 +287,15 @@
"transport_maps": "Transport Maps",
"transports_hint": "→ Transport Maps <b>überwiegen</b> senderabhängige Transport Maps.<br>\r\n→ Transport Maps ignorieren Mailbox-Einstellungen für ausgehende Verschlüsselung. Eine serverweite TLS-Richtlinie wird jedoch angewendet.<br>\r\n→ Der Transport erfolgt immer via \"smtp:\".<br>\r\n→ Adressen, die mit \"/localhost$/\" übereinstimmen, werden immer via \"local:\" transportiert, daher sind sie von einer Zieldefinition \"*\" ausgeschlossen.<br>\r\n→ Die Authentifizierung wird anhand des \"Next hop\" Parameters ermittelt. Hierbei würde bei einem beispielhaften Wert \"[host]:25\" immer zuerst \"host\" abfragt und <b>erst im Anschluss</b> \"[host]:25\". Dieses Verhalten schließt die <b>gleichzeitige Verwendung</b> von Einträgen der Art \"host\" sowie \"[host]:25\" aus.",
"ui_footer": "Footer (HTML zulässig)",
"ui_header_announcement": "Ankündigungen",
"ui_header_announcement_active": "Ankündigung aktivieren",
"ui_header_announcement_content": "Text (HTML zulässig)",
"ui_header_announcement_help": "Die Ankündigungsbox erzeugt einen deutlichen Hinweis für alle Benutzer und auf der Login-Seite der UI.",
"ui_header_announcement_select": "Ankündigungstyp auswählen",
"ui_header_announcement_type": "Typ",
"ui_header_announcement_type_info": "Info",
"ui_header_announcement_type_warning": "Wichtig",
"ui_header_announcement_type_danger": "Sehr wichtig",
"ui_texts": "UI Label und Texte",
"unban_pending": "ausstehend",
"unchanged_if_empty": "Unverändert, wenn leer",

View File

@ -286,6 +286,15 @@
"transport_maps": "Transport Maps",
"transports_hint": "→ A transport map entry <b>overrules</b> a sender-dependent transport map</b>.<br>\r\n→ Outbound TLS policy settings per-user are ignored and can only be enforced by TLS policy map entries.<br>\r\n→ The transport service for defined transports is always \"smtp:\".<br>\r\n→ Addresses matching \"/localhost$/\" will always be transported via \"local:\", therefore a \"*\" destination will not apply to those addresses.<br>\r\n→ To determine credentials for an exemplary next hop \"[host]:25\", Postfix <b>always</b> queries for \"host\" before searching for \"[host]:25\". This behavior makes it impossible to use \"host\" and \"[host]:25\" at the same time.",
"ui_footer": "Footer (HTML allowed)",
"ui_header_announcement": "Announcements",
"ui_header_announcement_active": "Set announcement active",
"ui_header_announcement_content": "Text (HTML allowed)",
"ui_header_announcement_help": "The announcement is visible for all logged in users and on the login screen of the UI.",
"ui_header_announcement_select": "Select announcement type",
"ui_header_announcement_type": "Type",
"ui_header_announcement_type_info": "Info",
"ui_header_announcement_type_warning": "Important",
"ui_header_announcement_type_danger": "Very important",
"ui_texts": "UI labels and texts",
"unban_pending": "unban pending",
"unchanged_if_empty": "If unchanged leave blank",

View File

@ -160,6 +160,7 @@ if (!isset($_SESSION['mailcow_cc_role'])) {
<option value="s" <?=(isset($rl['frame']) && $rl['frame'] == 's') ? 'selected' : null;?>>msgs / second</option>
<option value="m" <?=(isset($rl['frame']) && $rl['frame'] == 'm') ? 'selected' : null;?>>msgs / minute</option>
<option value="h" <?=(isset($rl['frame']) && $rl['frame'] == 'h') ? 'selected' : null;?>>msgs / hour</option>
<option value="d" <?=(isset($rl['frame']) && $rl['frame'] == 'd') ? 'selected' : null;?>>msgs / day</option>
</select>
</div>
</div>
@ -375,6 +376,7 @@ if (!isset($_SESSION['mailcow_cc_role'])) {
<option value="s" <?=(isset($rl['frame']) && $rl['frame'] == 's') ? 'selected' : null;?>>msgs / second</option>
<option value="m" <?=(isset($rl['frame']) && $rl['frame'] == 'm') ? 'selected' : null;?>>msgs / minute</option>
<option value="h" <?=(isset($rl['frame']) && $rl['frame'] == 'h') ? 'selected' : null;?>>msgs / hour</option>
<option value="d" <?=(isset($rl['frame']) && $rl['frame'] == 'd') ? 'selected' : null;?>>msgs / day</option>
</select>
</div>
</div>