diff --git a/admin/index.php b/admin/index.php index a665ba1..d371ce4 100644 --- a/admin/index.php +++ b/admin/index.php @@ -7,10 +7,34 @@ if (!file_exists("../config.php")) else{ require_once("../config.php"); require_once("../classes/constellation.php"); - require_once("../classes/mailer.php"); + require_once("../classes/mailer.php"); require_once("../classes/notification.php"); require_once("../template.php"); require_once("../libs/parsedown/Parsedown.php"); + require_once("../classes/queue.php"); + + // Process the subscriber notification queue + // If CRON_SERVER_IP is not set, call notification once incident has been saved + if ( empty(CRON_SERVER_IP) ) + { + if ( isset($_GET['sent']) && $_GET['sent'] == true ) + { + Queue::process_queue(); + } + } + else if ( isset($_GET['task']) && $_GET['task'] == 'cron' ) + { + // Else, base it on call to /admin?task=cron being called from IP defined by CRON_SERVER_IP + if (! empty(CRON_SERVER_IP) && $_SERVER['REMOTE_ADDR'] == CRON_SERVER_IP ) + { + Queue::process_queue(); + syslog(1, "CRON server processed"); + } + else { + syslog(1, "CRON called from unauthorised server"); + } + } + if(isset($_COOKIE['user'])&&!isset($_SESSION['user'])) { @@ -32,7 +56,7 @@ else{ require_once("login-form.php"); } } - else + else { $user = new User($_SESSION['user']); if (!$user->is_active()) @@ -53,7 +77,7 @@ else{ case 'user': require_once("user.php"); break; - + case 'settings': require_once("settings.php"); break; @@ -73,4 +97,4 @@ else{ Template::render_footer(true); } -} \ No newline at end of file +} diff --git a/classes/incident.php b/classes/incident.php index db45920..3a3cd0a 100644 --- a/classes/incident.php +++ b/classes/incident.php @@ -75,7 +75,7 @@ class Incident implements JsonSerializable } /** - * Processes submitted form and adds incident unless problem is encountered, + * Processes submitted form and adds incident unless problem is encountered, * calling this is possible only for admin or higher rank. Also checks requirements * for char limits. * @return void @@ -129,7 +129,7 @@ class Incident implements JsonSerializable if (!empty($_POST['time']) && $type == 2){ $input_time = (!empty($_POST['time_js'])?$_POST['time_js']: $_POST['time']); $input_end_time = (!empty($_POST['end_time_js'])?$_POST['end_time_js']: $_POST['end_time']); - $time = strtotime($input_time); + $time = strtotime($input_time); $end_time = strtotime($input_end_time); if (!$time) { @@ -152,7 +152,7 @@ class Incident implements JsonSerializable $time = time(); $end_time = ''; } - + $stmt = $mysqli->prepare("INSERT INTO status VALUES (NULL,?, ?, ?, ?, ?, ?)"); $stmt->bind_param("issiii", $type, $title, $text, $time ,$end_time ,$user_id); $stmt->execute(); @@ -160,24 +160,24 @@ class Incident implements JsonSerializable $status_id = $mysqli->insert_id; foreach ($services as $service) { - $stmt = $mysqli->prepare("INSERT INTO services_status VALUES (NULL,?, ?)"); + $stmt = $mysqli->prepare("INSERT INTO services_status VALUES (NULL,?, ?)"); $stmt->bind_param("ii", $service, $status_id); $stmt->execute(); $query = $stmt->get_result(); } - + // Perform notification to subscribers $notify = new Notification(); $notify->populate_impacted_services($status_id); $notify->type = $type; - $notify->time = $time; + $notify->time = $time; $notify->title = $title; $notify->text = $text; $notify->status = $statuses[$type]; - + $notify->notify_subscribers(); - + header("Location: ".WEB_URL."/admin?sent=true"); } } @@ -214,7 +214,7 @@ class Incident implements JsonSerializable echo ''.$value . ' '; } - if (isset($this->end_date)){?> + if (isset($this->end_date)){?> end_date)>time()?_("Ending"):_("Ended");?>:  @@ -234,4 +234,4 @@ class Incident implements JsonSerializable "username" => $this->username ]; } -} +} diff --git a/classes/notification.php b/classes/notification.php index a1332a5..762bbd7 100644 --- a/classes/notification.php +++ b/classes/notification.php @@ -72,7 +72,7 @@ class Notification $queue->template_data1 = $arr_data['subject']; $queue->template_data2 = $arr_data['body']; $task_id_email = $queue->add_task(); - syslog(1, "queue email: ". $task_id_email); + //syslog(1, "queue email: ". $task_id_email); $arr_email = array(); } if ( SUBSCRIBE_TELEGRAM ) { @@ -81,7 +81,7 @@ class Notification $queue->template_data1 = null; $queue->template_data2 = $arr_data['body']; $task_id_telegram = $queue->add_task(); - syslog(1, "queue telegram: ". $task_id_telegram); + //syslog(1, "queue telegram: ". $task_id_telegram); $arr_telegram = array(); } @@ -116,32 +116,6 @@ class Notification $queue->task_id = $task_id_email; $queue->add_notification($arr_email); // Add array of Email users to the notification queue list } - - /* OLD CODE to get user email/telegram data) - Move to queue handler... - while ($subscriber = $query->fetch_assoc()) { - // Fetch list of subscriber details for already found subscriber IDs - $stmt = $mysqli->prepare("SELECT typeID, userID, firstname, token FROM subscribers WHERE subscriberID = ? AND active=1"); - $stmt->bind_param("i", $subscriber['subscriberIDFK']); - $stmt->execute(); - $subscriberQuery = $stmt->get_result(); - - while ($subscriberData = $subscriberQuery->fetch_assoc()) { - $typeID = $subscriberData['typeID']; // Telegram = 1, email = 2 - $userID = $subscriberData['userID']; - $firstname = $subscriberData['firstname']; - $token = $subscriberData['token']; - - // Handle telegram - if ($typeID == 1) { - $this->submit_telegram($userID, $firstname); - } - - // Handle email - if ($typeID == 2) { - $this->submit_email($userID, $token); - } - } - }*/ } /** @@ -163,11 +137,9 @@ class Notification $response = json_decode($json, true); if (!is_array($response) || ! array_key_exists("ok", $response) || $response['ok'] != 1 ) { - syslog(1, "telegram failed: ".$userID); return false; } - syslog(1,"telegram ok: " .$userID); return true; } @@ -181,52 +153,13 @@ class Notification public function submit_queue_email($subscriber, $subject, $msg) { // TODO Error handling - //$Parsedown = new Parsedown(); $mailer = new Mailer(); if ( ! $mailer->send_mail($subscriber, $subject, $msg, true) ) { - syslog(1, "email failed: " .$subscriber); return false; } - syslog(1, "email ok: " .$subscriber); return true; } - // /** - // * Sends email notifications to a subscriber. - // * Function depends on Parsedown and Mailer class being loaded. - // * @param String $userID The email address to send to - // * @param String $uthkey Users token for managing subscription - // * @return void - // */ - // public function submit_email_old($userID, $token) - // { - // // TODO Error handling - // //$Parsedown = new Parsedown(); - // $mailer = new Mailer(); - // - // $str_mail = file_get_contents("../libs/templates/email_status_update.html"); - // $str_mail = str_replace("%name%", NAME, $str_mail); - // // $smtp_mail = str_replace("%email%", $userID, $smtp_mail); - // $str_mail = str_replace("%url%", WEB_URL, $str_mail); - // $str_mail = str_replace("%service%", $this->servicenames, $str_mail); - // $str_mail = str_replace("%status%", $this->status, $str_mail); - // $str_mail = str_replace("%time%", date("c", $this->time), $str_mail); - // $str_mail = str_replace("%comment%", $Parsedown->setBreaksEnabled(true)->text($this->text), $str_mail); - // $str_mail = str_replace("%token%", $token, $str_mail); - // - // $str_mail = str_replace("%service_status_update_from%", _("Service status update from"), $str_mail); - // $str_mail = str_replace("%services_impacted%", _("Service(s) Impacted"), $str_mail); - // $str_mail = str_replace("%status_label%", _("Status"), $str_mail); - // $str_mail = str_replace("%time_label%", _("Time"), $str_mail); - // $str_mail = str_replace("%manage_subscription%", _("Manage subscription"), $str_mail); - // $str_mail = str_replace("%unsubscribe%", _("Unsubscribe"), $str_mail); - // $str_mail = str_replace("%powered_by%", _("Powered by"), $str_mail); - // - // $subject = _('Status update from') . ' - ' . NAME . ' [ ' . $this->status . ' ]'; - // $mailer->send_mail($userID, $subject, $str_mail); - // } - // - public function prepare_email(){ $Parsedown = new Parsedown(); diff --git a/classes/queue.php b/classes/queue.php index 90c119b..9d04ca9 100644 --- a/classes/queue.php +++ b/classes/queue.php @@ -93,7 +93,6 @@ class Queue } $sql = "INSERT INTO queue_notify (task_id, status, subscriber_id, retries) VALUES ". $query; - syslog(1,$sql); $mysqli->query($sql); $this->set_task_status($this->all_status['ready']); // Make task available for release @@ -127,8 +126,7 @@ class Queue $tmp = $stmt2->get_result(); $result2 = $tmp->fetch_assoc(); $typeID = $result2['type_id']; - syslog(1, $typeID . " " . $result['task_id'] . " " . $result['userID']); - + // Handle telegram if ($typeID == 1) { $msg = str_replace("#s", $result['firstname'], $result2['template_data2']); diff --git a/classes/subscriber.php b/classes/subscriber.php index e122070..0fef6fd 100644 --- a/classes/subscriber.php +++ b/classes/subscriber.php @@ -11,14 +11,14 @@ Class Subscriber public $lastname = null; public $userID = ""; // Holds email, telegram id etc public $token = null; - public $active = 0; - public $typeID = null; // Holds subscription type ID - - + public $active = 0; + public $typeID = null; // Holds subscription type ID + + function __construct() { $this->firstname = null; $this->lastname = null; - $this->userID = ""; + $this->userID = ""; $this->token = null; $this->active = 0; $this->typeID = null; @@ -39,12 +39,12 @@ Class Subscriber $result = $stmt->get_result(); if ($result->num_rows > 0) { $row = $result->fetch_assoc(); - $this->token = $row['token']; + $this->token = $row['token']; //$this->get_subscriber_by_token($this->token); return $row['token']; } return false; - + } public function get_subscriber_by_token($token) { @@ -56,12 +56,12 @@ Class Subscriber if ($result->num_rows > 0) { $row = $result->fetch_assoc(); $this->id = $row['subscriberID']; - $this->populate(); // + $this->populate(); // return true; } return false; } - + public function get_subscriber_by_userid($create = false) { global $mysqli; @@ -69,7 +69,7 @@ Class Subscriber $stmt->bind_param("si", $this->userID, $this->typeID ); $stmt->execute(); $result = $stmt->get_result(); - + if ($result->num_rows > 0) { $row = $result->fetch_assoc(); $this->id = $row['subscriberID']; @@ -84,7 +84,7 @@ Class Subscriber return false; } } - + public function populate() { global $mysqli; @@ -111,12 +111,12 @@ Class Subscriber $expireTime = strtotime("+2 hours"); $updateTime = strtotime("now"); $token = $this->generate_token(); - syslog(1,"token". $token); + $stmt = $mysqli->prepare("INSERT INTO subscribers (typeID, userID, firstname, lastname, token, active, expires, create_time) VALUES (?, ?, ?, ?, ?, ?, ?, ?)"); $stmt->bind_param("issssiii", $typeID, $userID, $firstname, $lastname, $token, $active, $expireTime, $updateTime); $stmt->execute(); //$query = $stmt->get_result(); - + $this->id = $mysqli->insert_id; $this->typeID = $typeID; $this->userID = $userID; @@ -126,7 +126,7 @@ Class Subscriber $this->active = $active; return $this->id; } - + public function update($subscriberID) { global $mysqli; @@ -135,49 +135,49 @@ Class Subscriber $stmt->bind_param("ii", $updateTime, $subscriberID); $stmt->execute(); return true; - + } - + public function activate($subscriberID) { - global $mysqli; + global $mysqli; $updateTime = strtotime("now"); - + $stmt = $mysqli->prepare("UPDATE subscribers SET update_time = ?, expires = ? WHERE subscriberID = ?"); $tmp = null; $stmt->bind_param("iii", $updateTime, $tmp, $subscriberID); $stmt->execute(); return true; } - + public function delete($subscriberID) { global $mysqli; - + $stmt = $mysqli->prepare("DELETE FROM services_subscriber WHERE subscriberIDFK = ?"); $stmt->bind_param("i", $subscriberID); $stmt->execute(); //$query = $stmt->get_result(); - + $stmt = $mysqli->prepare("DELETE FROM subscribers WHERE subscriberID = ?"); $stmt->bind_param("i", $subscriberID); $stmt->execute(); //$query = $stmt->get_result(); return true; - + } - + public function check_userid_exist() { global $mysqli; - + $stmt = $mysqli->prepare("SELECT subscriberID, userID, token, active FROM subscribers WHERE typeID=? AND userID=? LIMIT 1"); $stmt->bind_param("is", $this->typeID, $this->userID); $stmt->execute(); $result = $stmt->get_result(); - if($result->num_rows > 0) { + if($result->num_rows > 0) { $row = $result->fetch_assoc(); $this->id = $row['subscriberID']; $this->populate(); @@ -185,33 +185,33 @@ Class Subscriber } return false; } - - public function is_active_subscriber($token) + + public function is_active_subscriber($token) { global $mysqli; - + $stmt = $mysqli->prepare("SELECT subscriberID, token, userID, active, expires FROM subscribers WHERE token LIKE ? LIMIT 1"); $stmt->bind_param("s", $token ); $stmt->execute(); $result = $stmt->get_result(); - if ($result->num_rows > 0) { + if ($result->num_rows > 0) { $row = $result->fetch_assoc(); } else { // No data found, fail gently... - return false; + return false; } - - // If account is not already active, check if we are within timeframe of exipre +2h + + // If account is not already active, check if we are within timeframe of exipre +2h // and active if so, otherwise,delete account and return falsev if ( $row['active'] <> 1 ) { - // Calculate time range for when subscription need to be validated + // Calculate time range for when subscription need to be validated $time_end = $row['expires']; - $time_start = $time_end - (3600*2); // TODO - make this interval configurable via a config option + $time_start = $time_end - (3600*2); // TODO - make this interval configurable via a config option $time_now = time(); - + if ( ($time_now > $time_start) && ($time_now < $time_end) ) { // Timefram is within range, active user.. $stmt2 = $mysqli->prepare("UPDATE subscribers SET active=1, expires=null WHERE subscriberID = ?"); @@ -223,7 +223,7 @@ Class Subscriber $this->userID = $row['userID']; $this->token = $row['token']; return true; - + } else { // Timeframe outside of given scope -> delete account $stmt2 = $mysqli->prepare("DELETE FROM subscribers WHERE subscriberID = ?"); @@ -240,9 +240,9 @@ Class Subscriber $this->id = $row['subscriberID']; $this->userID = $row['userID']; $this->token = $row['token']; - return true; + return true; } - + /** * Generate a new 64 byte token (32 bytes converted from bin2hex = 64 bytes) * @return string token @@ -255,10 +255,10 @@ Class Subscriber $token = openssl_random_pseudo_bytes(32); //Generate a random string. $token = bin2hex($token); //Convert the binary data into hexadecimal representation. } else { - // Use alternative token generator if openssl isn't available... - $token = make_alt_token(32, 32); + // Use alternative token generator if openssl isn't available... + $token = make_alt_token(32, 32); } - + // Make sure token doesn't already exist in db $stmt = $mysqli->prepare("SELECT subscriberID FROM subscribers WHERE token LIKE ?"); echo $mysqli->error; @@ -266,16 +266,16 @@ Class Subscriber $stmt->execute(); $result = $stmt->get_result(); if ($result->num_rows > 0 ) { - // token already exists, call self again - $token = $this->generate_token(); + // token already exists, call self again + $token = $this->generate_token(); } return $token; } - + /** * Alternative token generator if openssl_random_pseudo_bytes is not available - * Original code by jsheets at shadonet dot com from http://php.net/manual/en/function.mt-rand.php + * Original code by jsheets at shadonet dot com from http://php.net/manual/en/function.mt-rand.php * @params int min_length Minimum length of token * @params int max_length Maximum length of token * @return String token @@ -283,31 +283,31 @@ Class Subscriber public function make_alt_token($min_length = 32, $max_length = 64) { $key = ''; - + // build range and shuffle range using ASCII table for ($i=0; $i<=255; $i++) { $range[] = chr($i); } - + // shuffle our range 3 times for ($i=0; $i<=3; $i++) { shuffle($range); } - + // loop for random number generation for ($i = 0; $i < mt_rand($min_length, $max_length); $i++) { $key .= $range[mt_rand(0, count($range)-1)]; } - + $return = bin2hex($key); - + if (!empty($return)) { return $return; } else { return 0; } } - + public function set_logged_in() { $_SESSION['subscriber_valid'] = true; @@ -316,7 +316,7 @@ Class Subscriber $_SESSION['subscriber_typeid'] = $this->typeID; //email $_SESSION['subscriber_token'] = $this->token; } - + public function set_logged_off() { unset($_SESSION['subscriber_valid']); @@ -325,5 +325,5 @@ Class Subscriber unset($_SESSION['subscriber_id']); unset($_SESSION['subscriber_token']); } - -} \ No newline at end of file + +} diff --git a/config.php.template b/config.php.template index a90eced..d9e5c77 100644 --- a/config.php.template +++ b/config.php.template @@ -23,7 +23,7 @@ session_start(); //Start editing here define("NAME", "##name##"); //Website name define("TITLE", "##title##"); -define("WEB_URL", "##url##"); //Used for links +define("WEB_URL", "##url##"); //Used for links define("MAILER_NAME", "##mailer##"); //Mailer name define("MAILER_ADDRESS", "##mailer_email##"); //Mailer address define("POLICY_NAME", "##policy_name##"); //name for contact in policy @@ -34,7 +34,7 @@ define("WHO_WE_ARE","##who_we_are##"); define("POLICY_URL","##policy_url##"); define('SUBSCRIBE_EMAIL', true); define('SUBSCRIBE_TELEGRAM', false); -define("TG_BOT_API_TOKEN", "##tg_bot_token##"); //Telegram Bot Token +define("TG_BOT_API_TOKEN", "##tg_bot_token##"); //Telegram Bot Token define("TG_BOT_USERNAME", "##tg_bot_username##"); //Telegram Bot username define("INSTALL_OVERRIDE", false); define("DEFAULT_LANGUAGE", "en_GB"); @@ -46,11 +46,12 @@ define("PHP_MAILER_PATH", "##phpmailer_path##"); // Path to src folder of PHPMai define("PHP_MAILER_SMTP", false); // Set to true if we are to use SMTP define("PHP_MAILER_HOST", "##phpmailer_host##"); // SMTP host define("PHP_MAILER_PORT", "##phpmailer_port##"); // SMTP Port -define("PHP_MAILER_SECURE", ""); // Set to TLS or SSL or leave blank for plaintext +define("PHP_MAILER_SECURE", ""); // Set to TLS or SSL or leave blank for plaintext define("PHP_MAILER_USER", "##phpmailer_user##"); // SMTP Authentication user define("PHP_MAILER_PASS", "##phpmailer_pass##"); // SMTP authenticatin password define("CUSTOM_LOGO_URL",""); // This will use the default logo if left empty define("COPYRIGHT_TEXT",""); // Leave this empty if you don't want your copyright displayed +define("CRON_SERVER_IP",""); // IP Address that will be used to call cron task. Leave empty if not used! // Without COPYRIGHT_TEXT Set // 2020 Server Status Project Contributors // With COPYRIGHT_TEXT Set @@ -71,7 +72,7 @@ putenv('LANGUAGE='.$_SESSION['locale'].'.UTF-8'); setlocale(LC_ALL, $_SESSION['locale'].".UTF-8"); setlocale(LC_MESSAGES, $_SESSION['locale'].".UTF-8"); bindtextdomain("server-status", __DIR__ . "/locale/"); -bind_textdomain_codeset("server-status", "utf-8"); +bind_textdomain_codeset("server-status", "utf-8"); textdomain("server-status"); //Database connection