From de831174c15f3bc5ddf108edc1beab03ab1f424f Mon Sep 17 00:00:00 2001 From: hmoreau Date: Sat, 25 Jan 2025 22:40:50 +0100 Subject: [PATCH 1/4] Feature: Add a custom HEADER field to servers requests (#1215) * Update Installer: add field to db * Add custom header to StatusUpdater * Update server update form * Translations * Update installer --- src/includes/functions.inc.php | 8 +++++++- src/lang/en_US.lang.php | 2 ++ src/lang/fr_FR.lang.php | 2 ++ .../Module/Server/Controller/AbstractServerController.php | 3 ++- src/psm/Module/Server/Controller/ServerController.php | 4 ++++ src/psm/Util/Install/Installer.php | 3 +++ src/psm/Util/Server/Updater/StatusUpdater.php | 5 +++-- .../default/module/server/server/update.tpl.html | 6 ++++++ 8 files changed, 29 insertions(+), 4 deletions(-) diff --git a/src/includes/functions.inc.php b/src/includes/functions.inc.php index a879d74f..3cfe5e38 100644 --- a/src/includes/functions.inc.php +++ b/src/includes/functions.inc.php @@ -390,6 +390,7 @@ namespace { * @param string|bool $website_password Password website * @param string|null $request_method Request method like GET, POST etc. * @param string|null $post_field POST data + * @param string|null $custom_header HEADER data * @return array cURL result */ function psm_curl_get( @@ -401,7 +402,8 @@ namespace { $website_username = false, $website_password = false, $request_method = null, - $post_field = null + $post_field = null, + $custom_header = null ) { ($timeout === null || $timeout > 0) ? PSM_CURL_TIMEOUT : intval($timeout); @@ -429,6 +431,10 @@ namespace { curl_setopt($ch, CURLOPT_POSTFIELDS, $post_field); } + if (!empty($custom_header)){ + curl_setopt($ch, CURLOPT_HTTPHEADER, array($custom_header)); + } + if ( $website_username !== false && $website_password !== false && diff --git a/src/lang/en_US.lang.php b/src/lang/en_US.lang.php index f414f964..f0bf3efd 100644 --- a/src/lang/en_US.lang.php +++ b/src/lang/en_US.lang.php @@ -283,6 +283,8 @@ $sm_lang = array( 'error_server_type_invalid' => 'The selected server type is invalid.', 'error_server_warning_threshold_invalid' => 'The warning threshold must be a valid integer greater than 0.', 'error_server_ssl_cert_expiry_days' => 'The remaining days for SSL certificate validity must be a valid integer greater than or equal to 0.', + 'custom_header' => 'Custom header', + 'custom_header_description' => 'Allows to add a custom header to the request.', ), 'config' => array( 'general' => 'General', diff --git a/src/lang/fr_FR.lang.php b/src/lang/fr_FR.lang.php index 35ca0f36..0bf9a813 100644 --- a/src/lang/fr_FR.lang.php +++ b/src/lang/fr_FR.lang.php @@ -272,6 +272,8 @@ $sm_lang = array( 'error_server_ip_bad_website' => 'L\'URL du site web n\'est pas valide.', 'error_server_type_invalid' => 'Le type de service sélectionné n\'est pas valide.', 'error_server_warning_threshold_invalid' => 'Le seuil d\'alerte doit être un nombre entier supérieur à 0.', + 'custom_header' => 'Header personnalisé', + 'custom_header_description' => 'Permet d\'ajouter une directive HEADER personnalisée à la requête', ), 'config' => array( 'general' => 'Général', diff --git a/src/psm/Module/Server/Controller/AbstractServerController.php b/src/psm/Module/Server/Controller/AbstractServerController.php index 8ae2968c..ffe25e84 100644 --- a/src/psm/Module/Server/Controller/AbstractServerController.php +++ b/src/psm/Module/Server/Controller/AbstractServerController.php @@ -95,7 +95,8 @@ abstract class AbstractServerController extends AbstractController `s`.`website_password`, `s`.`last_error`, `s`.`last_error_output`, - `s`.`last_output` + `s`.`last_output`, + `s`.`custom_header` FROM `" . PSM_DB_PREFIX . "servers` AS `s` {$sql_join} {$sql_where} diff --git a/src/psm/Module/Server/Controller/ServerController.php b/src/psm/Module/Server/Controller/ServerController.php index d81ba0b9..6aa3b7c1 100644 --- a/src/psm/Module/Server/Controller/ServerController.php +++ b/src/psm/Module/Server/Controller/ServerController.php @@ -261,6 +261,7 @@ class ServerController extends AbstractServerController 'edit_pushover_selected' => $edit_server['pushover'], 'edit_telegram_selected' => $edit_server['telegram'], 'edit_jabber_selected' => $edit_server['jabber'], + 'edit_custom_header' => $edit_server['custom_header'], )); } @@ -337,6 +338,7 @@ class ServerController extends AbstractServerController 'webhook' => in_array($_POST['webhook'], array('yes', 'no')) ? $_POST['webhook'] : 'no', 'telegram' => in_array($_POST['telegram'], array('yes', 'no')) ? $_POST['telegram'] : 'no', 'jabber' => in_array($_POST['jabber'], array('yes', 'no')) ? $_POST['jabber'] : 'no', + 'custom_header' => empty(psm_POST('custom_header')) ? null : psm_POST('custom_header'), ); // make sure websites start with http:// if ( @@ -651,6 +653,8 @@ class ServerController extends AbstractServerController 'label_log_no_logs' => psm_get_lang('log', 'no_logs'), 'label_date' => psm_get_lang('system', 'date'), 'label_message' => psm_get_lang('system', 'message'), + 'label_custom_header' => psm_get_lang('servers', 'custom_header'), + 'label_custom_header_description' => psm_get_lang('servers', 'custom_header_description'), ); } diff --git a/src/psm/Util/Install/Installer.php b/src/psm/Util/Install/Installer.php index 0cc91a83..5b40898b 100644 --- a/src/psm/Util/Install/Installer.php +++ b/src/psm/Util/Install/Installer.php @@ -293,6 +293,7 @@ class Installer `last_error` varchar(255) DEFAULT NULL, `last_error_output` TEXT, `last_output` TEXT, + `custom_header` TEXT NULL DEFAULT NULL, PRIMARY KEY (`server_id`) ) DEFAULT CHARSET=utf8;", PSM_DB_PREFIX . 'servers_uptime' => "CREATE TABLE IF NOT EXISTS `" . PSM_DB_PREFIX . "servers_uptime` ( @@ -747,6 +748,8 @@ class Installer CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL;"; $queries[] = "ALTER TABLE `" . PSM_DB_PREFIX . "servers` ADD `webhook` ENUM( 'yes','no' ) NOT NULL DEFAULT 'yes' AFTER `telegram`;"; + $queries[] = "ALTER TABLE `" . PSM_DB_PREFIX . "servers` + ADD `custom_header` TEXT NULL DEFAULT NULL AFTER `last_output`;"; $queries[] = "INSERT INTO `" . PSM_DB_PREFIX . "config` (`key`, `value`) VALUE ('discord_status', '0'), ('log_discord', '1'), diff --git a/src/psm/Util/Server/Updater/StatusUpdater.php b/src/psm/Util/Server/Updater/StatusUpdater.php index e299ae98..5a006166 100644 --- a/src/psm/Util/Server/Updater/StatusUpdater.php +++ b/src/psm/Util/Server/Updater/StatusUpdater.php @@ -100,7 +100,7 @@ class StatusUpdater 'allow_http_status', 'redirect_check', 'header_name', 'header_value', 'status', 'active', 'warning_threshold', 'warning_threshold_counter', 'ssl_cert_expiry_days', 'ssl_cert_expired_time', 'timeout', 'website_username', - 'website_password', 'last_offline' + 'website_password', 'last_offline', 'custom_header' )); if (empty($this->server)) { return false; @@ -248,7 +248,8 @@ class StatusUpdater psm_password_decrypt($this->server['server_id'] . psm_get_conf('password_encrypt_key'), $this->server['website_password']), $this->server['request_method'], - $this->server['post_field'] + $this->server['post_field'], + $this->server['custom_header'] ); $this->header = $curl_result['exec']; $this->curl_info = $curl_result['info']; diff --git a/src/templates/default/module/server/server/update.tpl.html b/src/templates/default/module/server/server/update.tpl.html index 1867031b..f1fe57ac 100644 --- a/src/templates/default/module/server/server/update.tpl.html +++ b/src/templates/default/module/server/server/update.tpl.html @@ -120,6 +120,12 @@ {{ macro.input_field("number", "timeout", null, "timeout", label_timeout, edit_value_timeout, default_value_timeout, "10", 'timeout_help', label_timeout_description) }} +
+ {{ label_custom_header }} ({{ label_optional }}) +
+ {{ macro.input_field("text", "custom_header", null, "custom_header", label_custom_header, edit_custom_header, "Cookie:...", null, 'custom_header_help', label_custom_header_description) }} +
+
{{ label_authentication_settings }} ({{ label_optional }})
From 607c2e1e827a9cf0e8e05ab8a34ac33eba363d2e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Bivoj=20Kubie=C5=84?= Date: Sat, 25 Jan 2025 23:28:57 +0100 Subject: [PATCH 2/4] Add IP whitelist turn off option (#1249) --- config.php.sample | 2 ++ cron/status.cron.php | 14 ++++++++++---- dev/vagrant-config.php | 1 + 3 files changed, 13 insertions(+), 4 deletions(-) diff --git a/config.php.sample b/config.php.sample index a9537ed0..61b2c271 100644 --- a/config.php.sample +++ b/config.php.sample @@ -7,4 +7,6 @@ define('PSM_DB_HOST', 'localhost'); define('PSM_DB_PORT', '3306'); //3306 is the default port for MySQL. If no specfic port is used, leave it empty. define('PSM_BASE_URL', ''); define('PSM_WEBCRON_KEY', ''); +define('PSM_WEBCRON_ENABLE_IP_WHITELIST', 'true'); // Enable IP whitelisting for calling webcron define('PSM_PUBLIC', false); + diff --git a/cron/status.cron.php b/cron/status.cron.php index e4fac525..a4f541e5 100644 --- a/cron/status.cron.php +++ b/cron/status.cron.php @@ -44,10 +44,16 @@ namespace { $data = (defined('PHP_MAJOR_VERSION') && PHP_MAJOR_VERSION >= 7) ? false : @unserialize(PSM_CRON_ALLOW); $allow = $data === false ? PSM_CRON_ALLOW : $data; - if (!in_array($_SERVER['REMOTE_ADDR'], $allow) && !in_array($_SERVER["HTTP_X_FORWARDED_FOR"], $allow) - && ! (array_key_exists ("webcron_key", $_GET) && - $_GET["webcron_key"]==PSM_WEBCRON_KEY && (PSM_WEBCRON_KEY != "")) - ) { + $ipWhitelistCheckPassed = in_array($_SERVER['REMOTE_ADDR'], $allow) + && in_array($_SERVER["HTTP_X_FORWARDED_FOR"], $allow) + && PSM_WEBCRON_ENABLE_IP_WHITELIST; + + $webCronKeyCheckPassed = + array_key_exists ("webcron_key", $_GET) + && $_GET["webcron_key"] == PSM_WEBCRON_KEY + && (PSM_WEBCRON_KEY != ""); + + if (!$ipWhitelistCheckPassed && !$webCronKeyCheckPassed) { header('HTTP/1.0 403 Forbidden'); die(' diff --git a/dev/vagrant-config.php b/dev/vagrant-config.php index d2c8582a..c1addd82 100644 --- a/dev/vagrant-config.php +++ b/dev/vagrant-config.php @@ -7,4 +7,5 @@ define('PSM_DB_HOST', 'localhost'); define('PSM_DB_PORT', '3306'); //3306 is the default port for MySQL. If no specfic port is used, leave it empty. define('PSM_BASE_URL', ''); define('PSM_WEBCRON_KEY', ''); +define('PSM_WEBCRON_ENABLE_IP_WHITELIST', 'true'); define('PSM_PUBLIC', false); From 7e9826b532dd2578b0e26565576dc77fa582be2f Mon Sep 17 00:00:00 2001 From: M Alfiyan S Date: Sun, 26 Jan 2025 05:32:15 +0700 Subject: [PATCH 3/4] Server monthly uptime analytics (#1146) * add month button * generate by last month, tracing why < week uptime truncated * start hack archiver * add weekly default config for dynamic archive * if monthly archive defined, allow up to ~1 month old uptime date * allow quarterly retention * add comment for archiver * query by archive settings retention --- .../Install/Controller/InstallController.php | 1 + .../Util/Server/Archiver/UptimeArchiver.php | 13 +++++++++++-- src/psm/Util/Server/HistoryGraph.php | 18 +++++++++++++++++- 3 files changed, 29 insertions(+), 3 deletions(-) diff --git a/src/psm/Module/Install/Controller/InstallController.php b/src/psm/Module/Install/Controller/InstallController.php index 34f85818..d96c958c 100644 --- a/src/psm/Module/Install/Controller/InstallController.php +++ b/src/psm/Module/Install/Controller/InstallController.php @@ -202,6 +202,7 @@ class InstallController extends AbstractController 'db_pass' => '', 'db_prefix' => 'psm_', 'base_url' => $this->getBaseUrl(), + 'uptime_archive' => 'weekly', ); $changed = false; diff --git a/src/psm/Util/Server/Archiver/UptimeArchiver.php b/src/psm/Util/Server/Archiver/UptimeArchiver.php index e7db3183..e047d0c5 100644 --- a/src/psm/Util/Server/Archiver/UptimeArchiver.php +++ b/src/psm/Util/Server/Archiver/UptimeArchiver.php @@ -56,7 +56,10 @@ class UptimeArchiver implements ArchiverInterface } /** - * Archive all server status records older than 1 week. + * Archive all server status records older than (X) based on config. + * quarterly = up to last 3 months + * monthly = up to last 1 month + * default / weekly = up to 1 week * * Archiving means calculating averages per day, and storing 1 single * history row for each day for each server. @@ -65,7 +68,13 @@ class UptimeArchiver implements ArchiverInterface */ public function archive($server_id = null) { - $latest_date = new \DateTime('-1 week 0:0:0'); + if(PSM_UPTIME_ARCHIVE == 'quarterly'){ + $latest_date = new \DateTime('-3 month 0:0:0'); + }else if(PSM_UPTIME_ARCHIVE == 'monthly'){ + $latest_date = new \DateTime('-1 month 0:0:0'); + }else{ + $latest_date = new \DateTime('-1 week 0:0:0'); + } // Lock tables to prevent simultaneous archiving (by other sessions or the cron job) try { diff --git a/src/psm/Util/Server/HistoryGraph.php b/src/psm/Util/Server/HistoryGraph.php index 11425e8b..c61e07b5 100644 --- a/src/psm/Util/Server/HistoryGraph.php +++ b/src/psm/Util/Server/HistoryGraph.php @@ -71,11 +71,21 @@ class HistoryGraph $archive->archive($server_id); $now = new DateTime(); + + if(PSM_UPTIME_ARCHIVE == 'quarterly'){ + $start_date = new DateTime('-3 month 0:0:0'); + }else if(PSM_UPTIME_ARCHIVE == 'monthly'){ + $start_date = new DateTime('-1 month 0:0:0'); + }else{ + $start_date = new DateTime('-1 week 0:0:0'); + } + $last_week = new DateTime('-1 week 0:0:0'); + $last_month = new DateTime('-1 month 0:0:0'); $last_year = new DateTime('-1 year -1 week 0:0:0'); $graphs = array( - 0 => $this->generateGraphUptime($server_id, $last_week, $now), + 0 => $this->generateGraphUptime($server_id, $start_date, $now), 1 => $this->generateGraphHistory($server_id, $last_year, $last_week), ); $info_fields = array( @@ -120,6 +130,7 @@ class HistoryGraph $hour = new DateTime('-1 hour'); $day = new DateTime('-1 day'); $week = new DateTime('-1 week'); + $month = new DateTime('-1 month'); $records = $this->getRecords('uptime', $server_id, $start_time, $end_time); @@ -146,6 +157,11 @@ class HistoryGraph 'time' => $week->getTimestamp() * 1000, 'label' => psm_get_lang('servers', 'week') ); + $data['buttons'][] = array( + 'unit' => 'day', + 'time' => $month->getTimestamp() * 1000, + 'label' => psm_get_lang('servers', 'month') + ); return $data; } From c70d23859a333d58c5d60eb2729015831d69d059 Mon Sep 17 00:00:00 2001 From: Tim Zandbergen Date: Sun, 26 Jan 2025 00:00:51 +0100 Subject: [PATCH 4/4] Removed non-translated lines. --- src/lang/pl_PL.lang.php | 25 ------------------------- 1 file changed, 25 deletions(-) diff --git a/src/lang/pl_PL.lang.php b/src/lang/pl_PL.lang.php index c7cfbac1..59b812f9 100644 --- a/src/lang/pl_PL.lang.php +++ b/src/lang/pl_PL.lang.php @@ -525,31 +525,6 @@ $sm_lang = array( 'on_jabber_message' => 'Serwer \'%LABEL%\' znów działa poprawnie, był offline przez %LAST_OFFLINE_DURATION%:

Serwer: %LABEL%
IP: %IP%
Port: %PORT%
Data: %DATE%', - 'combi_off_email_message' => '
  • Server: %LABEL%
  • IP: %IP%
  • Port: %PORT%
  • Error: - %ERROR%
  • Date: %DATE%
', - 'combi_off_discord_message' => '- Server: %LABEL%
- IP: %IP%
- Port: %PORT%
- Error: %ERROR%
- - Date: %DATE%

', - 'combi_off_webhook_message' => '
  • Server: %LABEL%
  • IP: %IP%
  • Port: %PORT%
  • Error: - %ERROR%
  • Date: %DATE%
', - 'combi_off_pushover_message' => '
  • Server: %LABEL%
  • IP: %IP%
  • Port: %PORT%
  • Error: - %ERROR%
  • Date: %DATE%
', - 'combi_off_telegram_message' => '- Server: %LABEL%
- IP: %IP%
- Port: %PORT%
- Error: %ERROR%
- - Date: %DATE%

', - 'combi_off_jabber_message' => '- Server: %LABEL%
- IP: %IP%
- Port: %PORT%
- Error: %ERROR%
- - Date: %DATE%

', - 'combi_on_email_message' => '
  • Server: %LABEL%
  • IP: %IP%
  • Port: %PORT%
  • Downtime: - %LAST_OFFLINE_DURATION%
  • Date: %DATE%
', - 'combi_on_webhook_message' => '
  • Server: %LABEL%
  • IP: %IP%
  • Port: %PORT%
  • Downtime: - %LAST_OFFLINE_DURATION%
  • Date: %DATE%
', - 'combi_on_discord_message' => '- Server: %LABEL%
- IP: %IP%
- Port: %PORT%
- Downtime: - %LAST_OFFLINE_DURATION%
- Date: %DATE%

', - 'combi_on_pushover_message' => '
  • Server: %LABEL%
  • IP: %IP%
  • Port: - %PORT%
  • Downtime: %LAST_OFFLINE_DURATION%
  • Date: - %DATE%
', - 'combi_on_telegram_message' => '- Server: %LABEL%
- IP: %IP%
- Port: %PORT%
- Downtime: - %LAST_OFFLINE_DURATION%
- Date: %DATE%

', - 'combi_on_jabber_message' => '- Server: %LABEL%
- IP: %IP%
- Port: %PORT%
- Downtime: - %LAST_OFFLINE_DURATION%
- Date: %DATE%

', 'combi_email_subject' => 'WAŻNE: \'%UP%\' serverów znowu ONLINE, \'%DOWN%\' serverów jest OFFLINE', 'combi_webhook_subject' => '\'%UP%\' serverów jest znowu ONLINE UP, \'%DOWN%\' serverów jest OFFLINE', 'combi_pushover_subject' => '\'%UP%\' serverów jest znowu ONLINE UP, \'%DOWN%\' serverów jest OFFLINE',