diff options
Diffstat (limited to 'modules-available/statistics/page.inc.php')
-rw-r--r-- | modules-available/statistics/page.inc.php | 267 |
1 files changed, 161 insertions, 106 deletions
diff --git a/modules-available/statistics/page.inc.php b/modules-available/statistics/page.inc.php index 5fe4ebfa..a9cde6fb 100644 --- a/modules-available/statistics/page.inc.php +++ b/modules-available/statistics/page.inc.php @@ -1,165 +1,177 @@ <?php global $STATS_COLORS, $SIZE_ID44, $SIZE_RAM; -global $unique_key; $STATS_COLORS = array(); for ($i = 0; $i < 10; ++$i) { $STATS_COLORS[] = '#55' . sprintf('%02s%02s', dechex((($i + 1) * ($i + 1)) / .3922), dechex(abs((5 - $i) * 51))); } //$STATS_COLORS = array('#57e', '#ee8', '#5ae', '#fb7', '#6d7', '#e77', '#3af', '#666', '#e0e', '#999'); -$SIZE_ID44 = array(0, 8, 16, 24, 30, 40, 50, 60, 80, 100, 120, 150, 180, 250, 300, 350, 400, 450, 500); +$SIZE_ID44 = array(0, 8, 16, 24, 30, 40, 50, 60, 80, 100, 120, 150, 180, 250, 300, 400, 500, 1000, 2000, 4000); $SIZE_RAM = array(1, 2, 3, 4, 6, 8, 10, 12, 16, 24, 32, 48, 64, 96, 128, 192, 256, 320, 480, 512, 768, 1024); class Page_Statistics extends Page { /* some constants, TODO: Find a better place */ - public static $op_nominal; - public static $op_ordinal; - public static $op_stringcmp; + const OP_NOMINAL = ['!=', '=']; + const OP_ORDINAL = ['!=', '<=', '>=', '=', '<', '>']; + const OP_STRCMP = ['!~', '~', '=', '!=']; public static $columns; private $query; - - private $locationsAllowedToView; + private $show; /** * @var bool whether we have a SubPage from the pages/ subdir */ private $haveSubpage; - /* PHP sucks, no static, const array definitions... Or am I missing something? */ - public function initConstants() + /** + * Do this here instead of const since we need to check for available modules while building array. + */ + public static function initConstants() { - Page_Statistics::$op_nominal = ['!=', '=']; - Page_Statistics::$op_ordinal = ['!=', '<=', '>=', '=', '<', '>']; - Page_Statistics::$op_stringcmp = ['!~', '~', '=', '!=']; Page_Statistics::$columns = [ 'machineuuid' => [ - 'op' => Page_Statistics::$op_nominal, + 'op' => Page_Statistics::OP_NOMINAL, 'type' => 'string', 'column' => true, ], 'macaddr' => [ - 'op' => Page_Statistics::$op_nominal, + 'op' => Page_Statistics::OP_NOMINAL, 'type' => 'string', 'column' => true, ], 'firstseen' => [ - 'op' => Page_Statistics::$op_ordinal, + 'op' => Page_Statistics::OP_ORDINAL, 'type' => 'date', 'column' => true, ], 'lastseen' => [ - 'op' => Page_Statistics::$op_ordinal, + 'op' => Page_Statistics::OP_ORDINAL, 'type' => 'date', 'column' => true, ], 'logintime' => [ - 'op' => Page_Statistics::$op_ordinal, + 'op' => Page_Statistics::OP_ORDINAL, 'type' => 'date', 'column' => true, ], 'realcores' => [ - 'op' => Page_Statistics::$op_ordinal, + 'op' => Page_Statistics::OP_ORDINAL, 'type' => 'int', 'column' => true, ], 'systemmodel' => [ - 'op' => Page_Statistics::$op_stringcmp, + 'op' => Page_Statistics::OP_STRCMP, 'type' => 'string', 'column' => true, ], 'cpumodel' => [ - 'op' => Page_Statistics::$op_stringcmp, + 'op' => Page_Statistics::OP_STRCMP, 'type' => 'string', 'column' => true, ], 'hddgb' => [ - 'op' => Page_Statistics::$op_ordinal, + 'op' => Page_Statistics::OP_ORDINAL, 'type' => 'int', 'column' => false, 'map_sort' => 'id44mb' ], 'gbram' => [ - 'op' => Page_Statistics::$op_ordinal, + 'op' => Page_Statistics::OP_ORDINAL, 'type' => 'int', 'map_sort' => 'mbram', 'column' => false, ], 'kvmstate' => [ - 'op' => Page_Statistics::$op_nominal, + 'op' => Page_Statistics::OP_NOMINAL, 'type' => 'enum', 'column' => true, 'values' => ['ENABLED', 'DISABLED', 'UNSUPPORTED'] ], 'badsectors' => [ - 'op' => Page_Statistics::$op_ordinal, + 'op' => Page_Statistics::OP_ORDINAL, 'type' => 'int', 'column' => true ], 'clientip' => [ - 'op' => Page_Statistics::$op_nominal, + 'op' => Page_Statistics::OP_NOMINAL, 'type' => 'string', 'column' => true ], 'hostname' => [ - 'op' => Page_Statistics::$op_stringcmp, + 'op' => Page_Statistics::OP_STRCMP, 'type' => 'string', 'column' => true ], 'subnet' => [ - 'op' => Page_Statistics::$op_nominal, + 'op' => Page_Statistics::OP_NOMINAL, 'type' => 'string', 'column' => false ], 'currentuser' => [ - 'op' => Page_Statistics::$op_nominal, + 'op' => Page_Statistics::OP_NOMINAL, 'type' => 'string', 'column' => true ], 'state' => [ - 'op' => Page_Statistics::$op_nominal, + 'op' => Page_Statistics::OP_NOMINAL, 'type' => 'enum', 'column' => true, 'values' => ['occupied', 'on', 'off', 'idle', 'standby'] ], - 'runtime' => [ - 'op' => Page_Statistics::$op_ordinal, + 'live_swapfree' => [ + 'op' => Page_Statistics::OP_ORDINAL, + 'type' => 'int', + 'column' => true + ], + 'live_memfree' => [ + 'op' => Page_Statistics::OP_ORDINAL, + 'type' => 'int', + 'column' => true + ], + 'live_tmpfree' => [ + 'op' => Page_Statistics::OP_ORDINAL, 'type' => 'int', 'column' => true ], ]; if (Module::isAvailable('locations')) { Page_Statistics::$columns['location'] = [ - 'op' => Page_Statistics::$op_stringcmp, + 'op' => Page_Statistics::OP_STRCMP, 'type' => 'enum', 'column' => false, 'values' => array_keys(Location::getLocationsAssoc()), ]; } - /* TODO ... */ } protected function doPreprocess() { - $this->initConstants(); User::load(); if (!User::isLoggedIn()) { Message::addError('main.no-permission'); Util::redirect('?do=Main'); } - $this->locationsAllowedToView = User::getAllowedLocations("view"); - - - $show = Request::any('show', 'stat', 'string'); - $show = preg_replace('/[^a-z0-9_\-]/', '', $show); + $this->show = Request::any('show', false, 'string'); + if ($this->show === false) { + if (User::hasPermission('view.summary')) { + $this->show = 'summary'; + } elseif (User::hasPermission('view.list')) { + $this->show = 'list'; + } else { + User::assertPermission('view.summary'); + } + } else { + $this->show = preg_replace('/[^a-z0-9_\-]/', '', $this->show); + } - if (file_exists('modules/statistics/pages/' . $show . '.inc.php')) { + if (file_exists('modules/statistics/pages/' . $this->show . '.inc.php')) { - require_once 'modules/statistics/pages/' . $show . '.inc.php'; + require_once 'modules/statistics/pages/' . $this->show . '.inc.php'; $this->haveSubpage = true; SubPage::doPreprocess(); @@ -168,20 +180,23 @@ class Page_Statistics extends Page $action = Request::post('action'); if ($action === 'setnotes') { $uuid = Request::post('uuid', '', 'string'); - $locationid = Database::queryFirst('SELECT locationid FROM machine WHERE machineuuid = :uuid', - array('uuid' => $uuid))['locationid']; - if (User::hasPermission("note", $locationid)) { - $text = Request::post('content', '', 'string'); - if (empty($text)) { - $text = null; - } - Database::exec('UPDATE machine SET notes = :text WHERE machineuuid = :uuid', array( - 'uuid' => $uuid, - 'text' => $text, - )); - Message::addSuccess('notes-saved'); - Util::redirect('?do=Statistics&uuid=' . $uuid); + $res = Database::queryFirst('SELECT locationid FROM machine WHERE machineuuid = :uuid', + array('uuid' => $uuid)); + if ($res === false) { + Message::addError('unknown-machine', $uuid); + Util::redirect('?do=statistics'); } + User::assertPermission("machine.note.edit", (int)$res['locationid']); + $text = Request::post('content', null, 'string'); + if (empty($text)) { + $text = null; + } + Database::exec('UPDATE machine SET notes = :text WHERE machineuuid = :uuid', array( + 'uuid' => $uuid, + 'text' => $text, + )); + Message::addSuccess('notes-saved'); + Util::redirect('?do=statistics&uuid=' . $uuid); } elseif ($action === 'delmachines') { $this->deleteMachines(); Util::redirect('?do=statistics', true); @@ -204,14 +219,20 @@ class Page_Statistics extends Page Message::addError('main.parameter-empty', 'uuid'); return; } + $allowedLocations = User::getAllowedLocations("machine.delete"); + if (empty($allowedLocations)) { + Message::addError('main.no-permission'); + Util::redirect('?do=statistics'); + } $res = Database::simpleQuery('SELECT machineuuid, locationid FROM machine WHERE machineuuid IN (:ids)', compact('ids')); $ids = array_flip($ids); $delete = []; - $allowedLocations = User::getAllowedLocations("delete"); while ($row = $res->fetch(PDO::FETCH_ASSOC)) { + unset($ids[$row['machineuuid']]); if (in_array($row['locationid'], $allowedLocations)) { - unset($ids[$row['machineuuid']]); $delete[] = $row['machineuuid']; + } else { + Message::addError('locations.no-permission-location', $row['locationid']); } } if (!empty($delete)) { @@ -219,7 +240,6 @@ class Page_Statistics extends Page Message::addSuccess('deleted-n-machines', count($delete)); } if (!empty($ids)) { - // TODO: Warn permissions Message::addWarning('unknown-machine', implode(', ', array_keys($ids))); } } @@ -237,8 +257,6 @@ class Page_Statistics extends Page return; } - $show = Request::get('show', 'stat', 'string'); - /* read filter */ $this->query = Request::any('filters', false); if ($this->query === false) { @@ -251,23 +269,31 @@ class Page_Statistics extends Page $filterSet = new FilterSet($filters); $filterSet->setSort($sortColumn, $sortDirection); - if ($show == 'list') { + if (!$filterSet->setAllowedLocationsFromPermission('view.' . $this->show)) { + Message::addError('main.no-permission'); + Util::redirect('?do=main'); + } + + if ($this->show === 'list') { Render::openTag('div', array('class' => 'row')); $this->showFilter('list', $filterSet); Render::closeTag('div'); $this->showMachineList($filterSet); return; + } elseif ($this->show === 'summary') { + $filterSet->filterNonClients(); + Render::openTag('div', array('class' => 'row')); + $this->showFilter('summary', $filterSet); + $this->showSummary($filterSet); + $this->showMemory($filterSet); + $this->showId44($filterSet); + $this->showKvmState($filterSet); + $this->showLatestMachines($filterSet); + $this->showSystemModels($filterSet); + Render::closeTag('div'); + } else { + Message::addError('main.value-invalid', 'show', $this->show); } - $filterSet->filterNonClients(); - Render::openTag('div', array('class' => 'row')); - $this->showFilter('stat', $filterSet); - $this->showSummary($filterSet); - $this->showMemory($filterSet); - $this->showId44($filterSet); - $this->showKvmState($filterSet); - $this->showLatestMachines($filterSet); - $this->showSystemModels($filterSet); - Render::closeTag('div'); } /** @@ -295,15 +321,17 @@ class Page_Statistics extends Page $locsFlat = array(); if (Module::isAvailable('locations')) { + $allowed = $filterSet->getAllowedLocations(); foreach (Location::getLocations() as $loc) { $locsFlat['L' . $loc['locationid']] = array( 'pad' => $loc['locationpad'], 'name' => $loc['locationname'], - 'disabled' => !in_array($loc['locationid'], $this->locationsAllowedToView) + 'disabled' => $allowed !== false && !in_array($loc['locationid'], $allowed), ); } } + Permission::addGlobalTags($data['perms'], null, ['view.summary', 'view.list']); $data['locations'] = json_encode($locsFlat); Render::addTemplate('filterbox', $data); @@ -355,8 +383,6 @@ class Page_Statistics extends Page private function showSummary($filterSet) { $filterSet->makeFragments($where, $join, $sort, $args); - $args['allowedLocations'] = $this->locationsAllowedToView; - $where = "locationid IN (:allowedLocations) AND ($where)"; $known = Database::queryFirst("SELECT Count(*) AS val FROM machine $join WHERE $where", $args); // If we only have one machine, redirect to machine details if ($known['val'] == 1) { @@ -417,8 +443,6 @@ class Page_Statistics extends Page global $STATS_COLORS; $filterSet->makeFragments($where, $join, $sort, $args); - $args['allowedLocations'] = $this->locationsAllowedToView; - $where = "locationid IN (:allowedLocations) AND ($where)"; $res = Database::simpleQuery('SELECT systemmodel, Round(AVG(realcores)) AS cores, Count(*) AS `count` FROM machine' . " $join WHERE $where GROUP BY systemmodel ORDER BY `count` DESC, systemmodel ASC", $args); $lines = array(); @@ -451,8 +475,6 @@ class Page_Statistics extends Page global $STATS_COLORS, $SIZE_RAM; $filterSet->makeFragments($where, $join, $sort, $args); - $args['allowedLocations'] = $this->locationsAllowedToView; - $where = "locationid IN (:allowedLocations) AND ($where)"; $res = Database::simpleQuery("SELECT mbram, Count(*) AS `count` FROM machine $join WHERE $where GROUP BY mbram", $args); $lines = array(); while ($row = $res->fetch(PDO::FETCH_ASSOC)) { @@ -498,8 +520,6 @@ class Page_Statistics extends Page private function showKvmState($filterSet) { $filterSet->makeFragments($where, $join, $sort, $args); - $args['allowedLocations'] = $this->locationsAllowedToView; - $where = "locationid IN (:allowedLocations) AND ($where)"; $colors = array('UNKNOWN' => '#666', 'UNSUPPORTED' => '#ea5', 'DISABLED' => '#e55', 'ENABLED' => '#6d6'); $res = Database::simpleQuery("SELECT kvmstate, Count(*) AS `count` FROM machine $join WHERE $where GROUP BY kvmstate ORDER BY `count` DESC", $args); $lines = array(); @@ -523,8 +543,6 @@ class Page_Statistics extends Page global $STATS_COLORS, $SIZE_ID44; $filterSet->makeFragments($where, $join, $sort, $args); - $args['allowedLocations'] = $this->locationsAllowedToView; - $where = "locationid IN (:allowedLocations) AND ($where)"; $res = Database::simpleQuery("SELECT id44mb, Count(*) AS `count` FROM machine $join WHERE $where GROUP BY id44mb", $args); $lines = array(); $total = 0; @@ -576,8 +594,6 @@ class Page_Statistics extends Page private function showLatestMachines($filterSet) { $filterSet->makeFragments($where, $join, $sort, $args); - $args['allowedLocations'] = $this->locationsAllowedToView; - $where = "locationid IN (:allowedLocations) AND ($where)"; $args['cutoff'] = ceil(time() / 3600) * 3600 - 86400 * 10; $res = Database::simpleQuery("SELECT machineuuid, clientip, hostname, firstseen, mbram, kvmstate, id44mb FROM machine $join" @@ -611,8 +627,6 @@ class Page_Statistics extends Page { Module::isAvailable('js_stupidtable'); $filterSet->makeFragments($where, $join, $sort, $args); - $args['allowedLocations'] = $this->locationsAllowedToView; - $where = "locationid IN (:allowedLocations) AND ($where)"; $xtra = ''; if ($filterSet->isNoId44Filter()) { $xtra .= ', data'; @@ -629,14 +643,17 @@ class Page_Statistics extends Page . " $join WHERE $where $sort", $args); $rows = array(); $singleMachine = 'none'; - $deleteAllowedLocations = User::getAllowedLocations("delete"); + $deleteAllowedLocations = User::getAllowedLocations("machine.delete"); + $detailsAllowedLocations = User::getAllowedLocations("machine.view-details"); while ($row = $res->fetch(PDO::FETCH_ASSOC)) { if ($singleMachine === 'none') { $singleMachine = $row['machineuuid']; } else { $singleMachine = false; } - $row['deleteAllowed'] = in_array($row['locationid'], $deleteAllowedLocations); + // TODO: This only makes sense as long as there is only one action to perform on selected clients; reboot/shutdown is planned + $row['delete_disabled'] = in_array($row['locationid'], $deleteAllowedLocations) ? '' : 'disabled'; + $row['link_details'] = in_array($row['locationid'], $detailsAllowedLocations); $row['state_' . $row['state']] = true; //$row['firstseen'] = Util::prettyTime($row['firstseen']); $row['lastseen_int'] = $row['lastseen']; @@ -668,12 +685,13 @@ class Page_Statistics extends Page $row['modeName'] = $data['modeName']; } } + $row['locationname'] = Location::getName($row['locationid']); $rows[] = $row; } if ($singleMachine !== false && $singleMachine !== 'none') { Util::redirect('?do=statistics&uuid=' . $singleMachine); } - Render::addTemplate('clientlist', array( + $data = array( 'rowCount' => count($rows), 'rows' => $rows, 'query' => $this->query, @@ -684,7 +702,8 @@ class Page_Statistics extends Page 'showList' => 1, 'show' => 'list', 'redirect' => $_SERVER['QUERY_STRING'] - )); + ); + Render::addTemplate('clientlist', $data); } private function ramColorClass($mb) @@ -755,9 +774,9 @@ class Page_Statistics extends Page $row['currentsession'] = $lecture['displayname']; $row['lectureid'] = $lecture['lectureid']; } + $row['session'] = $row['currentsession']; + return; } - $row['session'] = $row['currentsession']; - return; } $res = Database::simpleQuery('SELECT dateline, username, data FROM statistic' . " WHERE clientip = :ip AND typeid = '.vmchooser-session-name'" @@ -774,23 +793,23 @@ class Page_Statistics extends Page } if ($session !== false) { $row['session'] = $session['data']; - $row['username'] = $session['username']; + if (empty($row['currentuser'])) { + $row['username'] = $session['username']; + } } } private function showMachine($uuid) { - $client = Database::queryFirst('SELECT machineuuid, locationid, macaddr, clientip, firstseen, lastseen, logintime, lastboot, state,' - . ' mbram, kvmstate, cpumodel, id44mb, data, hostname, currentuser, currentsession, notes FROM machine WHERE machineuuid = :uuid', + $client = Database::queryFirst('SELECT machineuuid, locationid, macaddr, clientip, firstseen, lastseen, logintime, lastboot, state, + mbram, live_tmpsize, live_tmpfree, live_swapsize, live_swapfree, live_memsize, live_memfree, + kvmstate, cpumodel, id44mb, data, hostname, currentuser, currentsession, notes FROM machine WHERE machineuuid = :uuid', array('uuid' => $uuid)); if ($client === false) { Message::addError('unknown-machine', $uuid); return; } - if (!in_array($client['locationid'], $this->locationsAllowedToView)) { - Message::addError('main.no-permission'); - return; - } + User::assertPermission('machine.view-details', (int)$client['locationid']); // Hack: Get raw collected data if (Request::get('raw', false)) { Header('Content-Type: text/plain; charset=utf-8'); @@ -820,6 +839,7 @@ class Page_Statistics extends Page $client['state_' . $client['state']] = true; $client['firstseen_s'] = date('d.m.Y H:i', $client['firstseen']); $client['lastseen_s'] = date('d.m.Y H:i', $client['lastseen']); + $client['logintime_s'] = date('d.m.Y H:i', $client['logintime']); if ($client['lastboot'] == 0) { $client['lastboot_s'] = '-'; } else { @@ -829,9 +849,14 @@ class Page_Statistics extends Page $client['lastboot_s'] .= ' (Up ' . floor($uptime / 86400) . 'd ' . gmdate('H:i', $uptime) . ')'; } } - $client['logintime_s'] = date('d.m.Y H:i', $client['logintime']); - $client['gbram'] = round(round($client['mbram'] / 500) / 2, 1); + $client['gbram'] = round(ceil($client['mbram'] / 512) / 2, 1); $client['gbtmp'] = round($client['id44mb'] / 1024); + foreach (['tmp', 'swap', 'mem'] as $item) { + if ($client['live_' . $item . 'size'] == 0) + continue; + $client['live_' . $item . 'percent'] = round(($client['live_' . $item . 'free'] / $client['live_' . $item . 'size']) * 100, 2); + $client['live_' . $item . 'free_s'] = Util::readableFileSize($client['live_' . $item . 'free'], -1, 2); + } $client['ramclass'] = $this->ramColorClass($client['mbram']); $client['kvmclass'] = $this->kvmColorClass($client['kvmstate']); $client['hddclass'] = $this->hddColorClass($client['gbtmp']); @@ -856,7 +881,7 @@ class Page_Statistics extends Page Parser::parsePci($client['lspci1'], $client['lspci2'], $section[2]); } if (isset($hdds['hdds']) && $section[1] === 'smartctl') { - // This currently required that the partition table section comes first... + // This currently requires that the partition table section comes first... Parser::parseSmartctl($hdds['hdds'], $section[2]); } } @@ -891,6 +916,7 @@ class Page_Statistics extends Page $client['screens'][] = $row; } array_multisort($ports, SORT_ASC, $client['screens']); + Permission::addGlobalTags($client['perms'], null, ['hardware.projectors.edit', 'hardware.projectors.view']); // Throw output at user Render::addTemplate('machine-main', $client); // Sessions @@ -899,16 +925,18 @@ class Page_Statistics extends Page //if ($cutoff < $client['firstseen']) $cutoff = $client['firstseen']; $scale = 100 / ($NOW - $cutoff); $res = Database::simpleQuery('SELECT dateline, typeid, data FROM statistic' - . " WHERE dateline > :cutoff AND typeid IN ('~session-length', '~offline-length') AND machineuuid = :uuid ORDER BY dateline ASC", array( + . " WHERE dateline > :cutoff AND typeid IN (:sessionLength, :offlineLength) AND machineuuid = :uuid ORDER BY dateline ASC", array( 'cutoff' => $cutoff - 86400 * 14, 'uuid' => $uuid, + 'sessionLength' => Statistics::SESSION_LENGTH, + 'offlineLength' => Statistics::OFFLINE_LENGTH, )); $spans['rows'] = array(); $spans['graph'] = ''; $last = false; $first = true; while ($row = $res->fetch(PDO::FETCH_ASSOC)) { - if (!$client['isclient'] && $row['typeid'] === '~session-length') + if (!$client['isclient'] && $row['typeid'] === Statistics::SESSION_LENGTH) continue; // Don't differentiate between session and idle for non-clients if ($first && $row['dateline'] > $cutoff && $client['lastboot'] > $cutoff) { // Special case: offline before @@ -934,9 +962,12 @@ class Page_Statistics extends Page } $row['from'] = Util::prettyTime($row['dateline']); $row['duration'] = floor($row['data'] / 86400) . 'd ' . gmdate('H:i', $row['data']); - if ($row['typeid'] === '~offline-length') { + if ($row['typeid'] === Statistics::OFFLINE_LENGTH) { $row['glyph'] = 'off'; $color = '#444'; + } elseif ($row['typeid'] === Statistics::SUSPEND_LENGTH) { + $row['glyph'] = 'pause'; + $color = '#686'; } else { $row['glyph'] = 'user'; $color = '#e77'; @@ -956,8 +987,26 @@ class Page_Statistics extends Page } if ($client['state'] === 'OCCUPIED') { $spans['graph'] .= '<div style="background:#e99;left:' . round(($client['logintime'] - $cutoff) * $scale, 2) . '%;width:' . round(($NOW - $client['logintime'] + 900) * $scale, 2) . '%"> </div>'; + $spans['rows'][] = [ + 'from' => Util::prettyTime($client['logintime']), + 'duration' => '-', + 'glyph' => 'user', + ]; + $row['duration'] = floor($row['data'] / 86400) . 'd ' . gmdate('H:i', $row['data']); } elseif ($client['state'] === 'OFFLINE') { $spans['graph'] .= '<div style="background:#444;left:' . round(($client['lastseen'] - $cutoff) * $scale, 2) . '%;width:' . round(($NOW - $client['lastseen'] + 900) * $scale, 2) . '%"> </div>'; + $spans['rows'][] = [ + 'from' => Util::prettyTime($client['lastseen']), + 'duration' => '-', + 'glyph' => 'off', + ]; + } elseif ($client['state'] === 'STANDBY') { + $spans['graph'] .= '<div style="background:#686;left:' . round(($client['lastseen'] - $cutoff) * $scale, 2) . '%;width:' . round(($NOW - $client['lastseen'] + 900) * $scale, 2) . '%"> </div>'; + $spans['rows'][] = [ + 'from' => Util::prettyTime($client['lastseen']), + 'duration' => '-', + 'glyph' => 'pause', + ]; } $t = explode('-', date('Y-n-j-G', $cutoff)); if ($t[3] >= 8 && $t[3] <= 22) { @@ -1002,8 +1051,10 @@ class Page_Statistics extends Page )); } // Notes - $client["notesAllowed"] = User::hasPermission("note", $client["locationid"]); - Render::addTemplate('machine-notes', $client); + if (User::hasPermission('machine.note.*', (int)$client['locationid'])) { + Permission::addGlobalTags($client['perms'], (int)$client['locationid'], ['machine.note.edit']); + Render::addTemplate('machine-notes', $client); + } } private function eventToIconName($event) @@ -1026,6 +1077,8 @@ class Page_Statistics extends Page protected function doAjax() { + if (!User::load()) + return; $param = Request::any('lookup', false, 'string'); if ($param === false) { die('No lookup given'); @@ -1089,3 +1142,5 @@ class Page_Statistics extends Page ), true); } } + +Page_Statistics::initConstants(); |