From 140062e0b606495f90fd77b8f290987844c79cab Mon Sep 17 00:00:00 2001 From: Simon Rettberg Date: Fri, 29 Apr 2022 17:38:00 +0200 Subject: [locations/remoteaccess] Add option to veto remoteaccess mode Remoteaccess mode can now be forced to be disabled for individual locations in locations module, either unconditionally, or whenever the openingtimes schedule says the room is open. A reboot will be triggered whenever the room opens/closes to force clients into the proper runmode. --- inc/util.inc.php | 14 ++- .../locations/inc/openingtimes.inc.php | 33 +++++- modules-available/locations/pages/details.inc.php | 21 +++- .../locations/templates/ajax-opening-location.html | 29 ++++- .../locations/templates/location-subnets.html | 2 +- .../rebootcontrol/inc/rebootcontrol.inc.php | 1 - .../rebootcontrol/inc/scheduler.inc.php | 131 +++++++++++++-------- .../remoteaccess/baseconfig/getconfig.inc.php | 9 ++ 8 files changed, 179 insertions(+), 61 deletions(-) diff --git a/inc/util.inc.php b/inc/util.inc.php index 81c7d807..c3e70f89 100644 --- a/inc/util.inc.php +++ b/inc/util.inc.php @@ -590,11 +590,23 @@ SADFACE; { $regex = '/ ( - (?: [\x20-\xFF] ){1,100} # ignore lower non-printable range + [\x20-\xFF]{1,100} # ignore lower non-printable range ) | . # anything else /x'; return iconv('MS-ANSI', 'UTF-8', preg_replace($regex, '$1', $string)); } + /** + * Clamp given value into [min, max] range. + */ + public static function clamp(int &$value, int $min, int $max) + { + if ($value < $min) { + $value = $min; + } elseif ($value > $max) { + $value = $max; + } + } + } diff --git a/modules-available/locations/inc/openingtimes.inc.php b/modules-available/locations/inc/openingtimes.inc.php index 72ce92f4..18e25063 100644 --- a/modules-available/locations/inc/openingtimes.inc.php +++ b/modules-available/locations/inc/openingtimes.inc.php @@ -6,11 +6,12 @@ class OpeningTimes /** * Get opening times for given location. * Format is the decoded JSON from DB column, i.e. currently a list of entries: - * { + *
{
 	 * "days": ["Monday", "Tuesday", ...],
 	 * "openingtime": "8:00",
 	 * "closingtime": "20:00"
-	 * }
+	 * }
+ * @return array|null */ public static function forLocation(int $locationId) { @@ -31,4 +32,32 @@ class OpeningTimes return null; } + /** + * Check whether given location is open according to openingtimes. + * @param int $locationId location + * @param int $openOffsetMin offset to apply to opening times when checking. this is subtracted from opening time + * @param int $closeOffsetMin offset to apply to closing times when checking. this is added to closing time + */ + public static function isRoomOpen(int $locationId, int $openOffsetMin = 0, int $closeOffsetMin = 0): bool + { + $openingTimes = self::forLocation($locationId); + if ($openingTimes === null) + return true; // No opening times should mean room is always open + $now = time(); + $today = date('l', $now); + foreach ($openingTimes as $row) { + foreach ($row['days'] as $day) { + if ($day !== $today) + continue; // Not today! + if (strtotime("today {$row['openingtime']} -$openOffsetMin minutes") > $now) + continue; + if (strtotime("today {$row['closingtime']} +$closeOffsetMin minutes") < $now) + continue; + // Bingo! + return true; + } + } + return false; + } + } \ No newline at end of file diff --git a/modules-available/locations/pages/details.inc.php b/modules-available/locations/pages/details.inc.php index 86bfebd6..d2ec7b24 100644 --- a/modules-available/locations/pages/details.inc.php +++ b/modules-available/locations/pages/details.inc.php @@ -39,9 +39,10 @@ class SubPage $openingTimes = Request::post('openingtimes', Request::REQUIRED, 'string'); $locationid = Request::post('locationid', Request::REQUIRED, 'int'); $wol = Request::post('wol', false, 'bool'); - $woloffset = Request::post('wol-offset', 0, 'int'); + $wolOffset = Request::post('wol-offset', 0, 'int'); $sd = Request::post('sd', false, 'bool'); - $sdoffset = Request::post('sd-offset', 0, 'int'); + $sdOffset = Request::post('sd-offset', 0, 'int'); + $raMode = Request::post('ra-mode', 'ALWAYS', 'string'); User::assertPermission('location.edit.openingtimes', $locationid); @@ -93,7 +94,16 @@ class SubPage if (Module::isAvailable('rebootcontrol')) { // Set options - Scheduler::setLocationOptions($locationid, $wol, $sd, $woloffset, $sdoffset); + if (!Scheduler::isValidRaMode($raMode)) { + $raMode = Scheduler::RA_ALWAYS; + } + Scheduler::setLocationOptions($locationid, [ + 'wol' => $wol, + 'sd' => $sd, + 'wol-offset' => $wolOffset, + 'sd-offset' => $sdOffset, + 'ra-mode' => $raMode, + ]); } } @@ -396,7 +406,7 @@ class SubPage if (Module::get('rebootcontrol') !== false) { $res = Database::queryFirst("SELECT action, nextexecution FROM `reboot_scheduler` WHERE locationid = :id", ['id' => $locationId]); - if ($res !== false) { + if ($res !== false && $res['nextexecution'] > 0) { $data['next_action'] = $res['action']; $data['next_time'] = Util::prettyTime($res['nextexecution']); } @@ -431,12 +441,13 @@ class SubPage $data['rebootcontrol'] = $rebootcontrol; if ($rebootcontrol) { $data['scheduler-options'] = Scheduler::getLocationOptions($id); + $data['scheduler_' . $data['scheduler-options']['ra-mode'] . '_checked'] = 'checked'; } echo Render::parse('ajax-opening-location', $data); } - private static function isSimpleMode(&$array) + private static function isSimpleMode(&$array): bool { if (empty($array)) return true; diff --git a/modules-available/locations/templates/ajax-opening-location.html b/modules-available/locations/templates/ajax-opening-location.html index 967e111c..861bef65 100644 --- a/modules-available/locations/templates/ajax-opening-location.html +++ b/modules-available/locations/templates/ajax-opening-location.html @@ -1,5 +1,5 @@
-

{{lang_openingTime}}

+

{{lang_openingTime}}

@@ -129,7 +129,7 @@
{{#rebootcontrol}} -
+

{{lang_automatedMachineActions}}

@@ -164,9 +164,32 @@
+

{{lang_remoteAccessConstraints}}

+
+
+ + +
+
+
+
+ + +
+
+
+
+ + +
+
+

{{lang_remoteAccessHelp}}

{{/rebootcontrol}} -