Dashboard widget update (#9515)

Implemented in Laravel
Doesn't use legacy PHP session
Several widgets have new features and settings, for example:

- Multiple ports in one graph
- Maps settings are configurable and override system settings but default to system settings
- Graylog stream and/or device selection
- Much improved graph widget selection
- Many more

DO NOT DELETE THIS TEXT

#### Please note

> Please read this information carefully. You can run `./scripts/pre-commit.php` to check your code before submitting.

- [x] Have you followed our [code guidelines?](http://docs.librenms.org/Developing/Code-Guidelines/)

#### Testers

If you would like to test this pull request then please run: `./scripts/github-apply <pr_id>`, i.e `./scripts/github-apply 5926`
After you are done testing, you can remove the changes with `./scripts/github-remove`.  If there are schema changes, you can ask on discord how to revert.
This commit is contained in:
Tony Murray
2018-12-16 15:18:17 -06:00
committed by Neil Lathwood
parent dd695dde53
commit 74882e3950
113 changed files with 5103 additions and 1902 deletions

71
LibreNMS/Util/Colors.php Normal file
View File

@@ -0,0 +1,71 @@
<?php
/**
* Colors.php
*
* -Description-
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* @package LibreNMS
* @link http://librenms.org
* @copyright 2018 Tony Murray
* @author Tony Murray <murraytony@gmail.com>
*/
namespace LibreNMS\Util;
class Colors
{
public static function percentage($percentage, $component_perc_warn = null)
{
$perc_warn = 75;
if (isset($component_perc_warn)) {
$perc_warn = round($component_perc_warn, 0);
}
if ($percentage > $perc_warn) {
return [
'left' => 'c4323f',
'right' => 'c96a73'
];
}
if ($percentage > 75) {
return [
'left' => 'bf5d5b',
'right' => 'd39392'
];
}
if ($percentage > 50) {
return [
'left' => 'bf875b',
'right' => 'd3ae92'
];
}
if ($percentage > 25) {
return [
'left' => '5b93bf',
'right' => '92b7d3'
];
}
return [
'left' => '9abf5b',
'right' => 'bbd392'
];
}
}

84
LibreNMS/Util/Graph.php Normal file
View File

@@ -0,0 +1,84 @@
<?php
/**
* Graph.php
*
* -Description-
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* @package LibreNMS
* @link http://librenms.org
* @copyright 2018 Tony Murray
* @author Tony Murray <murraytony@gmail.com>
*/
namespace LibreNMS\Util;
use App\Models\Device;
use LibreNMS\Config;
class Graph
{
public static function getTypes()
{
return ['device', 'port', 'application', 'munin'];
}
/**
* Get an array of all graph subtypes for the given type
* @param $type
* @param Device $device
* @return array
*/
public static function getSubtypes($type, $device = null)
{
$types = [];
// find the subtypes defined in files
foreach (glob(base_path("/html/includes/graphs/$type/*.inc.php")) as $file) {
$type = basename($file, '.inc.php');
if ($type != 'auth') {
$types[] = $type;
}
}
if ($device != null) {
// find the MIB subtypes
$graphs = $device->graphs();
foreach (Config::get('graph_types') as $type => $type_data) {
foreach (array_keys($type_data) as $subtype) {
if ($graphs->contains($subtype) && self::isMibGraph($type, $subtype)) {
$types[] = $subtype;
}
}
}
}
sort($types);
return $types;
}
/**
* Check if the given graph is a mib graph
*
* @param $type
* @param $subtype
* @return bool
*/
public static function isMibGraph($type, $subtype)
{
return Config::get("graph_types.$type.$subtype.section") == 'mib';
}
}

View File

@@ -25,6 +25,8 @@
namespace LibreNMS\Util; namespace LibreNMS\Util;
use HTMLPurifier;
use HTMLPurifier_Config;
use LibreNMS\Config; use LibreNMS\Config;
class Html class Html
@@ -95,4 +97,58 @@ class Html
return $graph_data; return $graph_data;
} }
public static function percentageBar($width, $height, $percent, $left_text, $left_colour, $left_background, $right_text, $right_colour, $right_background)
{
if ($percent > '100') {
$size_percent = '100';
} else {
$size_percent = $percent;
}
$output = '
<div style="width:'.$width.'px; height:'.$height.'px; position: relative;">
<div class="progress" style="min-width: 2em; background-color:#'.$right_background.'; height:'.$height.'px;margin-bottom:-'.$height.'px;">
<div class="progress-bar" role="progressbar" aria-valuenow="'.$size_percent.'" aria-valuemin="0" aria-valuemax="100" style="min-width: 2em; width:'.$size_percent.'%; background-color: #'.$left_background.';">
</div>
</div>
<b style="padding-left: 2%; position: absolute; top: 0; left: 0;color:#'.$left_colour.';">'.$left_text.'</b>
<b style="padding-right: 2%; position: absolute; top: 0; right: 0;color:#'.$right_colour.';">'.$right_text.'</b>
</div>
';
return $output;
}
/**
* Clean a string for display in an html page.
*
* @param $value
* @param array $purifier_config (key, value pair)
* @return string
*/
public static function display($value, $purifier_config = [])
{
/** @var HTMLPurifier $purifier */
static $purifier;
// If $purifier_config is non-empty then we don't want
// to convert html tags and allow these to be controlled
// by purifier instead.
if (empty($purifier_config)) {
$value = htmlentities($value);
}
if (!isset($purifier)) {
// initialize HTML Purifier here since this is the only user
$p_config = HTMLPurifier_Config::createDefault();
$p_config->set('Cache.SerializerPath', Config::get('temp_dir', '/tmp'));
foreach ($purifier_config as $k => $v) {
$p_config->set($k, $v);
}
$purifier = new HTMLPurifier($p_config);
}
return $purifier->purify(stripslashes($value));
}
} }

View File

@@ -103,6 +103,7 @@ class Rewrite
'serviceinstance' => 'SI', 'serviceinstance' => 'SI',
'dwdm' => 'DWDM', 'dwdm' => 'DWDM',
'bundle-ether' => 'BE', 'bundle-ether' => 'BE',
'bridge-aggregation' => 'BA',
]; ];
return str_ireplace(array_keys($rewrite_shortif), array_values($rewrite_shortif), $name); return str_ireplace(array_keys($rewrite_shortif), array_values($rewrite_shortif), $name);

View File

@@ -0,0 +1,81 @@
<?php
/**
* Text.php
*
* -Description-
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* @package LibreNMS
* @link http://librenms.org
* @copyright 2018 Tony Murray
* @author Tony Murray <murraytony@gmail.com>
*/
namespace LibreNMS\Util;
class StringHelpers
{
/**
* Shorten text over 50 chars, if shortened, add ellipsis
*
* @param $string
* @param int $max
* @return string
*/
public static function shortenText($string, $max = 30)
{
if (strlen($string) > 50) {
return substr($string, 0, $max) . "...";
}
return $string;
}
public static function niceCase($string)
{
$replacements = [
'dbm' => 'dBm',
'entropy' => 'Random entropy',
'mysql' => 'MySQL',
'powerdns' => 'PowerDNS',
'bind' => 'BIND',
'nfs-stats' => 'NFS Stats',
'nfs-v3-stats' => 'NFS v3 Stats',
'nfs-server' => 'NFS Server',
'ntp' => 'NTP',
'ntp-client' => 'NTP Client',
'ntp-server' => 'NTP Server',
'os-updates' => 'OS Updates',
'smart' => 'SMART',
'powerdns-recursor' => 'PowerDNS Recursor',
'powerdns-dnsdist' => 'PowerDNS dnsdist',
'dhcp-stats' => 'DHCP Stats',
'ups-nut' => 'UPS nut',
'ups-apcups' => 'UPS apcups',
'gpsd' => 'GPSD',
'exim-stats' => 'EXIM Stats',
'fbsd-nfs-client' => 'FreeBSD NFS Client',
'fbsd-nfs-server' => 'FreeBSD NFS Server',
'php-fpm' => 'PHP-FPM',
'opengridscheduler' => 'Open Grid Scheduler',
'sdfsinfo' => 'SDFS info',
'freeradius' => 'FreeRADIUS',
'pi-hole' => 'pi-hole',
'zfs' => 'ZFS',
];
return isset($replacements[$string]) ? $replacements[$string] : ucfirst($string);
}
}

51
LibreNMS/Util/Time.php Normal file
View File

@@ -0,0 +1,51 @@
<?php
/**
* Time.php
*
* -Description-
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* @package LibreNMS
* @link http://librenms.org
* @copyright 2018 Tony Murray
* @author Tony Murray <murraytony@gmail.com>
*/
namespace LibreNMS\Util;
class Time
{
public static function legacyTimeSpecToSecs($description)
{
$conversion = [
'now' => 0,
'onehour' => 3600,
'fourhour' => 14400,
'sixhour' => 21600,
'twelvehour' => 43200,
'day' => 86400,
'twoday' => 172800,
'week' => 604800,
'twoweek' => 1209600,
'month' => 2678400,
'twomonth' => 5356800,
'threemonth' => 8035200,
'year' => 31536000,
'twoyear' => 63072000,
];
return isset($conversion[$description]) ? $conversion[$description] : 0;
}
}

View File

@@ -102,8 +102,7 @@ class Url
if ($overlib == 0) { if ($overlib == 0) {
$link = $contents; $link = $contents;
} else { } else {
// escape quotes $contents = self::escapeBothQuotes($contents);
$contents = str_replace(["'", '"'], "\'", $contents);
$link = Url::overlibLink($url, $text, $contents, $class); $link = Url::overlibLink($url, $text, $contents, $class);
} }
@@ -177,6 +176,33 @@ class Url
return self::generate(['page' => 'device', 'device' => $port->device_id, 'tab' => 'port', 'port' => $port->port_id], $vars); return self::generate(['page' => 'device', 'device' => $port->device_id, 'tab' => 'port', 'port' => $port->port_id], $vars);
} }
/**
* @param Port $port
* @return string
*/
public static function portThumbnail($port)
{
$graph_array = [
'port_id' => $port->port_id,
'graph_type' => 'port_bits',
'from' => Carbon::now()->subDay()->timestamp,
'to' => Carbon::now()->timestamp,
'width' => 150,
'height' => 21,
];
return self::portImage($graph_array);
}
public static function portImage($args)
{
if (empty($args['bg'])) {
$args['bg'] = 'FFFFFF00';
}
return "<img src='graph.php?type=" . $args['graph_type'] . '&amp;id=' . $args['port_id'] . '&amp;from=' . $args['from'] . '&amp;to=' . $args['to'] . '&amp;width=' . $args['width'] . '&amp;height=' . $args['height'] . '&amp;bg=' . $args['bg'] . "'>";
}
public static function generate($vars, $new_vars = []) public static function generate($vars, $new_vars = [])
{ {
$vars = array_merge($vars, $new_vars); $vars = array_merge($vars, $new_vars);
@@ -245,6 +271,22 @@ class Url
return $output; return $output;
} }
public static function overlibContent($graph_array, $text)
{
$overlib_content = '<div class=overlib><span class=overlib-text>' . $text . '</span><br />';
$now = Carbon::now();
foreach ([1, 7, 30, 365] as $days) {
$graph_array['from'] = $now->subDays($days)->timestamp;
$overlib_content .= self::escapeBothQuotes(self::graphTag($graph_array));
}
$overlib_content .= '</div>';
return $overlib_content;
}
/** /**
* Generate minigraph image url * Generate minigraph image url
* *
@@ -321,4 +363,9 @@ class Url
return "interface-upup"; return "interface-upup";
} }
private static function escapeBothQuotes($string)
{
return str_replace(["'", '"'], "\'", $string);
}
} }

View File

@@ -0,0 +1,145 @@
<?php
/**
* GraylogApi.php
*
* -Description-
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* @package LibreNMS
* @link http://librenms.org
* @copyright 2018 Tony Murray
* @author Tony Murray <murraytony@gmail.com>
*/
namespace App\ApiClients;
use App\Models\Device;
use GuzzleHttp\Client;
use LibreNMS\Config;
class GraylogApi
{
private $client;
private $api_prefix = '';
public function __construct(array $config = [])
{
if (version_compare(Config::get('graylog.version', '2.4'), '2.1', '>=')) {
$this->api_prefix = '/api';
}
if (empty($config)) {
$base_uri = Config::get('graylog.server');
if ($port = Config::get('graylog.port')) {
$base_uri .= ':' . $port;
}
$config = [
'base_uri' => $base_uri,
'auth' => [Config::get('graylog.username'), Config::get('graylog.password')],
'headers' => ['Accept' => 'application/json'],
];
}
$this->client = new Client($config);
}
public function getStreams()
{
if (!$this->isConfigured()) {
return [];
}
$uri = $this->api_prefix . '/streams';
$response = $this->client->get($uri);
$data = json_decode($response->getBody(), true);
return $data ?: [];
}
/**
* Query the Graylog server
*
* @param string $query
* @param int $range
* @param int $limit
* @param int $offset
* @param string $sort field:asc or field:desc
* @param string $filter
* @return array
*/
public function query($query = '*', $range = 0, $limit = 0, $offset = 0, $sort = null, $filter = null)
{
if (!$this->isConfigured()) {
return [];
}
$uri = Config::get('graylog.base_uri');
if (!$uri) {
$uri = $this->api_prefix . '/search/universal/relative';
}
$data = [
'query' => $query,
'range' => $range,
'limit' => $limit,
'offset' => $offset,
'sort' => $sort,
'filter' => $filter,
];
$response = $this->client->get($uri, ['query' => $data]);
$data = json_decode($response->getBody(), true);
return $data ?: [];
}
/**
* Build a simple query string that searches the messages field and/or filters by device
*
* @param string $search Search the message field for this string
* @param Device $device
* @return string
*/
public function buildSimpleQuery($search = null, $device = null)
{
$query = [];
if ($search) {
$query[] = 'message:"' . $search . '"';
}
if ($device) {
$ip = gethostbyname($device->hostname);
$device_query = 'source:"' . $device->hostname . '" || source:"' . $ip . '"';
if ($device->ip && $ip != $device->ip) {
$query .= ' || source:"' . $device->ip . '"';
}
$query[] = '(' . $device_query . ')';
}
if (empty($query)) {
return '*';
}
return implode('&&', $query);
}
public function isConfigured()
{
return isset($this->client->getConfig()['base_uri']);
}
}

View File

@@ -0,0 +1,61 @@
<?php
/**
* WidgetSettingsController.php
*
* -Description-
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* @package LibreNMS
* @link http://librenms.org
* @copyright 2018 Tony Murray
* @author Tony Murray <murraytony@gmail.com>
*/
namespace App\Http\Controllers\Form;
use App\Http\Controllers\Controller;
use App\Models\UserWidget;
use Illuminate\Http\Request;
class WidgetSettingsController extends Controller
{
public function update(Request $request, $widget_settings)
{
$this->validate($request, ['settings' => 'array']);
$widget = UserWidget::with('dashboard')->findOrFail($widget_settings);
$widget_settings = (array)$request->get('settings', []);
if (!$widget->dashboard->canWrite($request->user())) {
return response()->json([
'status' => 'error',
'message' => 'ERROR: You have no write-access to this dashboard'
]);
}
$widget->settings = $widget_settings;
if ($widget->save()) {
return response()->json([
'status' => 'ok',
'message' => 'Updated widget settings'
]);
}
return response()->json([
'status' => 'error',
'message' => 'ERROR: Could not update'
]);
}
}

View File

@@ -46,7 +46,7 @@ abstract class PaginatedAjaxController extends Controller
* @param \Illuminate\Http\Request $request * @param \Illuminate\Http\Request $request
* @return \Illuminate\Database\Eloquent\Builder|\Illuminate\Database\Query\Builder * @return \Illuminate\Database\Eloquent\Builder|\Illuminate\Database\Query\Builder
*/ */
abstract public function baseQuery($request); abstract protected function baseQuery($request);
/** /**
* @param Paginator $paginator * @param Paginator $paginator
@@ -59,7 +59,7 @@ abstract class PaginatedAjaxController extends Controller
* *
* @return array * @return array
*/ */
public function rules() protected function rules()
{ {
return []; return [];
} }
@@ -71,7 +71,7 @@ abstract class PaginatedAjaxController extends Controller
* @return array * @return array
* @SuppressWarnings(PHPMD.UnusedFormalParameter) * @SuppressWarnings(PHPMD.UnusedFormalParameter)
*/ */
public function searchFields($request) protected function searchFields($request)
{ {
return []; return [];
} }
@@ -82,7 +82,7 @@ abstract class PaginatedAjaxController extends Controller
* @param Model $model * @param Model $model
* @return array|Collection|Model * @return array|Collection|Model
*/ */
public function formatItem($model) protected function formatItem($model)
{ {
return $model; return $model;
} }

View File

@@ -0,0 +1,65 @@
<?php
/**
* ApplicationController.php
*
* -Description-
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* @package LibreNMS
* @link http://librenms.org
* @copyright 2018 Tony Murray
* @author Tony Murray <murraytony@gmail.com>
*/
namespace App\Http\Controllers\Select;
use App\Models\Application;
class ApplicationController extends SelectController
{
protected function rules()
{
return [
'type' => 'nullable|string',
];
}
/**
* Defines the base query for this resource
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Database\Eloquent\Builder|\Illuminate\Database\Query\Builder
*/
protected function baseQuery($request)
{
$query = Application::hasAccess($request->user())->with(['device' => function ($query) {
$query->select('device_id', 'hostname', 'sysName');
}]);
if ($type = $request->get('type')) {
$query->where('app_type', $type);
}
return $query;
}
public function formatItem($app)
{
return [
'id' => $app->app_id,
'text' => $app->displayName() . ' - ' . $app->device->displayName(),
];
}
}

View File

@@ -0,0 +1,48 @@
<?php
/**
* BillController.php
*
* -Description-
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* @package LibreNMS
* @link http://librenms.org
* @copyright 2018 Tony Murray
* @author Tony Murray <murraytony@gmail.com>
*/
namespace App\Http\Controllers\Select;
use App\Models\Bill;
class BillController extends SelectController
{
protected function searchFields($request)
{
return ['bill_name', 'bill_notes'];
}
/**
* Defines the base query for this resource
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Database\Eloquent\Builder|\Illuminate\Database\Query\Builder
*/
protected function baseQuery($request)
{
return Bill::hasAccess($request->user())
->select('bill_id', 'bill_name');
}
}

View File

@@ -29,13 +29,24 @@ use App\Models\Device;
class DeviceController extends SelectController class DeviceController extends SelectController
{ {
public function searchFields($request) private $id = 'device_id';
protected function rules()
{
return [
'id' => 'nullable|in:device_id,hostname'
];
}
protected function searchFields($request)
{ {
return ['hostname', 'sysName']; return ['hostname', 'sysName'];
} }
public function baseQuery($request) protected function baseQuery($request)
{ {
$this->id = $request->get('id', 'device_id');
return Device::hasAccess($request->user())->select('device_id', 'hostname', 'sysName'); return Device::hasAccess($request->user())->select('device_id', 'hostname', 'sysName');
} }
@@ -43,7 +54,7 @@ class DeviceController extends SelectController
{ {
/** @var Device $device */ /** @var Device $device */
return [ return [
'id' => $device->device_id, 'id' => $device->{$this->id},
'text' => $device->displayName(), 'text' => $device->displayName(),
]; ];
} }

View File

@@ -0,0 +1,49 @@
<?php
/**
* DeviceGroupController.php
*
* -Description-
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* @package LibreNMS
* @link http://librenms.org
* @copyright 2018 Tony Murray
* @author Tony Murray <murraytony@gmail.com>
*/
namespace App\Http\Controllers\Select;
use App\Models\DeviceGroup;
class DeviceGroupController extends SelectController
{
protected function searchFields($request)
{
return ['name'];
}
protected function baseQuery($request)
{
return DeviceGroup::hasAccess($request->user())->select('id', 'name');
}
public function formatItem($device_group)
{
return [
'id' => $device_group->id,
'text' => $device_group->name,
];
}
}

View File

@@ -34,7 +34,7 @@ class EventlogController extends SelectController
* *
* @return array * @return array
*/ */
public function rules() protected function rules()
{ {
return [ return [
'field' => 'required|in:type', 'field' => 'required|in:type',
@@ -48,7 +48,7 @@ class EventlogController extends SelectController
* @param \Illuminate\Http\Request $request * @param \Illuminate\Http\Request $request
* @return array * @return array
*/ */
public function searchFields($request) protected function searchFields($request)
{ {
return [$request->get('field')]; return [$request->get('field')];
} }
@@ -59,7 +59,7 @@ class EventlogController extends SelectController
* @param \Illuminate\Http\Request $request * @param \Illuminate\Http\Request $request
* @return \Illuminate\Database\Eloquent\Builder|\Illuminate\Database\Query\Builder * @return \Illuminate\Database\Eloquent\Builder|\Illuminate\Database\Query\Builder
*/ */
public function baseQuery($request) protected function baseQuery($request)
{ {
/** @var \Illuminate\Database\Eloquent\Builder $query */ /** @var \Illuminate\Database\Eloquent\Builder $query */
$query = Eventlog::hasAccess($request->user()) $query = Eventlog::hasAccess($request->user())

View File

@@ -0,0 +1,74 @@
<?php
/**
* GraphAggregateController.php
*
* -Description-
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* @package LibreNMS
* @link http://librenms.org
* @copyright 2018 Tony Murray
* @author Tony Murray <murraytony@gmail.com>
*/
namespace App\Http\Controllers\Select;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use LibreNMS\Config;
class GraphAggregateController extends Controller
{
private $rules = [
'limit' => 'int',
'page' => 'int',
'term' => 'nullable|string',
];
public function __invoke(Request $request)
{
$this->validate($request, $this->rules);
$types = [
'transit',
'peering',
'core',
];
foreach ((array)Config::get('custom_descr', []) as $custom) {
if ($custom) {
$types[] = $custom;
}
}
// handle search
if ($search = strtolower($request->get('term'))) {
$types = array_filter($types, function ($type) use ($search) {
return !str_contains(strtolower($type), $search);
});
}
// format results
return response()->json([
'results' => array_map(function ($type) {
return [
'id' => $type,
'text' => ucwords($type),
];
}, $types),
'pagination' => ['more' => false]
]);
}
}

View File

@@ -0,0 +1,152 @@
<?php
/**
* GraphController.php
*
* -Description-
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* @package LibreNMS
* @link http://librenms.org
* @copyright 2018 Tony Murray
* @author Tony Murray <murraytony@gmail.com>
*/
namespace App\Http\Controllers\Select;
use App\Http\Controllers\Controller;
use App\Models\Device;
use Illuminate\Http\Request;
use Illuminate\Support\Collection;
use LibreNMS\Util\Graph;
use LibreNMS\Util\StringHelpers;
class GraphController extends Controller
{
private $rules = [
'limit' => 'int',
'page' => 'int',
'term' => 'nullable|string',
'device' => 'nullable|int',
];
public function __invoke(Request $request)
{
$this->validate($request, $this->rules);
$data = [];
$search = $request->get('term');
$device_id = $request->get('device');
$device = $device_id ? Device::find($device_id) : null;
foreach (Graph::getTypes() as $type) {
$graphs = $this->filterTypeGraphs(collect(Graph::getSubtypes($type, $device)), $type, $search);
if ($graphs->isNotEmpty()) {
$data[] = [
'text' => StringHelpers::niceCase($type),
'children' => $graphs->map(function ($graph) use ($type) {
return $this->formatGraph($type, $graph);
})->values()
];
}
}
$aggregators = $this->filterTypeGraphs(collect([
'transit' => 'Transit',
'peering' => 'Peering',
'core' => 'Core',
'custom' => 'Custom',
'ports' => 'Manual Ports'
]), 'aggregators', $search);
if ($aggregators->isNotEmpty()) {
$data[] = [
'text' => 'Aggregators',
'children' => $aggregators->map(function ($text, $id) {
return compact('id', 'text');
})->values()
];
}
$billing = $this->filterTypeGraphs(collect([
'bill_bits' => 'Bill Bits'
]), 'bill', $search);
if ($billing->isNotEmpty()) {
$data[] = [
'text' => 'Bill',
'children' => $billing->map(function ($text, $id) {
return compact('id', 'text');
})->values()
];
}
return response()->json([
'results' => $data,
'pagination' => ['more' => false]
]);
}
private function formatGraph($top, $graph)
{
$text = $graph;
if (str_contains('_', $graph)) {
list($type, $subtype) = explode('_', $graph, 2);
} else {
$type = $graph;
$subtype = '';
}
if (!Graph::isMibGraph($type, $subtype)) {
$text = ucwords($top . ' ' . str_replace(['_', '-'], ' ', $text));
}
return [
'id' => $top . '_' . $graph,
'text' => $text,
];
}
/**
* @param Collection $graphs
* @param string $type
* @param string $search
* @return Collection
*/
private function filterTypeGraphs($graphs, $type, $search)
{
$search = strtolower($search);
if ($search) {
$terms = preg_split('/[ _-]/', $search, 2);
$first = array_shift($terms);
if (str_contains($type, $first)) {
// search matches type, show all unless there are more terms.
if (!empty($terms)) {
$sub_search = array_shift($terms);
$graphs = $graphs->filter(function ($graph) use ($sub_search) {
return str_contains(strtolower($graph), $sub_search);
});
}
} else {
// if the type matches, don't filter the sub values
$graphs = $graphs->filter(function ($graph) use ($search) {
return str_contains(strtolower($graph), $search);
});
}
}
return $graphs;
}
}

View File

@@ -0,0 +1,71 @@
<?php
/**
* GraylogStreamsController.php
*
* Select for the available streams from the graylog server.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* @package LibreNMS
* @link http://librenms.org
* @copyright 2018 Tony Murray
* @author Tony Murray <murraytony@gmail.com>
*/
namespace App\Http\Controllers\Select;
use App\ApiClients\GraylogApi;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Log;
class GraylogStreamsController extends Controller
{
/**
* The default method called by the route handler
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\JsonResponse
*/
public function __invoke(Request $request, GraylogApi $api)
{
$this->validate($request, [
'limit' => 'int',
'page' => 'int',
'term' => 'nullable|string',
]);
$search = strtolower($request->get('term'));
$streams = [];
try {
$streams = collect($api->getStreams()['streams'])->filter(function ($stream) use ($search) {
return !$search || str_contains(strtolower($stream['title']), $search) || str_contains(strtolower($stream['description']), $search);
})->map(function ($stream) {
$text = $stream['title'];
if ($stream['description']) {
$text .= " ({$stream['description']})";
}
return ['id' => $stream['id'], 'text' => $text];
});
} catch (\Exception $e) {
Log::error($e->getMessage(), ['file' => $e->getFile(), 'line' => $e->getLine()]);
}
return response()->json([
'results' => $streams,
'pagination' => ['more' => false]
]);
}
}

View File

@@ -0,0 +1,55 @@
<?php
/**
* MuninPluginController.php
*
* -Description-
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* @package LibreNMS
* @link http://librenms.org
* @copyright 2018 Tony Murray
* @author Tony Murray <murraytony@gmail.com>
*/
namespace App\Http\Controllers\Select;
use App\Models\MuninPlugin;
class MuninPluginController extends SelectController
{
/**
* Defines the base query for this resource
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Database\Eloquent\Builder|\Illuminate\Database\Query\Builder
*/
protected function baseQuery($request)
{
return MuninPlugin::hasAccess($request->user())
->with(['device' => function ($query) {
$query->select('device_id', 'hostname', 'sysName');
}])
->select('mplug_id', 'mplug_type');
}
public function formatItem($munin_plugin)
{
return [
'id' => $munin_plugin->mplug_id,
'text' => $munin_plugin->device->shortDisplayName() . ' - ' . $munin_plugin->mplug_type
];
}
}

View File

@@ -0,0 +1,94 @@
<?php
/**
* PortController.php
*
* -Description-
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* @package LibreNMS
* @link http://librenms.org
* @copyright 2018 Tony Murray
* @author Tony Murray <murraytony@gmail.com>
*/
namespace App\Http\Controllers\Select;
use App\Models\Port;
class PortController extends SelectController
{
/**
* Defines validation rules (will override base validation rules for select2 responses too)
*
* @return array
*/
protected function rules()
{
return [
'device' => 'nullable|int',
];
}
/**
* Defines search fields will be searched in order
*
* @param \Illuminate\Http\Request $request
* @return array
*/
protected function searchFields($request)
{
return (array)$request->get('field', ['ifAlias', 'ifName', 'ifDescr', 'devices.hostname', 'devices.sysName']);
}
/**
* Defines the base query for this resource
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Database\Eloquent\Builder|\Illuminate\Database\Query\Builder
*/
protected function baseQuery($request)
{
/** @var \Illuminate\Database\Eloquent\Builder $query */
$query = Port::hasAccess($request->user())
->with(['device' => function ($query) {
$query->select('device_id', 'hostname', 'sysName');
}])
->select('ports.device_id', 'port_id', 'ifAlias', 'ifName', 'ifDescr')
->groupBy(['ports.device_id', 'port_id', 'ifAlias', 'ifName', 'ifDescr']);
if ($request->get('term')) {
// join with devices for searches
$query->leftJoin('devices', 'devices.device_id', 'ports.device_id');
}
if ($device_id = $request->get('device')) {
$query->where('ports.device_id', $device_id);
}
return $query;
}
public function formatItem($port)
{
/** @var Port $port */
$label = $port->getShortLabel();
$description = ($label == $port->ifAlias ? '' : ' - ' . $port->ifAlias);
return [
'id' => $port->port_id,
'text' => $label . ' - ' . $port->device->shortDisplayName() . $description,
];
}
}

View File

@@ -0,0 +1,74 @@
<?php
/**
* PortFieldController.php
*
* -Description-
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* @package LibreNMS
* @link http://librenms.org
* @copyright 2018 Tony Murray
* @author Tony Murray <murraytony@gmail.com>
*/
namespace App\Http\Controllers\Select;
use App\Models\Port;
class PortFieldController extends SelectController
{
/**
* Defines validation rules (will override base validation rules for select2 responses too)
*
* @return array
*/
protected function rules()
{
return [
'field' => 'required|in:ifType',
'device' => 'nullable|int',
];
}
/**
* Defines search fields will be searched in order
*
* @param \Illuminate\Http\Request $request
* @return array
*/
protected function searchFields($request)
{
return [$request->get('field')];
}
/**
* Defines the base query for this resource
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Database\Eloquent\Builder|\Illuminate\Database\Query\Builder
*/
protected function baseQuery($request)
{
/** @var \Illuminate\Database\Eloquent\Builder $query */
$query = Port::hasAccess($request->user())
->select($request->get('field'))->distinct();
if ($device_id = $request->get('device')) {
$query->where('ports.device_id', $device_id);
}
return $query;
}
}

View File

@@ -50,7 +50,7 @@ abstract class SelectController extends PaginatedAjaxController
public function __invoke(Request $request) public function __invoke(Request $request)
{ {
$this->validate($request, $this->rules()); $this->validate($request, $this->rules());
$limit = $request->get('limit', 20); $limit = $request->get('limit', 50);
$query = $this->search($request->get('term'), $this->baseQuery($request), $this->searchFields($request)); $query = $this->search($request->get('term'), $this->baseQuery($request), $this->searchFields($request));
$paginator = $query->simplePaginate($limit); $paginator = $query->simplePaginate($limit);

View File

@@ -32,7 +32,7 @@ class SyslogController extends SelectController
* *
* @return array * @return array
*/ */
public function rules() protected function rules()
{ {
return [ return [
'field' => 'required|in:program,priority', 'field' => 'required|in:program,priority',
@@ -46,7 +46,7 @@ class SyslogController extends SelectController
* @param \Illuminate\Http\Request $request * @param \Illuminate\Http\Request $request
* @return array * @return array
*/ */
public function searchFields($request) protected function searchFields($request)
{ {
return [$request->get('field')]; return [$request->get('field')];
} }
@@ -57,7 +57,7 @@ class SyslogController extends SelectController
* @param \Illuminate\Http\Request $request * @param \Illuminate\Http\Request $request
* @return \Illuminate\Database\Eloquent\Builder|\Illuminate\Database\Query\Builder * @return \Illuminate\Database\Eloquent\Builder|\Illuminate\Database\Query\Builder
*/ */
public function baseQuery($request) protected function baseQuery($request)
{ {
/** @var \Illuminate\Database\Eloquent\Builder $query */ /** @var \Illuminate\Database\Eloquent\Builder $query */
$query = \App\Models\Syslog::hasAccess($request->user()) $query = \App\Models\Syslog::hasAccess($request->user())

View File

@@ -0,0 +1,134 @@
<?php
/**
* GraylogController.php
*
* -Description-
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* @package LibreNMS
* @link http://librenms.org
* @copyright 2018 Tony Murray
* @author Tony Murray <murraytony@gmail.com>
*/
namespace App\Http\Controllers\Table;
use App\ApiClients\GraylogApi;
use App\Models\Device;
use DateInterval;
use DateTime;
use DateTimeZone;
use Illuminate\Http\Request;
use LibreNMS\Config;
use LibreNMS\Util\Url;
class GraylogController extends SimpleTableController
{
private $timezone;
public function __construct()
{
$timezone = Config::get('graylog.timezone');
$this->timezone = $timezone ? new DateTimeZone($timezone) : null;
}
public function __invoke(Request $request, GraylogApi $api)
{
if (!$api->isConfigured()) {
return response()->json([
'error' => 'Graylog is not configured',
], 503);
}
$this->validate($request, [
'stream' => 'nullable|alpha_num',
'device' => 'nullable|int',
'range' => 'nullable|int',
]);
$search = $request->get('searchPhrase');
$device_id = $request->get('device');
$device = $device_id ? Device::find($device_id) : null;
$range = $request->get('range', 0) ;
$limit = $request->get('rowCount', 10);
$page = $request->get('current', 1);
$offset = ($page - 1) * $limit;
$query = $api->buildSimpleQuery($search, $device);
$sort = null;
foreach ($request->get('sort', []) as $field => $direction) {
$sort = "$field:$direction";
}
$stream = $request->get('stream');
$filter = $stream ? "streams:$stream" : null;
try {
$data = $api->query($query, $range, $limit, $offset, $sort, $filter);
return $this->formatResponse(
array_map([$this, 'formatMessage'], $data['messages']),
$page,
count($data['messages']),
$data['total_results']
);
} catch (\Exception $se) {
$error = $se->getMessage();
}
return response()->json([
'error' => $error,
], 500);
}
private function formatMessage($message)
{
if ($this->timezone) {
$graylogTime = new DateTime($message['message']['timestamp']);
$offset = $this->timezone->getOffset($graylogTime);
$timeInterval = DateInterval::createFromDateString((string)$offset . 'seconds');
$graylogTime->add($timeInterval);
$displayTime = $graylogTime->format('Y-m-d H:i:s');
} else {
$displayTime = $message['message']['timestamp'];
}
return [
'severity' => $this->severityLabel($message['message']['level']),
'timestamp' => $displayTime,
'source' => '<a href="'.Url::generate(['page'=>'device', 'device'=>$message['message']['source']]).'">'.$message['message']['source'].'</a>',
'message' => $message['message']['message'],
'facility' => isset($message['message']['facility']) ? $message['message']['facility'] : '',
'level' => $message['message']['level'],
];
}
private function severityLabel($severity)
{
$map = [
"0" => "label-danger",
"1" => "label-danger",
"2" => "label-danger",
"3" => "label-danger",
"4" => "label-warning",
"5" => "label-info",
"6" => "label-info",
"7" => "label-default",
"" => "label-info",
];
$barColor = isset($map[$severity]) ? $map[$severity] : 'label-info';
return '<span class="alert-status '.$barColor .'" style="margin-right:8px;float:left;"></span>';
}
}

View File

@@ -0,0 +1,72 @@
<?php
/**
* SimpleTableController.php
*
* -Description-
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* @package LibreNMS
* @link http://librenms.org
* @copyright 2018 Tony Murray
* @author Tony Murray <murraytony@gmail.com>
*/
namespace App\Http\Controllers\Table;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Illuminate\Support\Collection;
abstract class SimpleTableController extends Controller
{
public static $base_rules = [
'current' => 'int',
'rowCount' => 'int',
'searchPhrase' => 'nullable|string',
'sort.*' => 'in:asc,desc',
];
/**
* Validate the given request with the given rules.
*
* @param \Illuminate\Http\Request $request
* @param array $rules
* @param array $messages
* @param array $customAttributes
* @return void
*/
public function validate(Request $request, array $rules = [], array $messages = [], array $customAttributes = [])
{
$full_rules = array_replace(self::$base_rules, $rules);
parent::validate($request, $full_rules, $messages, $customAttributes);
}
/**
* @param array|Collection $rows
* @param int $page
* @param int $currentCount
* @param int $total
* @return \Illuminate\Http\JsonResponse
*/
protected function formatResponse($rows, $page, $currentCount, $total)
{
return response()->json([
'current' => $page,
'rowCount' => $currentCount,
'rows' => $rows,
'total' => $total,
]);
}
}

View File

@@ -34,14 +34,13 @@ abstract class TableController extends PaginatedAjaxController
{ {
final protected function baseRules() final protected function baseRules()
{ {
return [ return SimpleTableController::$base_rules;
'current' => 'int',
'rowCount' => 'int',
'searchPhrase' => 'nullable|string',
'sort.*' => 'in:asc,desc',
];
} }
/**
* @param Request $request
* @return \Illuminate\Http\JsonResponse
*/
public function __invoke(Request $request) public function __invoke(Request $request)
{ {
$this->validate($request, $this->rules()); $this->validate($request, $this->rules());

View File

@@ -0,0 +1,74 @@
<?php
/**
* AlertsController.php
*
* -Description-
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* @package LibreNMS
* @link http://librenms.org
* @copyright 2018 Tony Murray
* @author Tony Murray <murraytony@gmail.com>
*/
namespace App\Http\Controllers\Widgets;
use App\Models\DeviceGroup;
use Illuminate\Http\Request;
class AlertsController extends WidgetController
{
protected $title = 'Alerts';
protected $defaults = [
'device' => null,
'acknowledged' => null,
'fired' => null,
'min_severity' => null,
'state' => null,
'group' => null,
'proc' => 0,
'sort' => 1,
];
public function getView(Request $request)
{
return view('widgets.alerts', $this->getSettings());
}
public function getSettingsView(Request $request)
{
$data = $this->getSettings();
$data['severities'] = [
// alert_rules.status is enum('ok','warning','critical')
'ok' => 1,
'warning' => 2,
'critical' => 3,
'ok only' => 4,
'warning only' => 5,
'critical only' => 6,
];
$data['states'] = [
// divined from librenms/alerts.php
'recovered' => '0',
'alerted' => '1',
'acknowledged' => '2',
'worse' => '3',
'better' => '4',
];
$data['device_group'] = DeviceGroup::find($data['group']);
return view('widgets.settings.alerts', $data);
}
}

View File

@@ -0,0 +1,174 @@
<?php
/**
* AvailabilityMapController.php
*
* -Description-
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* @package LibreNMS
* @link http://librenms.org
* @copyright 2018 Tony Murray
* @author Tony Murray <murraytony@gmail.com>
*/
namespace App\Http\Controllers\Widgets;
use App\Models\Device;
use App\Models\DeviceGroup;
use App\Models\Service;
use App\Models\UserWidget;
use Illuminate\Http\Request;
use LibreNMS\Config;
class AvailabilityMapController extends WidgetController
{
protected $title = 'Availability Map';
public function __construct()
{
$this->defaults = [
'title' => null,
'type' => (int)Config::get('webui.availability_map_compact', 0),
'tile_size' => 12,
'color_only_select' => 0,
'show_disabled_and_ignored' => 0,
'mode_select' => 0,
'device_group' => 0,
];
}
public function getView(Request $request)
{
$data = $this->getSettings();
$devices = [];
$device_totals = [];
$services = [];
$services_totals = [];
$mode = $data['mode_select'];
if ($mode == 0 || $mode == 2) {
list($devices, $device_totals) = $this->getDevices($request);
}
if ($mode > 0) {
list($services, $services_totals) = $this->getServices($request);
}
$data['device'] = Device::first();
$data['devices'] = $devices;
$data['device_totals'] = $device_totals;
$data['services'] = $services;
$data['services_totals'] = $services_totals;
return view('widgets.availability-map', $data);
}
public function getSettingsView(Request $request)
{
$settings = $this->getSettings();
$settings['device_group'] = DeviceGroup::find($settings['device_group']);
return view('widgets.settings.availability-map', $settings);
}
/**
* @param Request $request
* @return array
*/
private function getDevices(Request $request)
{
$settings = $this->getSettings();
// filter for by device group or show all
if ($group_id = $settings['device_group']) {
$device_query = DeviceGroup::find($group_id)->devices()->hasAccess($request->user());
} else {
$device_query = Device::hasAccess($request->user());
}
if (!$settings['show_disabled_and_ignored']) {
$device_query->where('disabled', 0);
}
$devices = $device_query->select('devices.device_id', 'hostname', 'sysName', 'status', 'uptime')->get();
// process status
$uptime_warn = Config::get('uptime_warning', 84600);
$totals = ['warn' => 0, 'up' => 0, 'down' => 0, 'ignored' => 0, 'disabled' => 0];
foreach ($devices as $device) {
if ($device->disabled) {
$totals['disabled']++;
$device->stateName = "disabled";
$device->labelClass = "blackbg";
} elseif ($device->ignore) {
$totals['ignored']++;
$device->stateName = "ignored";
$device->labelClass = "label-default";
} elseif ($device->status == 1) {
if (($device->uptime < $uptime_warn) && ($device->uptime != 0)) {
$totals['warn']++;
$device->stateName = 'warn';
$device->labelClass = 'label-warning';
} else {
$totals['up']++;
$device->stateName = 'up';
$device->labelClass = 'label-success';
}
} else {
$totals['down']++;
$device->stateName = 'down';
$device->labelClass = 'label-danger';
}
}
return [$devices, $totals];
}
private function getServices($request)
{
$settings = $this->getSettings();
// filter for by device group or show all
if ($group_id = $settings['device_group']) {
$services_query = DeviceGroup::find($group_id)->services()->hasAccess($request->user());
} else {
$services_query = Service::hasAccess($request->user());
}
$services = $services_query->with(['device' => function ($query) {
$query->select('devices.device_id', 'hostname', 'sysName');
}])->select('service_id', 'device_id', 'service_type', 'service_desc', 'service_status')->get();
// process status
$totals = ['warn' => 0, 'up' => 0, 'down' => 0];
foreach ($services as $service) {
if ($service->service_status == 0) {
$service->labelClass = "label-success";
$service->stateName = "up";
$totals['up']++;
} elseif ($service->service_status == 1) {
$service->labelClass = "label-warning";
$service->stateName = "warn";
$totals['warn']++;
} else {
$service->labelClass = "label-danger";
$service->stateName = "down";
$totals['down']++;
}
}
return [$services, $totals];
}
}

View File

@@ -0,0 +1,69 @@
<?php
/**
* ComponentStatusController.php
*
* -Description-
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* @package LibreNMS
* @link http://librenms.org
* @copyright 2018 Tony Murray
* @author Tony Murray <murraytony@gmail.com>
*/
namespace App\Http\Controllers\Widgets;
use App\Models\Component;
use DB;
use Illuminate\Http\Request;
use Illuminate\View\View;
class ComponentStatusController extends WidgetController
{
protected $title = 'Component Status';
/**
* @param Request $request
* @return View
*/
public function getView(Request $request)
{
$status = [
[
'color' => 'text-success',
'text' => __('Ok'),
],
[
'color' => 'grey',
'text' => __('Warning'),
],
[
'color' => 'text-danger',
'text' => __('Critical'),
]
];
$component_status = Component::query()
->select('status', DB::raw("count('status') as total"))
->groupBy('status')
->get()->pluck('total', 'status')->toArray();
foreach ($status as $key => $value) {
$status[$key]['total'] = isset($component_status[$key]) ? $component_status[$key] : 0;
}
return view('widgets.component-status', compact('status'));
}
}

View File

@@ -0,0 +1,88 @@
<?php
/**
* DeviceSummaryController.php
*
* -Description-
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* @package LibreNMS
* @link http://librenms.org
* @copyright 2018 Tony Murray
* @author Tony Murray <murraytony@gmail.com>
*/
namespace App\Http\Controllers\Widgets;
use App\Models\Device;
use App\Models\Port;
use App\Models\Service;
use Illuminate\Http\Request;
use LibreNMS\Config;
abstract class DeviceSummaryController extends WidgetController
{
protected $title = 'Device Summary';
public function __construct()
{
// init defaults we need to check config, so do it in construct
$this->defaults = [
'show_services' => (int)Config::get('show_services', 1),
'summary_errors' => (int)Config::get('summary_errors', 0)
];
}
public function getSettingsView(Request $request)
{
$settings = $this->getSettings();
return view('widgets.settings.device-summary', $settings);
}
protected function getData(Request $request)
{
$data = $this->getSettings();
$user = $request->user();
$data['devices'] = [
'count' => Device::hasAccess($user)->count(),
'up' => Device::hasAccess($user)->isUp()->count(),
'down' => Device::hasAccess($user)->isDown()->count(),
'ignored' => Device::hasAccess($user)->isIgnored()->count(),
'disabled' => Device::hasAccess($user)->isDisabled()->count(),
];
$data['ports'] = [
'count' => Port::hasAccess($user)->count(),
'up' => Port::hasAccess($user)->isUp()->count(),
'down' => Port::hasAccess($user)->isDown()->count(),
'ignored' => Port::hasAccess($user)->isIgnored()->count(),
'shutdown' => Port::hasAccess($user)->isShutdown()->count(),
'errored' => $data['summary_errors'] ? Port::hasAccess($user)->hasErrors()->count() : -1,
];
if ($data['show_services']) {
$data['services'] = [
'count' => Service::hasAccess($user)->count(),
'up' => Service::hasAccess($user)->isUp()->count(),
'down' => Service::hasAccess($user)->isDown()->count(),
'ignored' => Service::hasAccess($user)->isIgnored()->count(),
'disabled' => Service::hasAccess($user)->isDisabled()->count(),
];
}
return $data;
}
}

View File

@@ -0,0 +1,41 @@
<?php
/**
* DeviceSummaryHoriz.php
*
* -Description-
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* @package LibreNMS
* @link http://librenms.org
* @copyright 2018 Tony Murray
* @author Tony Murray <murraytony@gmail.com>
*/
namespace App\Http\Controllers\Widgets;
use Illuminate\Http\Request;
use Illuminate\View\View;
class DeviceSummaryHorizController extends DeviceSummaryController
{
/**
* @param Request $request
* @return View
*/
public function getView(Request $request)
{
return view('widgets.device-summary-horiz', $this->getData($request));
}
}

View File

@@ -0,0 +1,41 @@
<?php
/**
* DeviceSummaryVertController.php
*
* -Description-
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* @package LibreNMS
* @link http://librenms.org
* @copyright 2018 Tony Murray
* @author Tony Murray <murraytony@gmail.com>
*/
namespace App\Http\Controllers\Widgets;
use Illuminate\Http\Request;
use Illuminate\View\View;
class DeviceSummaryVertController extends DeviceSummaryController
{
/**
* @param Request $request
* @return View
*/
public function getView(Request $request)
{
return view('widgets.device-summary-vert', $this->getData($request));
}
}

View File

@@ -0,0 +1,53 @@
<?php
/**
* EventlogController.php
*
* -Description-
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* @package LibreNMS
* @link http://librenms.org
* @copyright 2018 Tony Murray
* @author Tony Murray <murraytony@gmail.com>
*/
namespace App\Http\Controllers\Widgets;
use App\Models\Device;
use Illuminate\Http\Request;
class EventlogController extends WidgetController
{
protected $title = 'Eventlog';
protected $defaults = [
'title' => null,
'device' => null,
'eventtype' => null,
];
public function getSettingsView(Request $request)
{
$data = $this->getSettings();
$data['device'] = Device::hasAccess($request->user())->find($data['device']);
return view('widgets.settings.eventlog', $data);
}
public function getView(Request $request)
{
return view('widgets.eventlog', $this->getSettings());
}
}

View File

@@ -0,0 +1,111 @@
<?php
/**
* GlobeController.php
*
* -Description-
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* @package LibreNMS
* @link http://librenms.org
* @copyright 2018 Tony Murray
* @author Tony Murray <murraytony@gmail.com>
*/
namespace App\Http\Controllers\Widgets;
use App\Models\Location;
use Illuminate\Http\Request;
use Illuminate\View\View;
use LibreNMS\Config;
class GlobeController extends WidgetController
{
protected $title = 'Globe';
public function __construct()
{
// init defaults we need to check config, so do it in construct
$this->defaults = [
'title' => null,
'markers' => Config::get('frontpage_globe.markers', 'devices'),
'region' => Config::get('frontpage_globe.region', 'world'),
'resolution' => Config::get('frontpage_globe.resolution', 'countries'),
];
}
public function getSettingsView(Request $request)
{
return view('widgets.settings.globe', $this->getSettings());
}
/**
* @param Request $request
* @return View
*/
public function getView(Request $request)
{
$data = $this->getSettings();
$locations = collect();
$eager_load = $data['markers'] == 'ports' ? ['devices.ports'] : ['devices'];
/** @var Location $location */
foreach (Location::hasAccess($request->user())->with($eager_load)->get() as $location) {
$count = 0;
$up = 0;
$down_items = collect();
if ($data['markers'] == 'devices') {
$count = $location->devices->count();
list($devices_down, $devices_up) = $location->devices->partition(function ($device) {
return $device->disable = 0 && $device->ignore = 0 && $device->status = 0;
});
$up = $devices_up->count();
$down_items = $devices_down->map(function ($device) {
return $device->displayName() . ' DOWN';
});
} elseif ($data['markers'] == 'ports') {
foreach ($location->devices as $device) {
list($ports_down, $ports_up) = $device->ports->partition(function ($port) {
return $port->ifOperStatus == 'down' && $port->ifAdminStatus == 'up';
});
$count += $device->ports->count();
$up += $ports_up->count();
$down_items = $ports_down->map(function ($port) use ($device) {
return $device->displayName() . '/' . $port->getShortLabel() . ' DOWN';
});
}
}
// indicate the number of up items before the itemized down
$down_items->prepend($up . '&nbsp;' . ucfirst($data['markers']) . '&nbsp;OK');
if ($count > 0) {
$locations->push([
$location->lat,
$location->lng,
$location->location,
$count ? (1 - $up / $count) * 100 : 0, // percent down
$count,
$down_items->implode(',<br/> '),
]);
}
}
$data['locations'] = $locations->toJson();
return view('widgets.globe', $data);
}
}

View File

@@ -0,0 +1,270 @@
<?php
/**
* GraphController.php
*
* -Description-
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* @package LibreNMS
* @link http://librenms.org
* @copyright 2018 Tony Murray
* @author Tony Murray <murraytony@gmail.com>
*/
namespace App\Http\Controllers\Widgets;
use App\Models\Application;
use App\Models\Bill;
use App\Models\Device;
use App\Models\MuninPlugin;
use App\Models\Port;
use App\Models\UserWidget;
use Carbon\Carbon;
use Illuminate\Http\Request;
use Illuminate\View\View;
use LibreNMS\Config;
use LibreNMS\Util\Graph;
use LibreNMS\Util\Time;
class GraphController extends WidgetController
{
protected $title = 'Graph';
protected $defaults = [
'title' => null,
'graph_type' => null,
'graph_range' => 'oneday',
'graph_legend' => 'yes',
'graph_device' => null,
'graph_port' => null,
'graph_application' => null,
'graph_munin' => null,
'graph_ports' => [],
'graph_custom' => [],
'graph_manual' => null,
'graph_bill' => null,
];
public function title()
{
$settings = $this->getSettings();
if (!empty($settings['title'])) {
return $settings['title'];
}
// automatic title
$type = $this->getGraphType();
if ($type == 'device') {
$device = Device::find($settings['graph_device']);
return ($device ? $device->displayName() : 'Device') . ' / ' . $settings['graph_type'];
} elseif ($type == 'aggregate') {
return 'Overall ' . $this->getGraphType(false) . ' Bits (' . $settings['graph_range'] . ')';
} elseif ($type == 'port') {
if ($port = Port::find($settings['graph_port'])) {
return $port->device->displayName() . ' / ' . $port->getShortLabel() . ' / ' . $settings['graph_type'];
}
} elseif ($type == 'application') {
if ($application = Application::find($settings['graph_application'])) {
return $application->device->displayName() . ' / ' . $application->app_type . ' / ' . $settings['graph_type'];
}
} elseif ($type == 'bill') {
if ($bill = Bill::find($settings['graph_bill'])) {
return 'Bill: ' . $bill->bill_name;
}
} elseif ($type == 'munin') {
if ($munin = MuninPlugin::find($settings['graph_munin'])) {
return $munin->device->displayName() . ' / ' . $munin->mplug_type . ' / ' . $settings['graph_type'];
}
}
// fall back for types where we couldn't find the item
if ($settings['graph_type']) {
return 'Device / ' . ucfirst($type) . ' / ' . $settings['graph_type'];
}
return $this->title;
}
public function getSettingsView(Request $request)
{
$data = $this->getSettings();
// format display name for selected graph type
$type_parts = explode('_', $data['graph_type']);
$primary = array_shift($type_parts);
$secondary = implode('_', $type_parts);
$name = $primary . ' ' . (Graph::isMibGraph($primary, $secondary) ? $secondary : implode(' ', $type_parts));
// format display for selected items
if ($primary == 'device' && $data['graph_device']) {
$device = Device::find($data['graph_device']);
}
$data['device_text'] = isset($device) ? $device->displayName() : __('Device does not exist');
if ($primary == 'port' && $data['graph_port']) {
$port = Port::find($data['graph_port']);
}
$data['port_text'] = isset($port) ? $port->getLabel() : __('Port does not exist');
if ($primary == 'application' && $data['graph_application']) {
$app = Application::find($data['graph_application']);
}
$data['application_text'] = isset($app) ? $app->displayName() . ' - ' . $app->device->displayName() : __('App does not exist');
if ($primary == 'bill' && $data['graph_bill']) {
$bill = Bill::find($data['graph_bill']);
}
$data['bill_text'] = isset($bill) ? $bill->bill_name : __('Bill does not exist');
if ($primary == 'munin' && $data['graph_munin']) {
$mplug = MuninPlugin::with('device')->find($data['graph_munin']);
}
$data['munin_text'] = isset($mplug) ? $mplug->device->displayName() . ' - ' . $mplug->mplug_type : __('Munin plugin does not exist');
$data['graph_ports'] = Port::whereIn('port_id', $data['graph_ports'])
->select('ports.device_id', 'port_id', 'ifAlias', 'ifName', 'ifDescr')
->with(['device' => function ($query) {
$query->select('device_id', 'hostname', 'sysName');
}])->get();
$data['graph_port_ids'] = $data['graph_ports']->pluck('port_id')->toJson();
$data['graph_text'] = ucwords($name);
return view('widgets.settings.graph', $data);
}
/**
* @param Request $request
* @return View
*/
public function getView(Request $request)
{
$settings = $this->getSettings();
// get type
$type = $this->getGraphType();
// force settings if not initialized
if (is_null($type) || empty($settings['graph_' . $this->getGraphType(false)])) {
return $this->getSettingsView($request);
}
$param = '';
if ($type == 'device') {
$param = 'device='.$settings['graph_device'];
} elseif ($type == 'application') {
$param = 'id='.$settings['graph_application'];
} elseif ($type == 'munin') {
if ($mplug = MuninPlugin::find($settings['graph_munin'])) {
$param = 'device='.$mplug->device_id.'&plugin='.$mplug->mplug_type;
}
} elseif ($type == 'aggregate') {
$aggregate_type = $this->getGraphType(false);
if ($aggregate_type == 'custom') {
$aggregate_type = $settings['graph_custom'];
}
if ($aggregate_type == 'ports') {
$port_ids = $settings['graph_ports'];
} else {
$port_types = collect((array)$aggregate_type)->map(function ($type) {
// check for config definitions
if (Config::has("{$type}_descr")) {
return Config::get("{$type}_descr", []);
}
return $type;
})->flatten();
$port_ids = Port::hasAccess($request->user())->where(function ($query) use ($port_types) {
foreach ($port_types as $port_type) {
$port_type = str_replace('@', '%', $port_type);
$query->orWhere('port_descr_type', 'LIKE', $port_type);
}
})->pluck('port_id')->all();
}
$param = 'id=' . implode(',', $port_ids);
$settings['graph_type'] = 'multiport_bits_separate';
} else {
$param = 'id='.$settings['graph_'.$type];
}
$data = $settings;
$data['param'] = $param;
$data['dimensions'] = $request->get('dimensions');
$data['from'] = Carbon::now()->subSeconds(Time::legacyTimeSpecToSecs($settings['graph_range']))->timestamp;
$data['to'] = Carbon::now()->timestamp;
return view('widgets.graph', $data);
}
private function getGraphType($summarize = true)
{
$type = explode('_', $this->getSettings()['graph_type'], 2)[0];
if ($summarize && in_array($type, ['transit', 'peering', 'core', 'ports', 'custom'])) {
return 'aggregate';
}
return $type;
}
public function getSettings()
{
if (is_null($this->settings)) {
$id = \Request::get('id');
$widget = UserWidget::findOrFail($id);
$settings = array_replace($this->defaults, (array)$widget->settings);
$settings['id'] = $id;
// legacy data conversions
if ($settings['graph_type'] == 'manual') {
$settings['graph_type'] = 'custom';
$settings['graph_custom'] = explode(',', $settings['graph_manual']);
}
if ($settings['graph_type'] == 'transpeer') {
$settings['graph_type'] = 'custom';
$settings['graph_custom'] = ['transit', 'peer'];
}
$settings['graph_device'] = $this->convertLegacySettingId($settings['graph_device'], 'device_id');
$settings['graph_port'] = $this->convertLegacySettingId($settings['graph_port'], 'port_id');
$settings['graph_application'] = $this->convertLegacySettingId($settings['graph_application'], 'app_id');
$settings['graph_munin'] = $this->convertLegacySettingId($settings['graph_munin'], 'mplug_id');
$settings['graph_bill'] = $this->convertLegacySettingId($settings['graph_bill'], 'bill_id');
$settings['graph_custom'] = (array)$settings['graph_custom'];
$settings['graph_ports'] = (array)$settings['graph_ports'];
$this->settings = $settings;
}
return $this->settings;
}
private function convertLegacySettingId($setting, $key)
{
if ($setting && !is_numeric($setting)) {
$data = json_decode($setting, true);
return isset($data[$key]) ? $data[$key] : 0;
}
return $setting;
}
}

View File

@@ -0,0 +1,62 @@
<?php
/**
* GraylogController.php
*
* -Description-
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* @package LibreNMS
* @link http://librenms.org
* @copyright 2018 Tony Murray
* @author Tony Murray <murraytony@gmail.com>
*/
namespace App\Http\Controllers\Widgets;
use App\Models\Device;
use Illuminate\Http\Request;
use Illuminate\View\View;
class GraylogController extends WidgetController
{
protected $title = 'Graylog';
protected $defaults = [
'title' => null,
'stream' => null,
'device' => null,
'range' => null,
'limit' => 15,
];
/**
* @param Request $request
* @return View
*/
public function getView(Request $request)
{
return view('widgets.graylog', $this->getSettings());
}
public function getSettingsView(Request $request)
{
$data = $this->getSettings();
if ($data['device']) {
$data['device'] = Device::find($data['device']);
}
return view('widgets.settings.graylog', $data);
}
}

View File

@@ -0,0 +1,79 @@
<?php
/**
* ImageController.php
*
* -Description-
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* @package LibreNMS
* @link http://librenms.org
* @copyright 2018 Tony Murray
* @author Tony Murray <murraytony@gmail.com>
*/
namespace App\Http\Controllers\Widgets;
use Illuminate\Http\Request;
class ImageController extends WidgetController
{
protected $title = 'Custom Image';
protected $defaults = [
'title' => null,
'image_url' => null,
'target_url' => null,
];
public function getView(Request $request)
{
$data = $this->getSettings();
if (is_null($data['image_url'])) {
return $this->getSettingsView($request);
}
$dimensions = $request->get('dimensions');
$data['dimensions'] = $dimensions;
// send size so generated images can generate the proper size
$data['image_url'] = str_replace(['@AUTO_HEIGHT@', '@AUTO_WIDTH@'], [$dimensions['y'], $dimensions['x']], $data['image_url']);
// bust cache
if (str_contains($data['image_url'], '?')) {
$data['image_url'] .= '&' . mt_rand();
} else {
$data['image_url'] .= '?' . mt_rand();
}
return view('widgets.image', $data);
}
public function getSettingsView(Request $request)
{
return view('widgets.settings.image', $this->getSettings());
}
public function getSettings()
{
if (is_null($this->settings)) {
parent::getSettings();
if (!empty($this->settings['image_title'])) {
$this->settings['title'] = $this->settings['image_title'];
}
}
return $this->settings;
}
}

View File

@@ -0,0 +1,63 @@
<?php
/**
* NotesController.php
*
* -Description-
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* @package LibreNMS
* @link http://librenms.org
* @copyright 2018 Tony Murray
* @author Tony Murray <murraytony@gmail.com>
*/
namespace App\Http\Controllers\Widgets;
use Illuminate\Http\Request;
use Illuminate\View\View;
use LibreNMS\Util\Html;
class NotesController extends WidgetController
{
protected $title = 'Notes';
protected $defaults = [
'title' => null,
'notes' => null,
];
public function getView(Request $request)
{
$settings = $this->getSettings();
if (is_null($settings['notes'])) {
return $this->getSettingsView($request);
}
$purifier_config = [
'HTML.Allowed' => 'b,iframe[frameborder|src|width|height],i,ul,ol,li,h1,h2,h3,h4,br,p,pre',
'HTML.Trusted' => true,
'HTML.SafeIframe' => true,
'URI.SafeIframeRegexp' => '%^(https?:)?//%',
];
$output = Html::display(nl2br($settings['notes']), $purifier_config);
return $output;
}
public function getSettingsView(Request $request)
{
return view('widgets.settings.notes', $this->getSettings());
}
}

View File

@@ -0,0 +1,38 @@
<?php
/**
* PlaceholderController.php
*
* -Description-
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* @package LibreNMS
* @link http://librenms.org
* @copyright 2018 Tony Murray
* @author Tony Murray <murraytony@gmail.com>
*/
namespace App\Http\Controllers\Widgets;
use Illuminate\Http\Request;
class PlaceholderController extends WidgetController
{
protected $title = 'Placeholder';
public function getView(Request $request)
{
return view('widgets.placeholder');
}
}

View File

@@ -0,0 +1,93 @@
<?php
/**
* ServerStatsController.php
*
* -Description-
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* @package LibreNMS
* @link http://librenms.org
* @copyright 2018 Tony Murray
* @author Tony Murray <murraytony@gmail.com>
*/
namespace App\Http\Controllers\Widgets;
use App\Models\Device;
use Illuminate\Http\Request;
class ServerStatsController extends WidgetController
{
protected $title = 'Server Stats';
protected $defaults = [
'title' => null,
'columnsize' => 3,
'device' => null,
'cpu' => 0,
'mempools' => [],
'disks' => [],
];
public function title(Request $request)
{
$settings = $this->getSettings();
if ($settings['title']) {
return $settings['title'];
}
/** @var Device $device */
$device = Device::hasAccess($request->user())->find($settings['device']);
if ($device) {
return $device->displayName() . ' Stats';
}
return $this->title;
}
public function getView(Request $request)
{
$data = $this->getSettings();
if (is_null($data['device'])) {
return $this->getSettingsView($request);
}
/** @var Device $device */
$device = Device::hasAccess($request->user())->find($data['device']);
if ($device) {
$data['cpu'] = $device->processors()->avg('processor_usage');
$data['mempools'] = $device->mempools()->select(\DB::raw('mempool_descr, ROUND(mempool_used / (1024*1024), 0) as used, ROUND(mempool_total /(1024*1024), 0) as total'))->get();
$data['disks'] = $device->storage()->select(\DB::raw('storage_descr, ROUND(storage_used / (1024*1024), 0) as used, ROUND(storage_size / (1024*1024), 0) as total'))->get();
}
return view('widgets.server-stats', $data);
}
public function getSettingsView(Request $request)
{
$settings = $this->getSettings();
$settings['device'] = Device::hasAccess($request->user())->find($settings['device']) ?: null;
return view('widgets.settings.server-stats', $settings);
}
public function getSettings()
{
$settings = parent::getSettings();
$settings['columns'] = 12 / $settings['columnsize'];
return $settings;
}
}

View File

@@ -0,0 +1,52 @@
<?php
/**
* SyslogController.php
*
* -Description-
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* @package LibreNMS
* @link http://librenms.org
* @copyright 2018 Tony Murray
* @author Tony Murray <murraytony@gmail.com>
*/
namespace App\Http\Controllers\Widgets;
use App\Models\Device;
use Illuminate\Http\Request;
class SyslogController extends WidgetController
{
protected $title = 'Syslog';
protected $defaults = [
'title' => null,
'device' => null,
];
public function getSettingsView(Request $request)
{
$data = $this->getSettings();
$data['device'] = Device::hasAccess($request->user())->find($data['device']);
return view('widgets.settings.syslog', $data);
}
public function getView(Request $request)
{
return view('widgets.syslog', $this->getSettings());
}
}

View File

@@ -0,0 +1,305 @@
<?php
/**
* TopDevices.php
*
* -Description-
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* @package LibreNMS
* @link http://librenms.org
* @copyright 2018 Tony Murray
* @author Tony Murray <murraytony@gmail.com>
*/
namespace App\Http\Controllers\Widgets;
use App\Models\Device;
use App\Models\Mempool;
use App\Models\Port;
use App\Models\Processor;
use App\Models\Storage;
use Auth;
use Carbon\Carbon;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Http\Request;
use Illuminate\Support\Collection;
use Illuminate\View\View;
use LibreNMS\Util\Colors;
use LibreNMS\Util\Html;
use LibreNMS\Util\StringHelpers;
use LibreNMS\Util\Url;
class TopDevicesController extends WidgetController
{
protected $title = 'Top Devices';
protected $defaults = [
'title' => null,
'top_query' => 'traffic',
'sort_order' => 'asc',
'device_count' => 5,
'time_interval' => 15,
];
public function title()
{
$settings = $this->getSettings();
return isset($settings['title']) ? $settings['title'] : $this->title;
}
/**
* @param Request $request
* @return View
*/
public function getView(Request $request)
{
$settings = $this->getSettings();
$sort = $settings['sort_order'];
switch ($settings['top_query']) {
case 'traffic':
$data = $this->getTrafficData($sort);
break;
case 'uptime':
$data = $this->getUptimeData($sort);
break;
case 'ping':
$data = $this->getPingData($sort);
break;
case 'cpu':
$data = $this->getProcessorData($sort);
break;
case 'ram':
$data = $this->getMemoryData($sort);
break;
case 'poller':
$data = $this->getPollerData($sort);
break;
case 'storage':
$data = $this->getStorageData($sort);
break;
default:
$data = [];
}
return view('widgets.top-devices', $data);
}
public function getSettingsView(Request $request)
{
return view('widgets.settings.top-devices', $this->getSettings());
}
/**
* @param array|string $headers
* @param Collection $rows
* @return array
*/
private function formatData($headers, $rows)
{
return [
'headers' => (array)$headers,
'rows' => $rows,
];
}
/**
* @param Builder $query
* @param string $left_table
* @return Builder
*/
private function withDeviceQuery($query, $left_table)
{
$settings = $this->getSettings();
/** @var Builder $query */
return $query->with(['device' => function ($query) {
$query->select('device_id', 'hostname', 'sysName', 'status');
}])
->select("$left_table.device_id")
->leftJoin('devices', "$left_table.device_id", 'devices.device_id')
->groupBy("$left_table.device_id")
->where('devices.last_polled', '>', Carbon::now()->subMinutes($settings['time_interval']));
}
/**
* @param Builder $query
* @return Builder
*/
private function deviceQuery()
{
$settings = $this->getSettings();
return Device::hasAccess(Auth::user())->select('device_id', 'hostname', 'sysName', 'status')
->where('devices.last_polled', '>', Carbon::now()->subMinutes($settings['time_interval']))
->limit($settings['device_count']);
}
/**
* @param Device $device
* @param string $graph_type
* @param array $graph_params
* @return array
*/
private function standardRow($device, $graph_type, $graph_params = [])
{
return [
Url::deviceLink($device, $device->shortDisplayName()),
Url::deviceLink($device, Url::minigraphImage(
$device,
Carbon::now()->subDays(1)->timestamp,
Carbon::now()->timestamp,
$graph_type,
'no',
150,
21
), $graph_params, 0, 0, 0),
];
}
private function getTrafficData($sort)
{
$settings = $this->getSettings();
/** @var Builder $query */
$query = Port::hasAccess(Auth::user())->with(['device' => function ($query) {
$query->select('device_id', 'hostname', 'sysName', 'status');
}])
->select('device_id')
->groupBy('device_id')
->where('poll_time', '>', Carbon::now()->subMinutes($settings['time_interval'])->timestamp)
->has('device')
->orderByRaw('SUM(ifInOctets_rate + ifOutOctets_rate) ' . $sort)
->limit($settings['device_count']);
$results = $query->get()->map(function ($port) {
return $this->standardRow($port->device, 'device_bits');
});
return $this->formatData('Traffic', $results);
}
private function getUptimeData($sort)
{
/** @var Builder $query */
$query = $this->deviceQuery()->orderBy('uptime', $sort);
$results = $query->get()->map(function ($device) {
return $this->standardRow($device, 'device_uptime', ['tab' => 'graphs', 'group' => 'system']);
});
return $this->formatData('Uptime', $results);
}
private function getPingData($sort)
{
/** @var Builder $query */
$query = $this->deviceQuery()->orderBy('last_ping_timetaken', $sort);
$results = $query->get()->map(function ($device) {
return $this->standardRow($device, 'device_ping_perf', ['tab' => 'graphs', 'group' => 'poller']);
});
return $this->formatData('Response time', $results);
}
private function getProcessorData($sort)
{
/** @var Builder $query */
$query = $this->withDeviceQuery(Processor::hasAccess(Auth::user()), (new Processor)->getTable())
->orderByRaw('AVG(`processor_usage`) ' . $sort);
$results = $query->get()->map(function ($port) {
return $this->standardRow($port->device, 'device_processor', ['tab' => 'health', 'metric' => 'processor']);
});
return $this->formatData('CPU Load', $results);
}
private function getMemoryData($sort)
{
/** @var Builder $query */
$query = $this->withDeviceQuery(Mempool::hasAccess(Auth::user()), (new Mempool)->getTable())
->orderBy('mempool_perc', $sort);
$results = $query->get()->map(function ($port) {
return $this->standardRow($port->device, 'device_mempool', ['tab' => 'health', 'metric' => 'mempool']);
});
return $this->formatData('Memory usage', $results);
}
private function getPollerData($sort)
{
/** @var Builder $query */
$query = $this->deviceQuery()->orderBy('last_polled_timetaken', $sort);
$results = $query->get()->map(function ($device) {
return $this->standardRow($device, 'device_poller_perf', ['tab' => 'graphs', 'group' => 'poller']);
});
return $this->formatData('Poller duration', $results);
}
private function getStorageData($sort)
{
$settings = $this->getSettings();
/** @var Builder $query */
$query = Storage::hasAccess(Auth::user())->with(['device' => function ($query) {
$query->select('device_id', 'hostname', 'sysName', 'status');
}])
->leftJoin('devices', 'storage.device_id', 'devices.device_id')
->select('storage.device_id', 'storage_id', 'storage_descr', 'storage_perc', 'storage_perc_warn')
->where('devices.last_polled', '>', Carbon::now()->subMinutes($settings['time_interval']))
->orderBy('storage_perc', $sort)
->limit($settings['device_count']);
$results = $query->get()->map(function ($storage) {
$device = $storage->device;
$graph_array = [
'height' => 100,
'width' => 210,
'to' => Carbon::now()->timestamp,
'from' => Carbon::now()->subDay()->timestamp,
'id' => $storage->storage_id,
'type' => 'device_storage',
'legend' => 'no',
];
$overlib_content = Url::overlibContent($graph_array, $device->displayName() . ' - ' . $storage->storage_descr);
$link_array = $graph_array;
$link_array['page'] = 'graphs';
unset($link_array['height'], $link_array['width'], $link_array['legend']);
$link = Url::generate($link_array);
$percent = $storage->storage_perc;
$background = Colors::percentage($percent, $storage->storage_perc_warn);
return [
Url::deviceLink($device, $device->shortDisplayName()),
StringHelpers::shortenText($storage->storage_descr, 50),
Url::overlibLink(
$link,
Html::percentageBar(150, 20, $percent, null, 'ffffff', $background['left'], $percent.'%', 'ffffff', $background['right']),
$overlib_content
)
];
});
return $this->formatData(['Storage Device', 'Disk usage'], $results);
}
}

View File

@@ -0,0 +1,73 @@
<?php
/**
* TopInterfacesController.php
*
* -Description-
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* @package LibreNMS
* @link http://librenms.org
* @copyright 2018 Tony Murray
* @author Tony Murray <murraytony@gmail.com>
*/
namespace App\Http\Controllers\Widgets;
use App\Models\Port;
use Carbon\Carbon;
use Illuminate\Http\Request;
use Illuminate\View\View;
class TopInterfacesController extends WidgetController
{
protected $title = 'Top Interfaces';
protected $defaults = [
'interface_count' => 5,
'time_interval' => 15,
'interface_filter' => null,
];
/**
* @param Request $request
* @return View
*/
public function getView(Request $request)
{
$data = $this->getSettings();
$query = Port::hasAccess($request->user())->with(['device' => function ($query) {
$query->select('device_id', 'hostname', 'sysName', 'status');
}])
->select('port_id', 'device_id', 'ifName', 'ifDescr', 'ifAlias')
->groupBy('port_id', 'device_id', 'ifName', 'ifDescr', 'ifAlias')
->where('poll_time', '>', Carbon::now()->subMinutes($data['time_interval']))
->orderByRaw('SUM(ifInOctets_rate + ifOutOctets_rate) DESC')
->limit($data['interface_count']);
if ($data['interface_filter']) {
$query->where('ifType', '=', $data['interface_filter']);
}
$data['ports'] = $query->get();
return view('widgets.top-interfaces', $data);
}
public function getSettingsView(Request $request)
{
return view('widgets.settings.top-interfaces', $this->getSettings());
}
}

View File

@@ -0,0 +1,105 @@
<?php
/**
* WidgetController.php
*
* -Description-
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* @package LibreNMS
* @link http://librenms.org
* @copyright 2018 Tony Murray
* @author Tony Murray <murraytony@gmail.com>
*/
namespace App\Http\Controllers\Widgets;
use App\Http\Controllers\Controller;
use App\Models\UserWidget;
use Illuminate\Http\Request;
use Illuminate\View\View;
abstract class WidgetController extends Controller
{
/** @var string sets the title for this widget, use title() function if you need to dynamically generate */
protected $title = 'Widget';
/** @var array Set default values for settings */
protected $defaults = [];
private $show_settings = false;
protected $settings = null;
/**
* @param Request $request
* @return View
*/
abstract public function getView(Request $request);
/**
* @param Request $request
* @return View
*/
public function getSettingsView(Request $request)
{
return view('widgets.settings.base');
}
public function __invoke(Request $request)
{
$this->show_settings = (bool)$request->get('settings');
if ($this->show_settings) {
$view = $this->getSettingsView($request);
} else {
$view = $this->getView($request);
}
$settings = $this->getSettings();
if (!empty($settings['title'])) {
$title = $settings['title'];
} else {
$title = __(method_exists($this, 'title') ? app()->call([$this, 'title']) : $this->title);
}
return $this->formatResponse($view, $title, $settings);
}
/**
* Get the settings (with defaults applied)
*
* @return array
*/
public function getSettings()
{
if (is_null($this->settings)) {
$id = \Request::get('id');
$widget = UserWidget::find($id);
$this->settings = array_replace($this->defaults, $widget ? (array)$widget->settings : []);
$this->settings['id'] = $id;
}
return $this->settings;
}
private function formatResponse($view, $title, $settings, $status = 'ok')
{
return response()->json([
'status' => $status,
'title' => __($title),
'html' => is_string($view) ? $view : $view->__toString(),
'settings' => $settings,
]);
}
}

View File

@@ -0,0 +1,99 @@
<?php
/**
* WorldMapController.php
*
* -Description-
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* @package LibreNMS
* @link http://librenms.org
* @copyright 2018 Tony Murray
* @author Tony Murray <murraytony@gmail.com>
*/
namespace App\Http\Controllers\Widgets;
use App\Models\Device;
use App\Models\Location;
use Illuminate\Http\Request;
use Illuminate\Support\Collection;
use LibreNMS\Config;
class WorldMapController extends WidgetController
{
protected $title = 'World Map';
public function __construct()
{
$this->defaults = [
'title' => null,
'title_url' => Config::get('leaflet.tile_url', '{s}.tile.openstreetmap.org'),
'init_lat' => Config::get('leaflet.default_lat', 51.4800),
'init_lng' => Config::get('leaflet.default_lng', 0),
'init_zoom' => Config::get('leaflet.default_zoom', 2),
'group_radius' => Config::get('leaflet.group_radius', 80),
'status' => '0,1',
];
}
public function getView(Request $request)
{
$settings = $this->getSettings();
$status = explode(',', $settings['status']);
$settings['dimensions'] = $request->get('dimensions');
$devices = Device::hasAccess($request->user())
->with('location')
->where('disabled', 0)
->whereIn('status', $status)
->get()
->filter(function ($device) use ($status) {
if (!($device->location_id && $device->location->coordinatesValid())) {
return false;
}
// add extra data
$device->markerIcon = 'greenMarker';
$device->zOffset = 0;
if ($device->status == 0) {
$device->markerIcon = 'redMarker';
$device->zOffset = 10000;
// TODO if ($device->isUnderMaintenance())
if (false) {
if ($status == 0) {
return false;
}
$device->markerIcon = 'blueMarker';
$device->zOffset = 5000;
}
}
return true;
});
$settings['devices'] = $devices;
return view('widgets.worldmap', $settings);
}
public function getSettingsView(Request $request)
{
return view('widgets.settings.worldmap', $this->getSettings());
}
}

53
app/Models/Bill.php Normal file
View File

@@ -0,0 +1,53 @@
<?php
/**
* Bill.php
*
* -Description-
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* @package LibreNMS
* @link http://librenms.org
* @copyright 2018 Tony Murray
* @author Tony Murray <murraytony@gmail.com>
*/
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Bill extends Model
{
public $timestamps = false;
protected $primaryKey = 'bill_id';
// ---- Query Scopes ----
public function scopeHasAccess($query, User $user)
{
if ($user->hasGlobalRead()) {
return $query;
}
return $query->join('bill_perms', 'bill_perms.bill_id', "bills.bill_id")
->where('bill_perms.user_id', $user->user_id);
}
// ---- Define Relationships ----
public function ports()
{
return $this->belongsToMany('App\Models\Port', 'bill_ports', 'bill_id', 'bill_id');
}
}

View File

@@ -11,11 +11,31 @@ class Dashboard extends Model
protected $primaryKey = 'dashboard_id'; protected $primaryKey = 'dashboard_id';
protected $fillable = ['user_id', 'dashboard_name', 'access']; protected $fillable = ['user_id', 'dashboard_name', 'access'];
// ---- Helper Functions ---
/**
* @param User $user
* @return bool
*/
public function canRead($user)
{
return $this->user_id == $user->user_id || $this->access > 0;
}
/**
* @param User $user
* @return bool
*/
public function canWrite($user)
{
return $this->user_id == $user->user_id || $this->access > 1;
}
// ---- Query scopes ---- // ---- Query scopes ----
/** /**
* @param Builder $query * @param Builder $query
* @param $user * @param User $user
* @return Builder|static * @return Builder|static
*/ */
public function scopeAllAvailable(Builder $query, $user) public function scopeAllAvailable(Builder $query, $user)
@@ -24,19 +44,13 @@ class Dashboard extends Model
->orWhere('access', '>', 0); ->orWhere('access', '>', 0);
} }
// ---- Define Reletionships ---- // ---- Define Relationships ----
/**
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
public function user() public function user()
{ {
return $this->belongsTo('App\Models\User', 'user_id'); return $this->belongsTo('App\Models\User', 'user_id');
} }
/**
* @return \Illuminate\Database\Eloquent\Relations\HasMany
*/
public function widgets() public function widgets()
{ {
return $this->hasMany('App\Models\UserWidget', 'dashboard_id'); return $this->hasMany('App\Models\UserWidget', 'dashboard_id');

View File

@@ -251,6 +251,18 @@ class Device extends BaseModel
return asset('images/os/generic.svg'); return asset('images/os/generic.svg');
} }
/**
* Get list of enabled graphs for this device.
*
* @return \Illuminate\Support\Collection
*/
public function graphs()
{
return DB::table('device_graphs')
->where('device_id', $this->device_id)
->pluck('graph');
}
/** /**
* Update the max_depth field based on parents * Update the max_depth field based on parents
* Performs SQL query, so make sure all parents are saved first * Performs SQL query, so make sure all parents are saved first
@@ -301,19 +313,21 @@ class Device extends BaseModel
/** /**
* @return string * @return string
*/ */
public function statusColour() public function statusName()
{ {
$status = $this->status; if ($this->disabled == 1) {
$ignore = $this->ignore; return 'disabled';
$disabled = $this->disabled; } elseif ($this->ignore == 1) {
if ($disabled == 1) { return 'ignore';
return 'teal'; } elseif ($this->status == 0) {
} elseif ($ignore == 1) { return 'down';
return 'yellow';
} elseif ($status == 0) {
return 'danger';
} else { } else {
return 'success'; $warning_time = \LibreNMS\Config::get('uptime_warning', 84600);
if ($this->uptime < $warning_time && $this->uptime != 0) {
return 'warn';
}
return 'up';
} }
} }

View File

@@ -311,4 +311,9 @@ class DeviceGroup extends BaseModel
{ {
return $this->belongsToMany('App\Models\Device', 'device_group_device', 'device_group_id', 'device_id'); return $this->belongsToMany('App\Models\Device', 'device_group_device', 'device_group_id', 'device_id');
} }
public function services()
{
return $this->belongsToMany('App\Models\Service', 'device_group_device', 'device_group_id', 'device_id');
}
} }

View File

@@ -9,6 +9,13 @@ class Mempool extends BaseModel
protected $primaryKey = 'mempool_id'; protected $primaryKey = 'mempool_id';
// ---- Query Scopes ----
public function scopeHasAccess($query, User $user)
{
return $this->hasDeviceAccess($query, $user);
}
// ---- Define Relationships ---- // ---- Define Relationships ----
public function device() public function device()

View File

@@ -0,0 +1,46 @@
<?php
/**
* MuninPlugin.php
*
* -Description-
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* @package LibreNMS
* @link http://librenms.org
* @copyright 2018 Tony Murray
* @author Tony Murray <murraytony@gmail.com>
*/
namespace App\Models;
class MuninPlugin extends BaseModel
{
public $timestamps = false;
protected $primaryKey = 'mplug_id';
// ---- Query scopes ----
public function scopeHasAccess($query, User $user)
{
return $this->hasDeviceAccess($query, $user);
}
// ---- Define Relationships ----
public function device()
{
return $this->belongsTo('App\Models\Device', 'device_id');
}
}

View File

@@ -56,7 +56,7 @@ class Port extends BaseModel
*/ */
public function getShortLabel() public function getShortLabel()
{ {
return Rewrite::shortenIfName(Rewrite::normalizeIfName($this->getLabel())); return Rewrite::shortenIfName(Rewrite::normalizeIfName($this->ifName ?: $this->ifDescr));
} }
/** /**
@@ -147,6 +147,15 @@ class Port extends BaseModel
]); ]);
} }
/**
* @param Builder $query
* @return Builder
*/
public function scopeIsShutdown($query)
{
return $query->where('ifAdminStatus', 'down');
}
/** /**
* @param Builder $query * @param Builder $query
* @return Builder * @return Builder

View File

@@ -2,6 +2,8 @@
namespace App\Models; namespace App\Models;
use Illuminate\Database\Eloquent\Builder;
class Service extends BaseModel class Service extends BaseModel
{ {
public $timestamps = false; public $timestamps = false;
@@ -9,6 +11,53 @@ class Service extends BaseModel
// ---- Query Scopes ---- // ---- Query Scopes ----
/**
* @param Builder $query
* @return Builder
*/
public function scopeIsUp($query)
{
return $query->where([
['service_ignore', '=', 0],
['service_disabled', '=', 0],
['service_status', '=', 0],
]);
}
/**
* @param Builder $query
* @return Builder
*/
public function scopeIsDown($query)
{
return $query->where([
['service_ignore', '=', 0],
['service_disabled', '=', 0],
['service_status', '=', 2],
]);
}
/**
* @param Builder $query
* @return Builder
*/
public function scopeIsIgnored($query)
{
return $query->where([
['service_ignore', '=', 1],
['service_disabled', '=', 0],
]);
}
/**
* @param Builder $query
* @return Builder
*/
public function scopeIsDisabled($query)
{
return $query->where('service_disabled', 1);
}
public function scopeHasAccess($query, User $user) public function scopeHasAccess($query, User $user)
{ {
return $this->hasDeviceAccess($query, $user); return $this->hasDeviceAccess($query, $user);

View File

@@ -9,6 +9,13 @@ class Storage extends BaseModel
protected $primaryKey = 'storage_id'; protected $primaryKey = 'storage_id';
// ---- Query Scopes ----
public function scopeHasAccess($query, User $user)
{
return $this->hasDeviceAccess($query, $user);
}
// ---- Define Relationships ---- // ---- Define Relationships ----
public function device() public function device()

View File

@@ -15,25 +15,16 @@ class UserWidget extends Model
// ---- Define Relationships ---- // ---- Define Relationships ----
/**
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
public function user() public function user()
{ {
return $this->belongsTo('App\Models\User', 'user_id'); return $this->belongsTo('App\Models\User', 'user_id');
} }
/**
* @return \Illuminate\Database\Eloquent\Relations\HasOne
*/
public function widget() public function widget()
{ {
return $this->hasOne('App\Models\Widgets', 'widget_id'); return $this->hasOne('App\Models\Widget', 'widget_id');
} }
/**
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
public function dashboard() public function dashboard()
{ {
return $this->belongsTo('App\Models\Dashboard', 'dashboard_id'); return $this->belongsTo('App\Models\Dashboard', 'dashboard_id');

35
app/Models/Widget.php Normal file
View File

@@ -0,0 +1,35 @@
<?php
/**
* Widget.php
*
* -Description-
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* @package LibreNMS
* @link http://librenms.org
* @copyright 2018 Tony Murray
* @author Tony Murray <murraytony@gmail.com>
*/
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Widget extends Model
{
public $timestamps = false;
protected $primaryKey = 'widget_id';
protected $fillable = ['widget_title', 'widget', 'base_dimensions'];
}

View File

@@ -35,8 +35,6 @@ class RouteServiceProvider extends ServiceProvider
*/ */
public function map() public function map()
{ {
$this->mapLegacyRoutes();
$this->mapApiRoutes(); $this->mapApiRoutes();
$this->mapWebRoutes(); $this->mapWebRoutes();
@@ -44,17 +42,6 @@ class RouteServiceProvider extends ServiceProvider
// //
} }
/**
* Define legacy routes for the application.
* Only initializing minimal middleware: Cookies and Session.
*/
protected function mapLegacyRoutes()
{
Route::middleware('minimal')
->namespace($this->namespace)
->group(base_path('routes/legacy.php'));
}
/** /**
* Define the "web" routes for the application. * Define the "web" routes for the application.
* *

View File

@@ -1,61 +1,10 @@
<?php <?php
/** header('Content-type: application/json');
* Laravel - A PHP Framework For Web Artisans
*
* @package Laravel
* @author Taylor Otwell <taylor@laravel.com>
*/
/* // reload dashboard referencing old endpoint
|-------------------------------------------------------------------------- exit(json_encode([
| Register The Auto Loader 'html' => '<script>window.location.reload(false);</script>',
|-------------------------------------------------------------------------- 'status' => 'ok',
| 'title' => 'Reload Dasbhoard'
| Composer provides a convenient, automatically generated class loader for ]));
| our application. We just need to utilize it! We'll simply require it
| into the script here so that we don't have to worry about manual
| loading any of our classes later on. It feels great to relax.
|
*/
require __DIR__.'/../bootstrap/autoload.php';
/*
|--------------------------------------------------------------------------
| Turn On The Lights
|--------------------------------------------------------------------------
|
| We need to illuminate PHP development, so let us turn on the lights.
| This bootstraps the framework and gets it ready for use, then it
| will load up this application so that we can run it and send
| the responses back to the browser and delight our users.
|
*/
$app = require_once __DIR__.'/../bootstrap/app.php';
/*
|--------------------------------------------------------------------------
| Run The Application
|--------------------------------------------------------------------------
|
| Once we have the application, we can handle the incoming request
| through the kernel, and send the associated response back to
| the client's browser allowing them to enjoy the creative
| and wonderful application we have prepared for them.
|
*/
$kernel = $app->make(Illuminate\Contracts\Http\Kernel::class);
// rewrite the request uri
$_SERVER['REQUEST_URI'] = '/legacy_ajax_dash';
$response = $kernel->handle(
$request = Illuminate\Http\Request::capture()
);
$response->send();
$kernel->terminate($request, $response);

View File

@@ -1,2 +1,2 @@
/*! gridster.js - v0.6.10 - 2015-08-05 - * https://dsmorse.github.io/gridster.js/ - Copyright (c) 2015 ducksboard; Licensed MIT */ /*! gridster.js - v0.7.0 - 2017-03-27 - * https://dsmorse.github.io/gridster.js/ - Copyright (c) 2017 ducksboard; Licensed MIT */
.gridster{position:relative}.gridster>*{-webkit-transition:height .4s,width .4s;-moz-transition:height .4s,width .4s;-o-transition:height .4s,width .4s;-ms-transition:height .4s,width .4s;transition:height .4s,width .4s}.gridster .gs-w{z-index:2;position:absolute}.gridster .preview-holder{z-index:1;position:absolute;background-color:#fff;border-color:#fff;opacity:.3}.gridster .player-revert{z-index:10!important;-webkit-transition:left .3s,top .3s!important;-moz-transition:left .3s,top .3s!important;-o-transition:left .3s,top .3s!important;transition:left .3s,top .3s!important}.gridster.collapsed{height:auto!important}.gridster.collapsed .gs-w{position:static!important}.ready .gs-w:not(.preview-holder),.ready .resize-preview-holder{-webkit-transition:opacity .3s,left .3s,top .3s,width .3s,height .3s;-moz-transition:opacity .3s,left .3s,top .3s,width .3s,height .3s;-o-transition:opacity .3s,left .3s,top .3s,width .3s,height .3s;transition:opacity .3s,left .3s,top .3s,width .3s,height .3s}.gridster .dragging,.gridster .resizing{z-index:10!important;-webkit-transition:all 0s!important;-moz-transition:all 0s!important;-o-transition:all 0s!important;transition:all 0s!important}.gs-resize-handle{position:absolute;z-index:1}.gs-resize-handle-both{width:20px;height:20px;bottom:-8px;right:-8px;background-image:url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBzdGFuZGFsb25lPSJubyI/Pg08IS0tIEdlbmVyYXRvcjogQWRvYmUgRmlyZXdvcmtzIENTNiwgRXhwb3J0IFNWRyBFeHRlbnNpb24gYnkgQWFyb24gQmVhbGwgKGh0dHA6Ly9maXJld29ya3MuYWJlYWxsLmNvbSkgLiBWZXJzaW9uOiAwLjYuMSAgLS0+DTwhRE9DVFlQRSBzdmcgUFVCTElDICItLy9XM0MvL0RURCBTVkcgMS4xLy9FTiIgImh0dHA6Ly93d3cudzMub3JnL0dyYXBoaWNzL1NWRy8xLjEvRFREL3N2ZzExLmR0ZCI+DTxzdmcgaWQ9IlVudGl0bGVkLVBhZ2UlMjAxIiB2aWV3Qm94PSIwIDAgNiA2IiBzdHlsZT0iYmFja2dyb3VuZC1jb2xvcjojZmZmZmZmMDAiIHZlcnNpb249IjEuMSINCXhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIHhtbDpzcGFjZT0icHJlc2VydmUiDQl4PSIwcHgiIHk9IjBweCIgd2lkdGg9IjZweCIgaGVpZ2h0PSI2cHgiDT4NCTxnIG9wYWNpdHk9IjAuMzAyIj4NCQk8cGF0aCBkPSJNIDYgNiBMIDAgNiBMIDAgNC4yIEwgNCA0LjIgTCA0LjIgNC4yIEwgNC4yIDAgTCA2IDAgTCA2IDYgTCA2IDYgWiIgZmlsbD0iIzAwMDAwMCIvPg0JPC9nPg08L3N2Zz4=);background-position:top left;background-repeat:no-repeat;cursor:se-resize;z-index:20}.gs-resize-handle-x{top:0;bottom:13px;right:-5px;width:10px;cursor:e-resize}.gs-resize-handle-y{left:0;right:13px;bottom:-5px;height:10px;cursor:s-resize}.gs-w:hover .gs-resize-handle,.resizing .gs-resize-handle{opacity:1}.gs-resize-handle,.gs-w.dragging .gs-resize-handle{opacity:0}.gs-resize-disabled .gs-resize-handle,[data-max-sizex="1"] .gs-resize-handle-x,[data-max-sizey="1"] .gs-resize-handle-y,[data-max-sizey="1"][data-max-sizex="1"] .gs-resize-handle{display:none!important} .gridster{position:relative}.gridster>*{-webkit-transition:height .4s,width .4s;-moz-transition:height .4s,width .4s;-o-transition:height .4s,width .4s;-ms-transition:height .4s,width .4s;transition:height .4s,width .4s}.gridster .gs-w{z-index:2;position:absolute}.gridster .preview-holder{z-index:1;position:absolute;background-color:#fff;border-color:#fff;opacity:.3}.gridster .player-revert{z-index:10!important;-webkit-transition:left .3s,top .3s!important;-moz-transition:left .3s,top .3s!important;-o-transition:left .3s,top .3s!important;transition:left .3s,top .3s!important}.gridster.collapsed{height:auto!important}.gridster.collapsed .gs-w{position:static!important}.ready .gs-w:not(.preview-holder),.ready .resize-preview-holder{-webkit-transition:opacity .3s,left .3s,top .3s,width .3s,height .3s;-moz-transition:opacity .3s,left .3s,top .3s,width .3s,height .3s;-o-transition:opacity .3s,left .3s,top .3s,width .3s,height .3s;transition:opacity .3s,left .3s,top .3s,width .3s,height .3s}.gridster .dragging,.gridster .resizing{z-index:10!important;-webkit-transition:all 0s!important;-moz-transition:all 0s!important;-o-transition:all 0s!important;transition:all 0s!important}.gs-resize-handle{position:absolute;z-index:1}.gs-resize-handle-both{width:20px;height:20px;bottom:-8px;right:-8px;background-image:url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBzdGFuZGFsb25lPSJubyI/Pg08IS0tIEdlbmVyYXRvcjogQWRvYmUgRmlyZXdvcmtzIENTNiwgRXhwb3J0IFNWRyBFeHRlbnNpb24gYnkgQWFyb24gQmVhbGwgKGh0dHA6Ly9maXJld29ya3MuYWJlYWxsLmNvbSkgLiBWZXJzaW9uOiAwLjYuMSAgLS0+DTwhRE9DVFlQRSBzdmcgUFVCTElDICItLy9XM0MvL0RURCBTVkcgMS4xLy9FTiIgImh0dHA6Ly93d3cudzMub3JnL0dyYXBoaWNzL1NWRy8xLjEvRFREL3N2ZzExLmR0ZCI+DTxzdmcgaWQ9IlVudGl0bGVkLVBhZ2UlMjAxIiB2aWV3Qm94PSIwIDAgNiA2IiBzdHlsZT0iYmFja2dyb3VuZC1jb2xvcjojZmZmZmZmMDAiIHZlcnNpb249IjEuMSINCXhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIHhtbDpzcGFjZT0icHJlc2VydmUiDQl4PSIwcHgiIHk9IjBweCIgd2lkdGg9IjZweCIgaGVpZ2h0PSI2cHgiDT4NCTxnIG9wYWNpdHk9IjAuMzAyIj4NCQk8cGF0aCBkPSJNIDYgNiBMIDAgNiBMIDAgNC4yIEwgNCA0LjIgTCA0LjIgNC4yIEwgNC4yIDAgTCA2IDAgTCA2IDYgTCA2IDYgWiIgZmlsbD0iIzAwMDAwMCIvPg0JPC9nPg08L3N2Zz4=);background-position:top left;background-repeat:no-repeat;cursor:se-resize;z-index:20}.gs-resize-handle-x{top:0;bottom:13px;right:-5px;width:10px;cursor:e-resize}.gs-resize-handle-y{left:0;right:13px;bottom:-5px;height:10px;cursor:s-resize}.gs-w:hover .gs-resize-handle,.resizing .gs-resize-handle{opacity:1}.gs-resize-handle,.gs-w.dragging .gs-resize-handle{opacity:0}.gs-resize-disabled .gs-resize-handle,[data-max-sizex="1"] .gs-resize-handle-x,[data-max-sizey="1"] .gs-resize-handle-y,[data-max-sizey="1"][data-max-sizex="1"] .gs-resize-handle{display:none!important}

View File

@@ -1731,10 +1731,6 @@ tr.search:nth-child(odd) {
border-top-right-radius: 4px; border-top-right-radius: 4px;
} }
.widget_body {
padding: 0.8em;
}
.mapTooltip { .mapTooltip {
position : fixed; position : fixed;
background-color : #B2B3B1; background-color : #B2B3B1;
@@ -1917,6 +1913,7 @@ label {
.edit-widget, .close-widget { cursor: pointer; } .edit-widget, .close-widget { cursor: pointer; }
.widget_body { .widget_body {
padding: 0.8em;
overflow-y: auto; overflow-y: auto;
width: 100%; width: 100%;
height: calc(100% - 38px); height: calc(100% - 38px);
@@ -2063,6 +2060,21 @@ label {
line-height:34px; line-height:34px;
} }
.dashboard-widget-settings label {
line-height:34px;
}
.dashboard-graph, .dashboard-graph img {
height: 100%;
width: 100%;
}
.dashboard-image {
padding: 2px;
height: 100%;
width: auto;
}
.nav > li > a { .nav > li > a {
padding-left: 10px; padding-left: 10px;
padding-right: 5px; padding-right: 5px;

View File

@@ -14,8 +14,8 @@
use LibreNMS\Authentication\LegacyAuth; use LibreNMS\Authentication\LegacyAuth;
if (isset($widget_settings['mode_select']) && $widget_settings['mode_select'] !== '') { if (isset($settings['mode_select']) && $settings['mode_select'] !== '') {
$mode = $widget_settings['mode_select']; $mode = $settings['mode_select'];
} elseif (isset($_SESSION["map_view"]) && is_numeric($_SESSION["map_view"])) { } elseif (isset($_SESSION["map_view"]) && is_numeric($_SESSION["map_view"])) {
$mode = $_SESSION["map_view"]; $mode = $_SESSION["map_view"];
} else { } else {
@@ -29,10 +29,10 @@ $select_modes = array(
); );
if ($config['webui']['availability_map_compact'] == 1) { if ($config['webui']['availability_map_compact'] == 1) {
$compact_tile = $widget_settings['tile_size']; $compact_tile = $settings['tile_size'];
} }
$show_disabled_ignored = $widget_settings['show_disabled_and_ignored']; $show_disabled_ignored = $settings['show_disabled_and_ignored'];
if (defined('SHOW_SETTINGS')) { if (defined('SHOW_SETTINGS')) {
$common_output[] = ' $common_output[] = '
@@ -42,7 +42,7 @@ if (defined('SHOW_SETTINGS')) {
<label for="title" class="control-label availability-map-widget-header">Widget title</label> <label for="title" class="control-label availability-map-widget-header">Widget title</label>
</div> </div>
<div class="col-sm-6"> <div class="col-sm-6">
<input type="text" class="form-control" name="title" placeholder="Custom title for widget" value="'.htmlspecialchars($widget_settings['title']).'"> <input type="text" class="form-control" name="title" placeholder="Custom title for widget" value="'.htmlspecialchars($settings['title']).'">
</div> </div>
</div>'; </div>';
@@ -54,8 +54,8 @@ if (defined('SHOW_SETTINGS')) {
</div> </div>
<div class="col-sm-6"> <div class="col-sm-6">
<select class="form-control" name="color_only_select"> <select class="form-control" name="color_only_select">
<option value="1"' . ($widget_settings['color_only_select'] == 1 ? ' selected' : '') . ' >yes</option> <option value="1"' . ($settings['color_only_select'] == 1 ? ' selected' : '') . ' >yes</option>
<option value="0"' . ($widget_settings['color_only_select'] == 1 ? '' : ' selected') . ' >no</option> <option value="0"' . ($settings['color_only_select'] == 1 ? '' : ' selected') . ' >no</option>
</select> </select>
</div> </div>
</div> </div>
@@ -107,7 +107,7 @@ if (defined('SHOW_SETTINGS')) {
$common_output[] = '<option value="0" selected>only devices</option>'; $common_output[] = '<option value="0" selected>only devices</option>';
} else { } else {
foreach ($select_modes as $mode_select => $option) { foreach ($select_modes as $mode_select => $option) {
if ($mode_select == $widget_settings["mode_select"]) { if ($mode_select == $settings["mode_select"]) {
$selected = 'selected'; $selected = 'selected';
} else { } else {
$selected = ''; $selected = '';
@@ -237,7 +237,7 @@ if (defined('SHOW_SETTINGS')) {
</div> </div>
</a>'; </a>';
} else { } else {
if ($widget_settings['color_only_select'] == 1) { if ($settings['color_only_select'] == 1) {
$deviceState = ' '; $deviceState = ' ';
$deviceLabel .= ' widget-availability-fixed'; $deviceLabel .= ' widget-availability-fixed';
} }
@@ -295,7 +295,7 @@ if (defined('SHOW_SETTINGS')) {
</a>'; </a>';
} else { } else {
$serviceText = $service['service_type'] . ' - ' . $serviceState; $serviceText = $service['service_type'] . ' - ' . $serviceState;
if ($widget_settings['color_only_select'] == 1) { if ($settings['color_only_select'] == 1) {
$serviceText = ' '; $serviceText = ' ';
$serviceLabel .= ' widget-availability-fixed'; $serviceLabel .= ' widget-availability-fixed';
} }

View File

@@ -1,38 +0,0 @@
<?php
$OBJCOMP = new LibreNMS\Component();
$common_output[] = '
<div>
<table id="component-status" class="table table-hover table-condensed table-striped">
<thead>
<tr>
<th data-column-id="status" data-order="desc">Status</th>
<th data-column-id="count">Count</th>
</tr>
</thead>
<tbody>
';
foreach ($OBJCOMP->getComponentStatus() as $k => $v) {
if ($k == 0) {
$status = 'Ok';
$color = 'green';
} elseif ($k == 1) {
$status = 'Warning';
$color = 'grey';
} else {
$status = 'Critical';
$color = 'red';
}
$common_output[] .= '
<tr>
<td><p class="text-left '.$color.'">'.$status.'</p></td>
<td><p class="text-left '.$color.'">'.$v.'</p></td>
</tr>
';
}
$common_output[] .= '
</tbody>
</table>
</div>
';

View File

@@ -1,427 +0,0 @@
<?php
/* Copyright (C) 2015-2016 Daniel Preussker, QuxLabs UG <preussker@quxlabs.com>
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. */
/**
* Generic Graph Widget
* @author Daniel Preussker
* @copyright 2015-2016 Daniel Preussker, QuxLabs UG
* @license GPL
* @package LibreNMS
* @subpackage Widgets
*/
if (defined('SHOW_SETTINGS') || empty($widget_settings)) {
$common_output[] = '
<form class="form" onsubmit="widget_settings(this); return false;">
<div class="form-group">
<div class="col-sm-2">
<label for="title" class="control-label">Title: </label>
</div>
<div class="col-sm-10">
<input type="text" class="form-control" name="title" placeholder="Automatic Title" value="'.htmlspecialchars($widget_settings['title']).'">
</div>
</div>
<div class="form-group">
<div class="col-sm-2">
<label for="graph_type" class="control-label">Graph: </label>
</div>
<div class="col-sm-8">
<select class="form-control" name="graph_type" id="select_'.$unique_id.'" onchange="switch_'.$unique_id.'($(this).val());">';
if (empty($widget_settings['graph_type'])) {
$common_output[] = '<option disabled selected>Select a Graph</option>';
}
$sub = '';
$old = '';
foreach (array('device','port','application','munin') as $type) {
$common_output[] = '<option disabled>'.nicecase($type).':</option>';
foreach (get_graph_subtypes($type) as $avail_type) {
$display_type = is_mib_graph($type, $avail_type) ? $avail_type : nicecase($avail_type);
if (strstr($display_type, '_')) {
$sub = explode('_', $display_type, 2);
$sub = array_shift($sub);
if ($sub != $old) {
$old = $sub;
$common_output[] = '<option disabled>&nbsp;&nbsp;&nbsp;'.nicecase($sub).':</option>';
}
$display_type = str_replace($sub.'_', '', $display_type);
$space = '&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;';
} else {
$space = '&nbsp;&nbsp;&nbsp;';
}
$common_output[] = '<option value="'.$type.'_'.$avail_type.'"';
if ($type.'_'.$avail_type == $widget_settings['graph_type']) {
$common_output[] = " selected";
}
$common_output[] = '>'.$space.nicecase($display_type).'</option>';
}
$common_output[] = '<option disabled></option>';
}
$common_output[] = '
<option disabled>Port Aggregators:</option>
<option value="transit"'.($widget_settings['graph_type'] == 'transit' ? ' selected' : '').'>&nbsp;&nbsp;&nbsp;Transit</option>
<option value="peering"'.($widget_settings['graph_type'] == 'peering' ? ' selected' : '').'>&nbsp;&nbsp;&nbsp;Peering</option>
<option value="transpeer"'.($widget_settings['graph_type'] == 'transpeer' ? ' selected' : '').'>&nbsp;&nbsp;&nbsp;Transit + Peering</option>
<option value="core"'.($widget_settings['graph_type'] == 'core' ? ' selected' : '').'>&nbsp;&nbsp;&nbsp;Core</option>
<option value="custom"'.($widget_settings['graph_type'] == 'custom' ? ' selected' : '').'>&nbsp;&nbsp;&nbsp;Custom Descr</option>
<option value="manual"'.($widget_settings['graph_type'] == 'manual' ? ' selected' : '').'>&nbsp;&nbsp;&nbsp;Manual Descr</option>
<option disabled></option>
<option value="bill_bits"'.($widget_settings['graph_type'] == 'bill_bits' ? ' selected' : '').'>Bill</option>
</select>
</div>
<div class="col-sm-offset-10 col-sm-2">
<div class="checkbox input-sm">
<label class="control-label">
<input type="checkbox" name="graph_legend" class="widget_setting" value="1" '.($widget_settings['graph_legend'] ? 'checked' : '').'> Legend
</label>
</div>
</div>
</div>
<div class="clearfix"></div>
<div class="form-group">
<div class="col-sm-2">
<label for="graph_range" class="control-label">Range: </label>
</div>
<div class="col-sm-10">
<select class="form-control" name="graph_range">';
$checked = '';
foreach (array_diff_key($config['time'], array('now'=>'')) as $k => $v) {
if ($widget_settings['graph_range'] == $k) {
$checked = ' selected';
} else {
$checked = '';
}
$common_output[] = '<option value="'.$k.'"'.$checked.'>'.nicecase($k).'</option>';
}
$common_output[] = '
</select>
</div>
</div>
<div class="form-group input_'.$unique_id.'" id="input_'.$unique_id.'_device">
<div class="col-sm-2">
<label for="graph_device" class="control-label">Device: </label>
</div>
<div class="col-sm-10">
<input type="text" class="form-control input_'.$unique_id.'_device" name="graph_device" placeholder="Device Name" value="'.htmlspecialchars($widget_settings['graph_device']).'">
</div>
</div>
<div class="form-group input_'.$unique_id.'" id="input_'.$unique_id.'_port">
<div class="col-sm-2">
<label for="graph_port" class="control-label">Port: </label>
</div>
<div class="col-sm-10">
<input type="text" class="form-control input_'.$unique_id.'_port" name="graph_port" placeholder="Port" value="'.htmlspecialchars($widget_settings['graph_port']).'">
</div>
</div>
<div class="form-group input_'.$unique_id.'" id="input_'.$unique_id.'_application">
<div class="col-sm-2">
<label for="graph_application" class="control-label">Application: </label>
</div>
<div class="col-sm-10">
<input type="text" class="form-control input_'.$unique_id.'_application" name="graph_application" placeholder="Application" value="'.htmlspecialchars($widget_settings['graph_application']).'">
</div>
</div>
<div class="form-group input_'.$unique_id.'" id="input_'.$unique_id.'_munin">
<div class="col-sm-2">
<label for="graph_munin" class="control-label">Munin Plugin: </label>
</div>
<div class="col-sm-10">
<input type="text" class="form-control input_'.$unique_id.'_munin" name="graph_munin" placeholder="Munin Plugin" value="'.htmlspecialchars($widget_settings['graph_munin']).'">
</div>
</div>
<div class="form-group input_'.$unique_id.'" id="input_'.$unique_id.'_custom">
<div class="col-sm-2">
<label for="graph_munin" class="control-label">Custom Port-Desc: </label>
</div>
<div class="col-sm-10">
<select class="form-control input_'.$unique_id.'_custom" name="graph_custom">';
foreach ($config['custom_descr'] as $opt) {
$common_output[] = '<option value="'.$opt.'" '.($widget_settings['graph_custom'] == $opt ? 'selected' : '').'>'.ucfirst($opt).'</option>';
}
$common_output[] = ' </select>
</div>
</div>
<div class="form-group input_'.$unique_id.'" id="input_'.$unique_id.'_manual">
<div class="col-sm-2">
<label for="graph_manual" class="control-label">Manual Port-Desc: </label>
</div>
<div class="col-sm-10">
<input type="text" class="form-control input_'.$unique_id.'_manual" name="graph_manual" placeholder="Descr String" value="'.htmlspecialchars($widget_settings['graph_manual']).'">';
$common_output[] = ' </div>
</div>
<div class="form-group input_'.$unique_id.'" id="input_'.$unique_id.'_bill">
<div class="col-sm-2">
<label for="graph_bill" class="control-label">Bill: </label>
</div>
<div class="col-sm-10">
<input type="text" class="form-control input_'.$unique_id.'_bill" name="graph_bill" placeholder="Bill" value="'.htmlspecialchars($widget_settings['graph_bill']).'">
</div>
</div>
<div class="form-group">
<div class="col-sm-2">
<button type="submit" class="btn btn-default">Set</button>
</div>
</div>
</form>
<style>
.twitter-typeahead {
width: 100%;
}
</style>
<script>
function '.$unique_id.'() {
var '.$unique_id.'_device = new Bloodhound({
datumTokenizer: Bloodhound.tokenizers.obj.whitespace("name"),
queryTokenizer: Bloodhound.tokenizers.whitespace,
remote: {
url: "ajax_search.php?search=%QUERY&type=device",
filter: function (output) {
return $.map(output, function (item) {
return {
device_id: item.device_id,
device_image: item.device_image,
name: item.name,
device_os: item.device_os,
version: item.version,
device_hardware: item.device_hardware,
device_ports: item.device_ports,
location: item.location
};
});
},
wildcard: "%QUERY"
}
});
'.$unique_id.'_device.initialize();
$(".input_'.$unique_id.'_device").typeahead({
hint: true,
highlight: true,
minLength: 1,
classNames: {
menu: "typeahead-left"
}
},
{
source: '.$unique_id.'_device.ttAdapter(),
limit: '.$typeahead_limit.',
async: false,
templates: {
header: "<h5><strong>&nbsp;Devices</strong></h5>",
suggestion: Handlebars.compile(\'<p><img src="{{device_image}}" border="0"> <small><strong>{{name}}</strong> | {{device_os}} | {{version}} | {{device_hardware}} with {{device_ports}} port(s) | {{location}}</small></p>\')
}
});
var '.$unique_id.'_port = new Bloodhound({
datumTokenizer: Bloodhound.tokenizers.obj.whitespace("port_id"),
queryTokenizer: Bloodhound.tokenizers.whitespace,
remote: {
url: "ajax_search.php?search=%QUERY&type=ports",
filter: function (output) {
return $.map(output, function (item) {
return {
name: item.name,
description: item.description,
hostname: item.hostname,
port_id: item.port_id
};
});
},
wildcard: "%QUERY"
}
});
'.$unique_id.'_port.initialize();
$(".input_'.$unique_id.'_port").typeahead({
hint: true,
highlight: true,
minLength: 1,
classNames: {
menu: "typeahead-left"
}
},
{
source: '.$unique_id.'_port.ttAdapter(),
limit: '.$typeahead_limit.',
async: false,
templates: {
header: "<h5><strong>&nbsp;Ports</strong></h5>",
suggestion: Handlebars.compile(\'<p><small><i class="fa fa-link fa-sm icon-theme" aria-hidden="true"></i> <strong>{{name}}</strong> {{hostname}} - <i>{{description}}</i></small></p>\')
}
});
var '.$unique_id.'_application = new Bloodhound({
datumTokenizer: Bloodhound.tokenizers.obj.whitespace("app_id"),
queryTokenizer: Bloodhound.tokenizers.whitespace,
remote: {
url: "ajax_search.php?search=%QUERY&type=applications",
filter: function (output) {
return $.map(output, function (item) {
return {
name: item.name,
hostname: item.hostname,
app_id: item.app_id
};
});
},
wildcard: "%QUERY"
}
});
'.$unique_id.'_application.initialize();
$(".input_'.$unique_id.'_application").typeahead({
hint: true,
highlight: true,
minLength: 1,
classNames: {
menu: "typeahead-left"
}
},
{
source: '.$unique_id.'_application.ttAdapter(),
limit: '.$typeahead_limit.',
async: false,
templates: {
header: "<h5><strong>&nbsp;Applications</strong></h5>",
suggestion: Handlebars.compile(\'<p><small><i class="fa fa-link fa-sm icon-theme" aria-hidden="true"></i> <strong>{{name}}</strong> {{hostname}}</small></p>\')
}
});
var '.$unique_id.'_munin = new Bloodhound({
datumTokenizer: Bloodhound.tokenizers.obj.whitespace("munin"),
queryTokenizer: Bloodhound.tokenizers.whitespace,
remote: {
url: "ajax_search.php?search=%QUERY&type=munin",
filter: function (output) {
return $.map(output, function (item) {
return {
desc: item.name,
name: item.plugin,
hostname: item.hostname,
plugin: item.plugin,
device_id: item.device_id,
};
});
},
wildcard: "%QUERY"
}
});
'.$unique_id.'_munin.initialize();
$(".input_'.$unique_id.'_munin").typeahead({
hint: true,
highlight: true,
minLength: 1,
classNames: {
menu: "typeahead-left"
}
},
{
source: '.$unique_id.'_munin.ttAdapter(),
limit: '.$typeahead_limit.',
async: false,
templates: {
header: "<h5><strong>&nbsp;Munin</strong></h5>",
suggestion: Handlebars.compile(\'<p><small><i class="fa fa-link fa-sm icon-theme" aria-hidden="true"></i> <strong>{{plugin}}</strong> {{hostname}}</small></p>\')
}
});
var '.$unique_id.'_bill = new Bloodhound({
datumTokenizer: Bloodhound.tokenizers.obj.whitespace("munin"),
queryTokenizer: Bloodhound.tokenizers.whitespace,
remote: {
url: "ajax_search.php?search=%QUERY&type=bill",
filter: function (output) {
return $.map(output, function (item) {
return {
name: item.bill_name,
bill_id: item.bill_id,
};
});
},
wildcard: "%QUERY"
}
});
'.$unique_id.'_bill.initialize();
$(".input_'.$unique_id.'_bill").typeahead({
hint: true,
highlight: true,
minLength: 1,
classNames: {
menu: "typeahead-left"
}
},
{
source: '.$unique_id.'_bill.ttAdapter(),
limit: '.$typeahead_limit.',
async: false,
templates: {
header: "<h5><strong><i class=\'fa fa-money\'></i>&nbsp;Bill</strong></h5>",
suggestion: Handlebars.compile(\'<p><small><strong>{{name}}</strong></small></p>\')
}
});
switch_'.$unique_id.'($("#select_'.$unique_id.'").val());
}
function switch_'.$unique_id.'(data) {
$(".input_'.$unique_id.'").fadeOut();
if (data != undefined && data != "") {
data = data.split("_");
type = data.shift();
data = data.join("_");
$("#input_'.$unique_id.'_"+type).fadeIn();
}
}
</script>
<script id="js_'.$unique_id.'">
$(function() {
$("#js_'.$unique_id.'").parent().parent().data("settings","1");
'.$unique_id.'();
});
</script>';
} else {
$type = explode('_', $widget_settings['graph_type'], 2);
$type = array_shift($type);
$widget_settings['graph_'.$type] = json_decode($widget_settings['graph_'.$type], true)?:$widget_settings['graph_'.$type];
if ($type == 'device') {
if (empty($widget_settings['title'])) {
$widget_settings['title'] = $widget_settings['graph_device']['name']." / ".$widget_settings['graph_type'];
}
$param = 'device='.$widget_settings['graph_device']['device_id'];
} elseif ($type == 'application') {
$param = 'id='.$widget_settings['graph_'.$type]['app_id'];
} elseif ($type == 'munin') {
$param = 'device='.$widget_settings['graph_'.$type]['device_id'].'&plugin='.$widget_settings['graph_'.$type]['name'];
} elseif ($type == 'transit' || $type == 'peering' || $type == 'core' || $type == 'custom' || $type == 'manual' || $type == 'transpeer') {
if ($type == 'custom' || $type == 'manual') {
$type = $widget_settings['graph_'.$type];
$type = explode(',', $type);
}
if ($type == 'transpeer') {
$type = array('transit','peering');
}
$ports = get_ports_from_type($type);
foreach ($ports as $port) {
$tmp[] = $port['port_id'];
}
$param = 'id='.implode(',', $tmp);
$widget_settings['graph_type'] = 'multiport_bits_separate';
if (empty($widget_settings['title'])) {
$widget_settings['title'] = 'Overall '.ucfirst(htmlspecialchars($type)).' Bits ('.$widget_settings['graph_range'].')';
}
} else {
$param = 'id='.$widget_settings['graph_'.$type][$type.'_id'];
}
if (empty($widget_settings['title'])) {
$widget_settings['title'] = $widget_settings['graph_'.$type]['hostname']." / ".$widget_settings['graph_'.$type]['name']." / ".$widget_settings['graph_type'];
}
$common_output[] = '<a href="graphs/'.$param.'/type='.$widget_settings['graph_type'].'/from='.$config['time'][$widget_settings['graph_range']].'"><img class="minigraph-image" width="'.$widget_dimensions['x'].'" height="'.$widget_dimensions['y'].'" src="graph.php?'.$param.'&from='.$config['time'][$widget_settings['graph_range']].'&to='.$config['time']['now'].'&width='.$widget_dimensions['x'].'&height='.$widget_dimensions['y'].'&type='.$widget_settings['graph_type'].'&legend='.($widget_settings['graph_legend'] == 1 ? 'yes' : 'no').'&absolute=1"/></a>';
}

View File

@@ -1,72 +0,0 @@
<?php
/* Copyright (C) 2015 Daniel Preussker, QuxLabs UG <preussker@quxlabs.com>
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. */
/**
* Generic Image Widget
* @author Daniel Preussker
* @copyright 2015 Daniel Preussker, QuxLabs UG
* @license GPL
* @package LibreNMS
* @subpackage Widgets
*/
if (defined('SHOW_SETTINGS') || empty($widget_settings)) {
$common_output[] = '
<form class="form" onsubmit="widget_settings(this); return false;">
<div class="form-group input_'.$unique_id.'" id="input_'.$unique_id.'">
<div class="col-sm-2">
<label for="image_url" class="control-label">Title: </label>
</div>
<div class="col-sm-10">
<input type="text" class="form-control input_'.$unique_id.'" name="image_title" placeholder="Title" value="'.htmlspecialchars($widget_settings['image_title']).'">
</div>
</div>
<div class="form-group input_'.$unique_id.'" id="input_'.$unique_id.'">
<div class="col-sm-2">
<label for="image_url" class="control-label">Image URL: </label>
</div>
<div class="col-sm-10">
<input type="text" class="form-control input_'.$unique_id.'" name="image_url" placeholder="Image URL" value="'.htmlspecialchars($widget_settings['image_url']).'">
</div>
</div>
<div class="form-group input_'.$unique_id.'" id="input_'.$unique_id.'">
<div class="col-sm-2">
<label for="image_url" class="control-label">Target URL: </label>
</div>
<div class="col-sm-10">
<input type="text" class="form-control input_'.$unique_id.'" name="target_url" placeholder="Target URL" value="'.htmlspecialchars($widget_settings['target_url']).'">
</div>
</div>
<div class="form-group">
<div class="col-sm-2">
<button type="submit" class="btn btn-default">Set</button>
</div>
</div>
</form>';
} else {
$widget_settings['title'] = $widget_settings['image_title'];
if (strstr($widget_settings['image_url'], '@AUTO_HEIGHT@')) {
$widget_settings['image_url'] = str_replace('@AUTO_HEIGHT@', $widget_dimensions['y'], $widget_settings['image_url']);
}
if (strstr($widget_settings['image_url'], '@AUTO_WIDTH@')) {
$widget_settings['image_url'] = str_replace('@AUTO_WIDTH@', $widget_dimensions['x'], $widget_settings['image_url']);
}
if (strstr($widget_settings['image_url'], '?')) {
$widget_settings['image_url'] .= "&".mt_rand();
} else {
$widget_settings['image_url'] .= "?".mt_rand();
}
$common_output[] = '<a target="_blank" rel="noopener" href="'.$widget_settings['target_url'].'"><img class="minigraph-image" style="max-width: '.$widget_dimensions['x'].'px; max-height:'.$widget_dimensions['y'].'px;" src="'.$widget_settings['image_url'].'"/></a>';
}

View File

@@ -17,7 +17,7 @@
* @author LibreNMS Contributors * @author LibreNMS Contributors
*/ */
use LibreNMS\Authentication\LegacyAuth; use App\Models\Device;
if (empty($results_limit)) { if (empty($results_limit)) {
$results_limit = 25; $results_limit = 25;
@@ -28,11 +28,12 @@ $tmp_output = '
<table id="graylog" class="table table-hover table-condensed graylog"> <table id="graylog" class="table table-hover table-condensed graylog">
<thead> <thead>
<tr> <tr>
<th data-column-id="timestamp">Timestamp</th> <th data-column-id="severity" data-sortable="false"></th>
<th data-column-id="level">Level</th> <th data-column-id="timestamp" data-formatter="browserTime">Timestamp</th>
<th data-column-id="source">Source</th> <th data-column-id="level" data-sortable="false">Level</th>
<th data-column-id="message">Message</th> <th data-column-id="source">Source</th>
<th data-column-id="facility">Facility</th> <th data-column-id="message" data-sortable="false">Message</th>
<th data-column-id="facility" data-sortable="false">Facility</th>
</tr> </tr>
</thead> </thead>
</table> </table>
@@ -45,28 +46,25 @@ searchbar = "<div id=\"{{ctx.id}}\" class=\"{{css.header}}\"><div class=\"row\">
"Filter: "+ "Filter: "+
'; ';
$tmp_output .= '"<div class=\"form-group\"><select name=\"stream\" id=\"stream\" class=\"form-control\" data-placeholder=\"All Messages\">"+';
if ($vars['stream']) {
$tmp_output .= '"<option value=\"' . display($vars['stream']) . '\">' . display($vars['stream']) . '</option>" +';
$filter_device = $device->device_id;
}
$tmp_output .= '"</select>&nbsp;</div>"+';
if (!empty($filter_device)) { if (!empty($filter_device)) {
$tmp_output .= ' $tmp_output .= '
"<input type=\"hidden\" name=\"hostname\" id=\"hostname\" value=\"'. $filter_device .'\">"+ "<input type=\"hidden\" name=\"device\" id=\"device\" value=\"'. $filter_device .'\">"+
'; ';
} else { } else {
$tmp_output .= ' $tmp_output .= '
"<div class=\"form-group\"><select name=\"hostname\" id=\"hostname\" class=\"form-control input-sm\">"+ "<div class=\"form-group\"><select name=\"device\" id=\"device\" class=\"form-control\" data-placeholder=\"All Devices\">"+
"<option value=\"\">All devices</option>"+
'; ';
if ($vars['device'] && $device = Device::find($vars['device'])) {
if (LegacyAuth::user()->hasGlobalRead()) { $tmp_output .= '"<option value=\"' . $device->device_id . '\">' . $device->displayName() . '</option>" +';
$results = dbFetchRows("SELECT `hostname` FROM `devices` GROUP BY `hostname` ORDER BY `hostname`"); $filter_device = $device->device_id;
} else {
$results = dbFetchRows("SELECT `D`.`hostname` FROM `devices` AS `D`, `devices_perms` AS `P` WHERE `P`.`user_id` = ? AND `P`.`device_id` = `D`.`device_id` GROUP BY `hostname` ORDER BY `hostname`", array(LegacyAuth::id()));
}
foreach ($results as $data) {
$tmp_output .= '"<option value=\"'.$data['hostname'].'\""+';
if (isset($vars['hostname']) && $data['hostname'] == $vars['hostname']) {
$tmp_output .= '"selected"+';
}
$tmp_output .= '">'.$data['hostname'].'</option>"+';
} }
$tmp_output .= ' $tmp_output .= '
@@ -74,10 +72,6 @@ if (!empty($filter_device)) {
'; ';
} }
if (empty($filter_device) && isset($_POST['hostname'])) {
$filter_device = mres($_POST['hostname']);
}
if (isset($config['graylog']['timezone'])) { if (isset($config['graylog']['timezone'])) {
$timezone = 'row.timestamp;'; $timezone = 'row.timestamp;';
} else { } else {
@@ -85,7 +79,8 @@ if (isset($config['graylog']['timezone'])) {
} }
$tmp_output .= ' $tmp_output .= '
"<div class=\"form-group\"><select name=\"range\" class=\"form-group input-sm\">"+ "<div class=\"form-group\"><select name=\"range\" class=\"form-control\">"+
"<option value=\"0\">Search all time</option>"+
"<option value=\"300\">Search last 5 minutes</option>"+ "<option value=\"300\">Search last 5 minutes</option>"+
"<option value=\"900\">Search last 15 minutes</option>"+ "<option value=\"900\">Search last 15 minutes</option>"+
"<option value=\"1800\">Search last 30 minutes</option>"+ "<option value=\"1800\">Search last 30 minutes</option>"+
@@ -98,9 +93,8 @@ $tmp_output .= '
"<option value=\"604800\">Search last 7 days</option>"+ "<option value=\"604800\">Search last 7 days</option>"+
"<option value=\"1209600\">Search last 14 days</option>"+ "<option value=\"1209600\">Search last 14 days</option>"+
"<option value=\"2592000\">Search last 30 days</option>"+ "<option value=\"2592000\">Search last 30 days</option>"+
"<option value=\"0\">Search all time</option>"+
"</select>&nbsp;</div>"+ "</select>&nbsp;</div>"+
"<button type=\"submit\" class=\"btn btn-success btn-sm\">Filter</button>&nbsp;"+ "<button type=\"submit\" class=\"btn btn-success\">Filter</button>&nbsp;"+
"</form></div>"+ "</form></div>"+
"<div class=\"col-sm-4 actionBar\"><p class=\"{{css.search}}\"></p><p class=\"{{css.actions}}\"></p></div></div></div>" "<div class=\"col-sm-4 actionBar\"><p class=\"{{css.search}}\"></p><p class=\"{{css.actions}}\"></p></div></div></div>"
@@ -126,13 +120,16 @@ $tmp_output .= '
post: function () post: function ()
{ {
return { return {
id: "graylog", stream: "' . (isset($_POST['stream']) ? mres($_POST['stream']) : '') . '",
hostname: "' . (isset($filter_device) ? $filter_device : '') . '", device: "' . (isset($filter_device) ? $filter_device : '') . '",
range: "' . (isset($_POST['range']) ? mres($_POST['range']) : '') . '" range: "' . (isset($_POST['range']) ? mres($_POST['range']) : '') . '"
}; };
}, },
url: "ajax_table.php", url: "ajax/table/graylog",
}); });
init_select2("#stream", "graylog-streams", {}, "' . (isset($_POST['stream']) ? mres($_POST['stream']) : '') . '");
init_select2("#device", "device", {limit: 100}, "' . (isset($filter_device) ? $filter_device : '') . '");
</script> </script>
'; ';

View File

@@ -1,44 +0,0 @@
<?php
/*
* LibreNMS
*
* Copyright (c) 2015 Neil Lathwood <https://github.com/laf/ http://www.lathwood.co.uk/fa>
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your
* option) any later version. Please see LICENSE.txt at the top level of
* the source code distribution for details.
*/
if (defined('SHOW_SETTINGS') || empty($widget_settings)) {
$common_output[] = '
<form class="form-horizontal" onsubmit="widget_settings(this); return false;">
<div class="form-group">
<div class="col-sm-12">
The following html tags are supported: &lt;b&gt;, &lt;iframe&gt;, &lt;i&gt;, &lt;ul&gt;, &lt;ol&gt;, &lt;li&gt;, &lt;h1&gt;, &lt;h2&gt;, &lt;h3&gt;, &lt;h4&gt;, &lt;br&gt;, &lt;p&gt;. If you want just text then wrap in &lt;pre&gt;&lt;/pre&gt;
</div>
</div>
<div class="form-group">
<label for="'.$unique_id.'_notes" class="col-sm-1" control-label"></label>
<div class="col-sm-11">
<textarea name="notes" id="'.$unique_id.'_notes" rows="3" class="form-control">'.htmlspecialchars($widget_settings['notes']).'</textarea>
</div>
</div>
<div class="form-group">
<div class="col-sm-1">
<button type="submit" class="btn btn-sm btn-primary">Set</button>
</div>
</div>
</form>';
} else {
$tmp_config = array(
'HTML.Allowed' => 'b,iframe[frameborder|src|width|height],i,ul,ol,li,h1,h2,h3,h4,br,p,pre',
'HTML.Trusted' => true,
'HTML.SafeIframe' => true,
'URI.SafeIframeRegexp' => '%^(https?:)?//%',
);
$common_output[] = display(nl2br($widget_settings['notes']), $tmp_config);
unset($tmp_config);
}

View File

@@ -1,139 +0,0 @@
<?php
use LibreNMS\Authentication\LegacyAuth;
$device_id = $widget_settings['device'];
$column = $widget_settings['columnsize'];
if (defined('SHOW_SETTINGS') || empty($widget_settings)) {
$cur_col_size = isset($widget_settings['columnsize']) ? $widget_settings['columnsize'] : '';
$cur_dev = isset($widget_settings['device']) ? $widget_settings['device'] : '';
$cur_title = isset($widget_settings['title']) ? $widget_settings['title'] : '';
$common_output[] = '
<form class="form" onsubmit="widget_settings(this); return false;">
<div class="form-group">
<div class="col-sm-4">
<label for="title" class="control-label availability-map-widget-header">Widget title</label>
</div>
<div class="col-sm-6">
<input type="text" class="form-control" name="title" placeholder="Custom title for widget" value="'.htmlspecialchars($cur_title).'">
</div>
</div>
<div class="form-group">
<div class="col-sm-4">
<label for="device" class="control-label availability-map-widget-header">Server</label>
</div>
<div class="col-sm-6">
<select id="device" name="device" class="form-control">';
if (LegacyAuth::user()->hasGlobalRead()) {
$sql = "SELECT `devices`.`device_id`, `hostname` FROM `devices` WHERE disabled = 0 AND `type` = 'server' ORDER BY `hostname` ASC";
$param = array();
} else {
$sql = "SELECT `devices`.`device_id`, `hostname` FROM `devices` LEFT JOIN `devices_perms` AS `DP` ON `devices`.`device_id` = `DP`.`device_id` WHERE disabled = 0 AND `type` = 'server' AND `DP`.`user_id`=? ORDER BY `hostname` ASC";
$param = array(LegacyAuth::id());
}
foreach (dbFetchRows($sql, $param) as $dev) {
if ($dev['device_id'] == $cur_dev) {
$selected = 'selected';
} else {
$selected = '';
}
$common_output[] = '<option value="'.$dev['device_id'].'" '.$selected.'>'.$dev['hostname'].'</option>';
}
$common_output[] ='</select>
</div>
</div>
<div class="form-group">
<div class="col-sm-4">
<label for="columnsize" class="control-label availability-map-widget-header">Column Size</label>
</div>
<div class="col-sm-6">
<select name="columnsize" class="form-control">
<option value="2"'.($cur_col_size == 2 ? ' selected' : ' ').'>2</option>
<option value="3"'.($cur_col_size == 3 ? ' selected' : ' ').'>3</option>
<option value="4"'.($cur_col_size == 4 ? ' selected' : ' ').'>4</option>
<option value="6"'.($cur_col_size == 6 ? ' selected' : ' ').'>6</option>
<option value="12"'.($cur_col_size == 12 ? ' selected' : ' ').'>12</option>
</select>
</div>
</div>
<div class="form-group">
<div class="col-sm-10">
<button type="submit" class="btn btn-default">Set</button>
</div>
</div>
</form>';
} else {
if (device_permitted($device_id)) {
$cpu = dbFetchCell("SELECT AVG(processor_usage) from processors WHERE device_id = ?", array($device_id));
$mem = dbFetchRows("SELECT mempool_descr,
ROUND(mempool_used / (1024*1024), 0) as used,
ROUND(mempool_total /(1024*1024), 0) as total
FROM mempools WHERE device_id = ?", array($device_id));
$disk = dbFetchRows("SELECT storage_descr,
ROUND(storage_used / (1024*1024), 0) as used,
ROUND(storage_size / (1024*1024), 0) as total
FROM storage WHERE device_id = ?", array($device_id));
$colno = 12 / $column;
if (!$cpu) {
$cpu = 0;
}
$common_output[] = '
<div class="col-sm-' . $colno . '">
<div id="cpu-' . $unique_id . '" ></div>
</div>';
$i = 0;
foreach ($mem as $m) {
$common_output[] = '<div class="col-sm-' . $colno . '">
<div id="mem-' . $i . '-' . $unique_id . '" ></div>
</div>';
$mem_js_output .= "var memgauge" . $i . " = new JustGage({
id: 'mem-" . $i . "-" . $unique_id . "',
value: " . $m['used'] . ",
min: 0,
max: " . $m['total'] . ",
label: 'Mbytes',
valueFontSize: '2px',
title: '" . $m['mempool_descr'] . " Usage'
});\n";
$i++;
}
$i = 0;
foreach ($disk as $d) {
$common_output[] = '<div class="col-sm-' . $colno . '">
<div id="disk-' . $i . '-' . $unique_id . '" ></div>
</div>';
$disk_js_output .= "var diskgauge" . $i . " = new JustGage({
id: 'disk-" . $i . "-" . $unique_id . "',
value: " . $d['used'] . ",
min: 0,
max: " . $d['total'] . ",
label: 'Mbytes',
valueFontSize: '2px',
title: '" . substr($d['storage_descr'], 0, 20) . " Usage'
});\n";
$i++;
}
$common_output[] = '<script src="js/raphael-min.js"></script>';
$common_output[] = '<script src="js/justgage.js"></script>';
$common_output[] = "<script>
var cpugauge = new JustGage({
id: 'cpu-" . $unique_id . "',
value: " . $cpu . ",
min: 0,
max: 100,
title: 'CPU Usage',
symbol: '%'
});\n";
$common_output[] = $mem_js_output;
$common_output[] = $disk_js_output;
$common_output[] = '</script>';
} else {
$common_output[] = 'You do not have permission to view this device';
}
}

View File

@@ -1,343 +0,0 @@
<?php
/* Copyright (C) 2015 Sergiusz Paprzycki <serek@walcz.net>
* Copyright (C) 2016 Cercel Valentin <crc@nuamchefazi.ro>
*
* This widget is based on legacy frontpage module created by Paul Gear.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
use LibreNMS\Authentication\LegacyAuth;
$top_query = $widget_settings['top_query'] ?: 'traffic';
$sort_order = $widget_settings['sort_order'];
$selected_sort_asc = '';
$selected_sort_desc = '';
if ($sort_order === 'asc') {
$selected_sort_asc = 'selected';
} elseif ($sort_order === 'desc') {
$selected_sort_desc = 'selected';
}
$selected_traffic = '';
$selected_uptime = '';
$selected_ping = '';
$selected_cpu = '';
$selected_ram = '';
$selected_poller = '';
$selected_storage = '';
switch ($top_query) {
case "traffic":
$table_header = 'Traffic';
$selected_traffic = 'selected';
$graph_type = 'device_bits';
$graph_params = array();
break;
case "uptime":
$table_header = 'Uptime';
$selected_uptime = 'selected';
$graph_type = 'device_uptime';
$graph_params = array('tab' => 'graphs', 'group' => 'system');
break;
case "ping":
$table_header = 'Response time';
$selected_ping = 'selected';
$graph_type = 'device_ping_perf';
$graph_params = array('tab' => 'graphs', 'group' => 'poller');
break;
case "cpu":
$table_header = 'CPU Load';
$selected_cpu = 'selected';
$graph_type = 'device_processor';
$graph_params = array('tab' => 'health', 'metric' => 'processor');
break;
case "ram":
$table_header = 'Memory usage';
$selected_ram = 'selected';
$graph_type = 'device_mempool';
$graph_params = array('tab' => 'health', 'metric' => 'mempool');
break;
case "poller":
$table_header = 'Poller duration';
$selected_poller = 'selected';
$graph_type = 'device_poller_perf';
$graph_params = array('tab' => 'graphs', 'group' => 'poller');
break;
case "storage":
$table_header = 'Disk usage';
$selected_storage = 'selected';
$graph_type = 'device_storage';
$graph_params = array('tab' => 'health', 'metric' => 'storage');
break;
}
$widget_settings['device_count'] = $widget_settings['device_count'] > 0 ? $widget_settings['device_count'] : 5;
$widget_settings['time_interval'] = $widget_settings['time_interval'] > 0 ? $widget_settings['time_interval'] : 15;
if (defined('SHOW_SETTINGS') || empty($widget_settings)) {
$common_output[] = '
<form class="form" onsubmit="widget_settings(this); return false;">
<div class="form-group">
<div class="col-sm-4">
<label for="title" class="control-label availability-map-widget-header">Widget title</label>
</div>
<div class="col-sm-6">
<input type="text" class="form-control" name="title" placeholder="Custom title for widget" value="' . htmlspecialchars($widget_settings['title']) . '">
</div>
</div>
<div class="form-group">
<div class="col-sm-4">
<label for="top_query" class="control-label availability-map-widget-header">Top query</label>
</div>
<div class="col-sm-6">
<select class="form-control" name="top_query">
<option value="traffic" ' . $selected_traffic . '>Traffic</option>
<option value="uptime" ' . $selected_uptime . '>Uptime</option>
<option value="ping" ' . $selected_ping . '>Response time</option>
<option value="poller" ' . $selected_poller . '>Poller duration</option>
<option value="cpu" ' . $selected_cpu . '>Processor load</option>
<option value="ram" ' . $selected_ram . '>Memory usage</option>
<option value="storage" ' . $selected_storage . '>Disk usage</option>
</select>
</div>
</div>
<div class="form-group">
<div class="col-sm-4">
<label for="top_query" class="control-label availability-map-widget-header">Sort order</label>
</div>
<div class="col-sm-6">
<select class="form-control" name="sort_order">
<option value="asc" ' . $selected_sort_asc . '>Ascending</option>
<option value="desc" ' . $selected_sort_desc . '>Descending</option>
</select>
</div>
</div>
<div class="form-group">
<div class="col-sm-4">
<label for="graph_type" class="control-label availability-map-widget-header">Number of Devices</label>
</div>
<div class="col-sm-6">
<input class="form-control" onkeypress="return (event.charCode == 8 || event.charCode == 0) ? null : event.charCode >= 48 && event.charCode <= 57" name="device_count" id="input_count_' . $unique_id . '" value="' . $widget_settings['device_count'] . '">
</div>
</div>
<div class="form-group">
<div class="col-sm-4">
<label for="graph_type" class="control-label availability-map-widget-header">Time interval (minutes)</label>
</div>
<div class="col-sm-6">
<input class="form-control" onkeypress="return (event.charCode == 8 || event.charCode == 0) ? null : event.charCode >= 48 && event.charCode <= 57" name="time_interval" id="input_time_' . $unique_id . '" value="' . $widget_settings['time_interval'] . '">
</div>
</div>
<div class="form-group">
<div class="col-sm-10">
<button type="submit" class="btn btn-default">Set</button>
</div>
</div>
</form>';
} else {
$interval = $widget_settings['time_interval'];
(integer)$interval_seconds = ($interval * 60);
(integer)$device_count = $widget_settings['device_count'];
$common_output[] = '<h4>Top ' . $device_count . ' devices (last ' . $interval . ' minutes)</h4>';
$params = ['interval' => $interval_seconds, 'count' => $device_count];
if (!LegacyAuth::user()->hasGlobalRead()) {
$params['user'] = LegacyAuth::id();
}
if ($top_query === 'traffic') {
if (LegacyAuth::user()->hasGlobalRead()) {
$query = '
SELECT *, sum(p.ifInOctets_rate + p.ifOutOctets_rate) as total
FROM ports as p, devices as d
WHERE d.device_id = p.device_id
AND unix_timestamp() - p.poll_time < :interval
AND ( p.ifInOctets_rate > 0
OR p.ifOutOctets_rate > 0 )
GROUP BY d.device_id
ORDER BY total ' . $sort_order . '
LIMIT :count
';
} else {
$query = '
SELECT *, sum(p.ifInOctets_rate + p.ifOutOctets_rate) as total
FROM ports as p, devices as d, `devices_perms` AS `P`
WHERE `P`.`user_id` = :user AND `P`.`device_id` = `d`.`device_id` AND
d.device_id = p.device_id
AND unix_timestamp() - p.poll_time < :interval
AND ( p.ifInOctets_rate > 0
OR p.ifOutOctets_rate > 0 )
GROUP BY d.device_id
ORDER BY total ' . $sort_order . '
LIMIT :count
';
}
} elseif ($top_query === 'uptime') {
if (LegacyAuth::user()->hasGlobalRead()) {
$query = 'SELECT `uptime`, `hostname`, `last_polled`, `device_id`, `sysName`
FROM `devices`
WHERE unix_timestamp() - UNIX_TIMESTAMP(`last_polled`) < :interval
ORDER BY `uptime` ' . $sort_order . '
LIMIT :count';
} else {
$query = 'SELECT `uptime`, `hostname`, `last_polled`, `d`.`device_id`, `d`.`sysName`
FROM `devices` as `d`, `devices_perms` AS `P`
WHERE `P`.`user_id` = :user
AND `P`.`device_id` = `d`.`device_id`
AND unix_timestamp() - UNIX_TIMESTAMP(`last_polled`) < :interval
ORDER BY `uptime` ' . $sort_order . '
LIMIT :count';
}
} elseif ($top_query === 'ping') {
if (LegacyAuth::user()->hasGlobalRead()) {
$query = 'SELECT `last_ping_timetaken`, `hostname`, `last_polled`, `device_id`, `sysName`
FROM `devices`
WHERE unix_timestamp() - UNIX_TIMESTAMP(`last_polled`) < :interval
ORDER BY `last_ping_timetaken` ' . $sort_order . '
LIMIT :count';
} else {
$query = 'SELECT `last_ping_timetaken`, `hostname`, `last_polled`, `d`.`device_id`, `d`.`sysName`
FROM `devices` as `d`, `devices_perms` AS `P`
WHERE `P`.`user_id` = :user
AND `P`.`device_id` = `d`.`device_id`
AND unix_timestamp() - UNIX_TIMESTAMP(`last_polled`) < :interval
ORDER BY `last_ping_timetaken` ' . $sort_order . '
LIMIT :count';
}
} elseif ($top_query === 'cpu') {
if (LegacyAuth::user()->hasGlobalRead()) {
$query = 'SELECT `hostname`, `last_polled`, `d`.`device_id`, avg(`processor_usage`) as `cpuload`, `d`.`sysName`
FROM `processors` AS `procs`, `devices` AS `d`
WHERE `d`.`device_id` = `procs`.`device_id`
AND unix_timestamp() - UNIX_TIMESTAMP(`last_polled`) < :interval
GROUP BY `d`.`device_id`, `d`.`hostname`, `d`.`last_polled`, `d`.`sysName`
ORDER BY `cpuload` ' . $sort_order . '
LIMIT :count';
} else {
$query = 'SELECT `hostname`, `last_polled`, `d`.`device_id`, avg(`processor_usage`) as `cpuload`, `d`.`sysName`
FROM `processors` AS procs, `devices` AS `d`, `devices_perms` AS `P`
WHERE `P`.`user_id` = :user AND `P`.`device_id` = `procs`.`device_id` AND `P`.`device_id` = `d`.`device_id`
AND unix_timestamp() - UNIX_TIMESTAMP(`last_polled`) < :interval
GROUP BY `procs`.`device_id`, `d`.`hostname`, `d`.`last_polled`, `d`.`sysName`
ORDER BY `cpuload` ' . $sort_order . '
LIMIT :count';
}
} elseif ($top_query === 'ram') {
if (LegacyAuth::user()->hasGlobalRead()) {
$query = 'SELECT `hostname`, `last_polled`, `d`.`device_id`, `mempool_perc`, `d`.`sysName`
FROM `mempools` as `mem`, `devices` as `d`
WHERE `d`.`device_id` = `mem`.`device_id`
AND `mempool_descr` IN (\'Physical memory\',\'Memory\')
AND unix_timestamp() - UNIX_TIMESTAMP(`last_polled`) < :interval
ORDER BY `mempool_perc` ' . $sort_order . '
LIMIT :count';
} else {
$query = 'SELECT `hostname`, `last_polled`, `d`.`device_id`, `mempool_perc`, `d`.`sysName`
FROM `mempools` as `mem`, `devices` as `d`, `devices_perms` AS `P`
WHERE `P`.`user_id` = :user AND `P`.`device_id` = `mem`.`device_id` AND `P`.`device_id` = `d`.`device_id`
AND `mempool_descr` IN (\'Physical memory\',\'Memory\')
AND unix_timestamp() - UNIX_TIMESTAMP(`last_polled`) < :interval
ORDER BY `mempool_perc` ' . $sort_order . '
LIMIT :count';
}
} elseif ($top_query === 'storage') {
if (LegacyAuth::user()->hasGlobalRead()) {
$query = 'SELECT `hostname`, `last_polled`, `d`.`device_id`, `storage_perc`, `d`.`sysName`, `storage_descr`, `storage_perc_warn`, `storage_id`
FROM `storage` as `disk`, `devices` as `d`
WHERE `d`.`device_id` = `disk`.`device_id`
AND `d`.`type` = \'server\'
AND unix_timestamp() - UNIX_TIMESTAMP(`last_polled`) < :interval
ORDER BY `storage_perc` ' . $sort_order . '
LIMIT :count';
} else {
$query = 'SELECT `hostname`, `last_polled`, `d`.`device_id`, `storage_perc`, `d`.`sysName`, `storage_descr`, `storage_perc_warn`, `storage_id`
FROM `storage` as `disk`, `devices` as `d`, `devices_perms` AS `P`
WHERE `P`.`user_id` = :user AND `P`.`device_id` = `disk`.`device_id` AND `P`.`device_id` = `d`.`device_id`
AND `d`.`type` = \'server\'
AND unix_timestamp() - UNIX_TIMESTAMP(`last_polled`) < :interval
ORDER BY `storage_perc` ' . $sort_order . '
LIMIT :count';
}
} elseif ($top_query === 'poller') {
if (LegacyAuth::user()->hasGlobalRead()) {
$query = 'SELECT `last_polled_timetaken`, `hostname`, `last_polled`, `device_id`, `sysName`
FROM `devices`
WHERE unix_timestamp() - UNIX_TIMESTAMP(`last_polled`) < :interval
ORDER BY `last_polled_timetaken` ' . $sort_order . '
LIMIT :count';
} else {
$query = 'SELECT `last_polled_timetaken`, `hostname`, `last_polled`, `d`.`device_id`, `d`.`sysName`
FROM `devices` as `d`, `devices_perms` AS `P`
WHERE `P`.`user_id` = :user
AND `P`.`device_id` = `d`.`device_id`
AND unix_timestamp() - UNIX_TIMESTAMP(`last_polled`) < :interval
ORDER BY `last_polled_timetaken` ' . $sort_order . '
LIMIT :count';
}
}
$common_output[] = '
<div class="table-responsive">
<table class="table table-hover table-condensed table-striped bootgrid-table">
<thead>
<tr>
<th class="text-left">Device</th>';
if ($top_query == 'storage') {
$common_output[] = '<th class="text-left">Storage Device</th>';
}
$common_output[] = ' <th class="text-left">' . $table_header . '</a></th>
</tr>
</thead>
<tbody>';
foreach (dbFetchRows($query, $params) as $result) {
$common_output[] = '
<tr>
<td class="text-left">' . generate_device_link($result, shorthost($result['hostname'])) . '</td>
<td class="text-left">';
if ($top_query == 'storage') {
$graph_array = array();
$graph_array['height'] = '100';
$graph_array['width'] = '210';
$graph_array['to'] = $config['time']['now'];
$graph_array['id'] = $drive['storage_id'];
$graph_array['type'] = $graph_type;
$graph_array['from'] = $config['time']['day'];
$graph_array['legend'] = 'no';
$overlib_content = generate_overlib_content($graph_array, $result['hostname'].' - '.$result['storage_descr']);
$link_array = $graph_array;
$link_array['page'] = 'graphs';
unset($link_array['height'], $link_array['width'], $link_array['legend']);
$link = generate_url($link_array);
$percent = $result['storage_perc'];
$background = get_percentage_colours($percent, $result['storage_perc_warn']);
$common_output[] = shorten_text($result['storage_descr'], 50).'</td><td class="text-left">';
$common_output[] = overlib_link($link, print_percentage_bar(150, 20, $percent, null, 'ffffff', $background['left'], $percent.'%', 'ffffff', $background['right']), $overlib_content);
} else {
$common_output[] = generate_device_link($result, generate_minigraph_image($result, $config['time']['day'], $config['time']['now'], $graph_type, 'no', 150, 21), $graph_params, 0, 0, 0);
}
$common_output[] = '</td></tr>';
}
$common_output[] = '
</tbody>
</table>
</div>';
}

View File

@@ -1,165 +0,0 @@
<?php
/* Copyright (C) 2015 Sergiusz Paprzycki <serek@walcz.net>
*
* This widget is based on legacy frontpage module created by Paul Gear.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. */
/**
* Top interfaces by traffic
* @author Sergiusz Paprzycki
* @copyright 2015 Sergiusz Paprzycki <serek@walcz.net>
* @license GPL
* @package LibreNMS
* @subpackage Widgets
*/
use LibreNMS\Authentication\LegacyAuth;
if (defined('SHOW_SETTINGS') || empty($widget_settings)) {
$common_output[] = '
<form class="form-horizontal" onsubmit="widget_settings(this); return false;">
<div class="form-group">
<label for="interface_count" class="col-sm-5 control-label">Number of Interfaces: </label>
<div class="col-sm-7">
<input class="form-control" type="number" min="0" step="1" name="interface_count" id="input_count_'.$unique_id.'" placeholder="ie. 5" value="'.$widget_settings['interface_count'].'">
</div>
</div>
<div class="form-group">
<label for="time_interval" class="col-sm-5 control-label">Last Polled within (minutes): </label>
<div class="col-sm-7">
<input class="form-control" type="number" min="5" step="1" name="time_interval" id="input_time_'.$unique_id.'" placeholder="ie. 15" value="'.$widget_settings['time_interval'].'">
</div>
</div>
<div class="form-group">
<label for="interface_filter" class="col-sm-5 control-label">Interface Type: </label>
<div class="col-sm-7">
<input class="form-control" name="interface_filter" id="input_filter_'.$unique_id.'" placeholder="Any" value="'.$widget_settings['interface_filter'].'">
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-5 col-sm-7">
<button type="submit" class="btn btn-default">Set</button>
</div>
</div>
</form>
<script>
$(function() {
var '.$unique_id.'_filter = new Bloodhound({
datumTokenizer: Bloodhound.tokenizers.obj.whitespace("name"),
queryTokenizer: Bloodhound.tokenizers.whitespace,
remote: {
url: "ajax_search.php?search=%QUERY&type=iftype",
filter: function (output) {
return $.map(output, function (item) {
return {
filter: item.filter
};
});
},
wildcard: "%QUERY"
}
});
'.$unique_id.'_filter.initialize();
$("#input_filter_'.$unique_id.'").typeahead({
hint: true,
highlight: true,
minLength: 1,
classNames: {
menu: "typeahead-left"
}
},
{
source: '.$unique_id.'_filter.ttAdapter(),
async: false,
display: "filter",
templates: {
header: "<h5><strong>&nbsp;Interface Types</strong></h5>",
suggestion: Handlebars.compile("<p>{{filter}}</p>")
}
});
});
</script>
<style>
.twitter-typeahead {
width: 100%;
}
</style>
';
} else {
$interval = $widget_settings['time_interval'];
(integer) $lastpoll_seconds = ($interval * 60) ?: 300;
(integer) $interface_count = $widget_settings['interface_count'] ?: 5;
$params = ['lastpoll' => $lastpoll_seconds, 'count' => $interface_count, 'filter1' => ($widget_settings['interface_filter']?:(int)1), 'filter2' => ($widget_settings['interface_filter']?:(int)1)];
if (!LegacyAuth::user()->hasGlobalRead()) {
$params['user1'] = LegacyAuth::id();
$params['user2'] = LegacyAuth::id();
}
if (LegacyAuth::user()->hasGlobalRead()) {
$query = '
SELECT p.*, devices.*, p.ifInOctets_rate + p.ifOutOctets_rate as total
FROM ports as p
INNER JOIN devices ON p.device_id = devices.device_id
AND unix_timestamp() - p.poll_time <= :lastpoll
AND ( p.ifType = :filter1 || 1 = :filter2 )
AND ( p.ifInOctets_rate > 0 || p.ifOutOctets_rate > 0 )
ORDER BY total DESC
LIMIT :count
';
} else {
$query = '
SELECT ports.*, devices.*, ports.ifInOctets_rate + ports.ifOutOctets_rate as total
FROM ports
INNER JOIN devices ON ports.device_id = devices.device_id
LEFT JOIN ports_perms ON ports.port_id = ports_perms.port_id
LEFT JOIN devices_perms ON devices.device_id = devices_perms.device_id
WHERE ( ports_perms.user_id = :user1 || devices_perms.user_id = :user2 )
AND unix_timestamp() - ports.poll_time <= :lastpoll
AND ( ports.ifType = :filter1 || 1 = :filter2 )
AND ( ports.ifInOctets_rate > 0 || ports.ifOutOctets_rate > 0 )
GROUP BY ports.port_id
ORDER BY total DESC
LIMIT :count
';
}
$common_output[] = '
<h4>Top '.$interface_count.' interfaces polled within '.$interval.' minutes</h4>
<div class="table-responsive">
<table class="table table-hover table-condensed table-striped bootgrid-table">
<thead>
<tr>
<th class="text-left">Device</th>
<th class="text-left">Interface</th>
<th class="text-left">Total traffic</a></th>
</tr>
</thead>
<tbody>
';
foreach (dbFetchRows($query, $params) as $result) {
$result = cleanPort($result);
$common_output[] = '
<tr>
<td class="text-left">'.generate_device_link($result, shorthost($result['hostname'])).'</td>
<td class="text-left">'.generate_port_link($result, shorten_interface_type($result['ifName'])).'</td>
<td class="text-left">'.generate_port_link($result, generate_port_thumbnail($result)).'</td>
</tr>
';
}
$common_output[] = '
</tbody>
</table>
</div>
';
}

View File

@@ -22,118 +22,30 @@
* @subpackage Frontpage * @subpackage Frontpage
*/ */
use LibreNMS\Authentication\LegacyAuth; use Auth;
use LibreNMS\Config; use LibreNMS\Config;
require_once $config['install_dir'] . '/includes/alerts.inc.php'; $install_dir = Config::get('install_dir');
require_once $config['install_dir'] . '/includes/device-groups.inc.php'; require_once $install_dir . '/includes/alerts.inc.php';
require_once $install_dir . '/includes/device-groups.inc.php';
if ($config['map']['engine'] == 'leaflet') { if (Config::get('map.engine', 'leaflet') == 'leaflet') {
if (defined('SHOW_SETTINGS') && $config['front_page'] == "pages/front/tiles.php") { $temp_output = '
$temp_output = '
<form class="form" onsubmit="widget_settings(this); return false;">
<div class="form-group">
<div class="col-sm-4">
<label for="init_lat" class="control-label">Initial Latitude: </label>
</div>
<div class="col-sm-8">
<input class="form-control" name="init_lat" id="input_lat_'.$unique_id.'" value="'.$widget_settings['init_lat'].'" placeholder="ie. 51.4800 for Greenwich">
</div>
</div>
<div class="form-group">
<div class="col-sm-4">
<label for="init_lng" class="control-label">Initial Longitude: </label>
</div>
<div class="col-sm-6">
<input class="form-control" name="init_lng" id="input_lng_'.$unique_id.'" value="'.$widget_settings['init_lng'].'" placeholder="ie. 0 for Greenwich">
</div>
</div>
<div class="form-group">
<div class="col-sm-4">
<label for="init_zoom" class="control-label">Initial Zoom: </label>
</div>
<div class="col-sm-8">
<select class="form-control" name="init_zoom" id="select_zoom'.$unique_id.'">
';
for ($i=0; $i<19; $i++) {
if ($i == $widget_settings['init_zoom']) {
$temp_output .= '<option selected value="'.$i.'">'.$i.'</option>';
} else {
$temp_output .= '<option value="'.$i.'">'.$i.'</option>';
}
}
$temp_output .= '
</select>
</div>
</div>
<div class="form-group">
<div class="col-sm-4">
<label for="group_radius" class="control-label">Grouping radius: </label>
</div>
<div class="col-sm-8">
<input class="form-control" name="group_radius" id="input_radius_'.$unique_id.'" value="'.$widget_settings['group_radius'].'" placeholder="default 80">
</div>
</div>
<div class="form-group">
<div class="col-sm-4">
<label for="status" class="control-label">Show devices: </label>
</div>
<div class="col-sm-8">
<select class="form-control" name="status" id="status_'.$unique_id.'">';
$temp_output .= '<option value="0,1"';
if ($widget_settings['status'] == '0,1') {
$temp_output .= ' selected';
}
$temp_output .= '>Up + Down</option>
<option value="1"';
if ($widget_settings['status'] == '1') {
$temp_output .= ' selected';
}
$temp_output .= '>Up</option>
<option value="0"';
if ($widget_settings['status'] == '0') {
$temp_output .= ' selected';
}
$temp_output .= '>Down</option>
</select>
</div>
</div>
<div class="form-group">
<div class="col-sm-2">
<button type="submit" class="btn btn-default">Set</button>
</div>
</div>
</form>
';
} else {
$temp_output = '
<script src="js/leaflet.js"></script> <script src="js/leaflet.js"></script>
<script src="js/leaflet.markercluster.js"></script> <script src="js/leaflet.markercluster.js"></script>
<script src="js/leaflet.awesome-markers.min.js"></script> <script src="js/leaflet.awesome-markers.min.js"></script>
<div id="leaflet-map"></div> <div id="leaflet-map"></div>
<script> <script>
'; ';
if (!empty($widget_settings) && !empty($widget_settings['init_lat']) && !empty($widget_settings['init_lng'])) { $init_lat = Config::get('leaflet.default_lat', 51.48);
$init_lat = $widget_settings['init_lat']; $init_lng = Config::get('leaflet.default_lng', 0);
$init_lng = $widget_settings['init_lng']; $init_zoom = Config::get('leaflet.default_zoom', 5);
$init_zoom = $widget_settings['init_zoom']; $group_radius = Config::get('leaflet.group_radius', 80);
} elseif (isset($config['leaflet'])) { $tile_url = Config::get('leaflet.tile_url', '{s}.tile.openstreetmap.org');
$init_lat = $config['leaflet']['default_lat']; $show_status = [0, 1];
$init_lng = $config['leaflet']['default_lng']; $map_init = "[" . $init_lat . ", " . $init_lng . "], " . sprintf("%01.1f", $init_zoom);
$init_zoom = $config['leaflet']['default_zoom']; $temp_output .= 'var map = L.map(\'leaflet-map\', { zoomSnap: 0.1 } ).setView('.$map_init.');
} L.tileLayer(\'//'.$tile_url.'/{z}/{x}/{y}.png\', {
if (!empty($widget_settings['group_radius'])) {
$group_radius = $widget_settings['group_radius'];
} else {
$group_radius = Config::get('leaflet.group_radius', 80);
}
if (empty($widget_settings['status']) && $widget_settings['status'] != '0') {
$widget_settings['status'] = '0,1';
}
$map_init = "[" . $init_lat . ", " . $init_lng . "], " . sprintf("%01.1f", $init_zoom);
$temp_output .= 'var map = L.map(\'leaflet-map\', { zoomSnap: 0.1 } ).setView('.$map_init.');
L.tileLayer(\'//'.$config['leaflet']['tile_url'].'/{z}/{x}/{y}.png\', {
attribution: \'&copy; <a href="http://osm.org/copyright">OpenStreetMap</a> contributors\' attribution: \'&copy; <a href="http://osm.org/copyright">OpenStreetMap</a> contributors\'
}).addTo(map); }).addTo(map);
@@ -168,57 +80,56 @@ var greenMarker = L.AwesomeMarkers.icon({
markerColor: \'green\', prefix: \'fa\', iconColor: \'white\' markerColor: \'green\', prefix: \'fa\', iconColor: \'white\'
}); });
'; ';
$status_select = explode(',', $widget_settings['status']);
// Checking user permissions // Checking user permissions
if (LegacyAuth::user()->hasGlobalRead()) { if (Auth::user()->hasGlobalRead()) {
// Admin or global read-only - show all devices // Admin or global read-only - show all devices
$sql = "SELECT DISTINCT(`device_id`),`location`,`sysName`,`hostname`,`os`,`status`,`lat`,`lng` FROM `devices` $sql = "SELECT DISTINCT(`device_id`),`location`,`sysName`,`hostname`,`os`,`status`,`lat`,`lng` FROM `devices`
LEFT JOIN `locations` ON `devices`.`location_id`=`locations`.`id` LEFT JOIN `locations` ON `devices`.`location_id`=`locations`.`id`
WHERE `disabled`=0 AND `ignore`=0 AND ((`lat` != '' AND `lng` != '') OR (`location` REGEXP '\[[0-9\.\, ]+\]')) WHERE `disabled`=0 AND `ignore`=0 AND ((`lat` != '' AND `lng` != '') OR (`location` REGEXP '\[[0-9\.\, ]+\]'))
AND `status` IN " . dbGenPlaceholders(count($status_select)) . AND `status` IN " . dbGenPlaceholders(count($show_status)) .
" ORDER BY `status` ASC, `hostname`"; " ORDER BY `status` ASC, `hostname`";
$param = $status_select; $param = $show_status;
} else { } else {
// Normal user - grab devices that user has permissions to // Normal user - grab devices that user has permissions to
$sql = "SELECT DISTINCT(`devices`.`device_id`) as `device_id`,`location`,`sysName`,`hostname`,`os`,`status`,`lat`,`lng` $sql = "SELECT DISTINCT(`devices`.`device_id`) as `device_id`,`location`,`sysName`,`hostname`,`os`,`status`,`lat`,`lng`
FROM `devices_perms`, `devices` FROM `devices_perms`, `devices`
LEFT JOIN `locations` ON `devices`.location_id=`locations`.`id` LEFT JOIN `locations` ON `devices`.location_id=`locations`.`id`
WHERE `disabled`=0 AND `ignore`=0 AND ((`lat` != '' AND `lng` != '') OR (`location` REGEXP '\[[0-9\.\, ]+\]')) WHERE `disabled`=0 AND `ignore`=0 AND ((`lat` != '' AND `lng` != '') OR (`location` REGEXP '\[[0-9\.\, ]+\]'))
AND `devices`.`device_id` = `devices_perms`.`device_id` AND `devices`.`device_id` = `devices_perms`.`device_id`
AND `devices_perms`.`user_id` = ? AND `status` IN " . dbGenPlaceholders(count($status_select)) . AND `devices_perms`.`user_id` = ? AND `status` IN " . dbGenPlaceholders(count($status_select)) .
" ORDER BY `status` ASC, `hostname`"; " ORDER BY `status` ASC, `hostname`";
$param = array_merge([LegacyAuth::id()], $status_select); $param = array_merge([Auth::id()], $status_select);
}
foreach (dbFetchRows($sql, $param) as $map_devices) {
$icon = 'greenMarker';
$z_offset = 0;
$tmp_loc = parse_location($map_devices['location']);
if (is_numeric($tmp_loc['lat']) && is_numeric($tmp_loc['lng'])) {
$map_devices['lat'] = $tmp_loc['lat'];
$map_devices['lng'] = $tmp_loc['lng'];
} }
if ($map_devices['status'] == 0) {
foreach (dbFetchRows($sql, $param) as $map_devices) { if (IsMaintenance($map_devices['device_id'])) {
$icon = 'greenMarker'; if ($show_status == 0) { // Don't show icon if only down devices should be shown
$z_offset = 0; continue;
$tmp_loc = parse_location($map_devices['location']);
if (is_numeric($tmp_loc['lat']) && is_numeric($tmp_loc['lng'])) {
$map_devices['lat'] = $tmp_loc['lat'];
$map_devices['lng'] = $tmp_loc['lng'];
}
if ($map_devices['status'] == 0) {
if (IsMaintenance($map_devices['device_id'])) {
if ($widget_settings['status'] == '0') { // Don't show icon if only down devices should be shown
continue;
} else {
$icon = 'blueMarker';
$z_offset = 5000;
}
} else { } else {
$icon = 'redMarker'; $icon = 'blueMarker';
$z_offset = 10000; // move marker to foreground $z_offset = 5000;
} }
} else {
$icon = 'redMarker';
$z_offset = 10000; // move marker to foreground
} }
$temp_output .= "var title = '<a href=\"" . generate_device_url($map_devices) . "\"><img src=\"".getIcon($map_devices)."\" width=\"32\" height=\"32\" alt=\"\"> ".format_hostname($map_devices)."</a>'; }
$temp_output .= "var title = '<a href=\"" . generate_device_url($map_devices) . "\"><img src=\"".getIcon($map_devices)."\" width=\"32\" height=\"32\" alt=\"\"> ".format_hostname($map_devices)."</a>';
var tooltip = '".format_hostname($map_devices)."'; var tooltip = '".format_hostname($map_devices)."';
var marker = L.marker(new L.LatLng(".$map_devices['lat'].", ".$map_devices['lng']."), {title: tooltip, icon: $icon, zIndexOffset: $z_offset}); var marker = L.marker(new L.LatLng(".$map_devices['lat'].", ".$map_devices['lng']."), {title: tooltip, icon: $icon, zIndexOffset: $z_offset});
marker.bindPopup(title); marker.bindPopup(title);
markers.addLayer(marker);\n"; markers.addLayer(marker);\n";
} }
$temp_output .= 'map.addLayer(markers); $temp_output .= 'map.addLayer(markers);
map.scrollWheelZoom.disable(); map.scrollWheelZoom.disable();
$(document).ready(function(){ $(document).ready(function(){
$("#leaflet-map").on("click", function(event) { $("#leaflet-map").on("click", function(event) {
@@ -229,7 +140,6 @@ $(document).ready(function(){
}); });
}); });
</script>'; </script>';
}
} else { } else {
$temp_output = 'Mapael engine not supported here'; $temp_output = 'Mapael engine not supported here';
} }

View File

@@ -1,69 +0,0 @@
<?php
/* Copyright (C) 2015 Daniel Preussker, QuxLabs UG <preussker@quxlabs.com>
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. */
/**
* Store per-widget settings
* @author Daniel Preussker
* @copyright 2015 Daniel Preussker, QuxLabs UG
* @license GPL
* @package LibreNMS
* @subpackage Widgets
*/
use LibreNMS\Authentication\LegacyAuth;
header('Content-type: application/json');
if (!LegacyAuth::check()) {
$response = array(
'status' => 'error',
'message' => 'Unauthenticated',
);
echo _json_encode($response);
exit;
}
$status = 'error';
$message = 'unknown error';
$widget_id = (int) $_REQUEST['id'];
if ($widget_id < 1) {
$status = 'error';
$message = 'ERROR: malformed widget ID. (' . $widget_id .')';
} else {
$widget_settings = $_REQUEST['settings'];
if (!is_array($widget_settings)) {
$widget_settings = array();
}
if (dbFetchCell('select 1 from users_widgets inner join dashboards on users_widgets.dashboard_id = dashboards.dashboard_id where user_widget_id = ? && (users_widgets.user_id = ? || dashboards.access = 2)', array($widget_id,LegacyAuth::id())) == 1) {
if (dbUpdate(array('settings'=>json_encode($widget_settings)), 'users_widgets', 'user_widget_id=?', array($widget_id)) >= 0) {
$status = 'ok';
$message = 'Updated widget settings';
} else {
$status = 'error';
$message = 'ERROR: Could not update';
}
} else {
$status = 'error';
$message = 'ERROR: You have no write-access to this dashboard';
}
}
$response = array(
'status' => $status,
'message' => $message
);
echo _json_encode($response);

View File

@@ -55,99 +55,15 @@ function data_uri($file, $mime)
}//end data_uri() }//end data_uri()
/**
* Convert string to nice case, mostly used for applications
*
* @param $item
* @return mixed|string
*/
function nicecase($item) function nicecase($item)
{ {
switch ($item) { return \LibreNMS\Util\StringHelpers::niceCase($item);
case 'dbm':
return 'dBm';
case 'entropy':
return 'Random entropy';
case 'mysql':
return ' MySQL';
case 'powerdns':
return 'PowerDNS';
case 'bind':
return 'BIND';
case 'nfs-stats':
return 'NFS Stats';
case 'nfs-v3-stats':
return 'NFS v3 Stats';
case 'nfs-server':
return 'NFS Server';
case 'ntp':
return 'NTP';
case 'ntp-client':
return 'NTP Client';
case 'ntp-server':
return 'NTP Server';
case 'os-updates':
return 'OS Updates';
case 'smart':
return 'SMART';
case 'powerdns-recursor':
return 'PowerDNS Recursor';
case 'powerdns-dnsdist':
return 'PowerDNS dnsdist';
case 'dhcp-stats':
return 'DHCP Stats';
case 'ups-nut':
return 'UPS nut';
case 'ups-apcups':
return 'UPS apcups';
case 'gpsd':
return 'GPSD';
case 'exim-stats':
return 'EXIM Stats';
case 'fbsd-nfs-client':
return 'FreeBSD NFS Client';
case 'fbsd-nfs-server':
return 'FreeBSD NFS Server';
case 'php-fpm':
return 'PHP-FPM';
case 'opengridscheduler':
return 'Open Grid Scheduler';
case 'sdfsinfo':
return 'SDFS info';
case 'pi-hole':
return 'Pi-hole';
case 'freeradius':
return 'FreeRADIUS';
case 'zfs':
return 'ZFS';
case 'asterisk':
return 'Asterisk';
default:
return ucfirst($item);
}
}//end nicecase() }//end nicecase()
@@ -234,31 +150,7 @@ function generate_overlib_content($graph_array, $text)
function get_percentage_colours($percentage, $component_perc_warn = null) function get_percentage_colours($percentage, $component_perc_warn = null)
{ {
$perc_warn = '75'; return \LibreNMS\Util\Colors::percentage($percentage, $component_perc_warn);
if (isset($component_perc_warn)) {
$perc_warn = round($component_perc_warn, 0);
}
$background = array();
if ($percentage > $perc_warn) {
$background['left'] = 'c4323f';
$background['right'] = 'C96A73';
} elseif ($percentage > '75') {
$background['left'] = 'bf5d5b';
$background['right'] = 'd39392';
} elseif ($percentage > '50') {
$background['left'] = 'bf875b';
$background['right'] = 'd3ae92';
} elseif ($percentage > '25') {
$background['left'] = '5b93bf';
$background['right'] = '92b7d3';
} else {
$background['left'] = '9abf5b';
$background['right'] = 'bbd392';
}
return ($background);
}//end get_percentage_colours() }//end get_percentage_colours()
@@ -595,25 +487,8 @@ STATE;
function print_percentage_bar($width, $height, $percent, $left_text, $left_colour, $left_background, $right_text, $right_colour, $right_background) function print_percentage_bar($width, $height, $percent, $left_text, $left_colour, $left_background, $right_text, $right_colour, $right_background)
{ {
if ($percent > '100') { return \LibreNMS\Util\Html::percentageBar($width, $height, $percent, $left_text, $left_colour, $left_background, $right_text, $right_colour, $right_background);
$size_percent = '100'; }
} else {
$size_percent = $percent;
}
$output = '
<div style="width:'.$width.'px; height:'.$height.'px; position: relative;">
<div class="progress" style="min-width: 2em; background-color:#'.$right_background.'; height:'.$height.'px;margin-bottom:-'.$height.'px;">
<div class="progress-bar" role="progressbar" aria-valuenow="'.$size_percent.'" aria-valuemin="0" aria-valuemax="100" style="min-width: 2em; width:'.$size_percent.'%; background-color: #'.$left_background.';">
</div>
</div>
<b style="padding-left: 2%; position: absolute; top: 0px; left: 0px;color:#'.$left_colour.';">'.$left_text.'</b>
<b style="padding-right: 2%; position: absolute; top: 0px; right: 0px;color:#'.$right_colour.';">'.$right_text.'</b>
</div>
';
return $output;
}//end print_percentage_bar()
function generate_entity_link($type, $entity, $text = null, $graph_type = null) function generate_entity_link($type, $entity, $text = null, $graph_type = null)
@@ -1065,11 +940,7 @@ function get_client_ip()
*/ */
function shorten_text($string, $max = 30) function shorten_text($string, $max = 30)
{ {
if (strlen($string) > 50) { return \LibreNMS\Util\StringHelpers::shortenText($string, $max);
return substr($string, 0, $max) . "...";
} else {
return $string;
}
} }
function shorten_interface_type($string) function shorten_interface_type($string)

File diff suppressed because one or more lines are too long

View File

@@ -299,12 +299,14 @@ $(document).ready(function () {
}, 300000); }, 300000);
}); });
function loadScript(src, callback) { var jsfilesadded = [];
var script = document.createElement("script"); function loadjs(filename, func){
script.type = "text/javascript"; if (jsfilesadded.indexOf(filename) < 0) {
if(callback)script.onload=callback; $.getScript(filename, func);
document.getElementsByTagName("head")[0].appendChild(script); jsfilesadded.push(filename);
script.src = src; } else {
func();
}
} }
function init_map(id, engine, api_key, config) { function init_map(id, engine, api_key, config) {
@@ -313,8 +315,8 @@ function init_map(id, engine, api_key, config) {
leaflet.setView([0, 0], 15); leaflet.setView([0, 0], 15);
if (engine === 'google') { if (engine === 'google') {
loadScript('https://maps.googleapis.com/maps/api/js?key=' + api_key, function () { loadjs('https://maps.googleapis.com/maps/api/js?key=' + api_key, function () {
loadScript('js/Leaflet.GoogleMutant.js', function () { loadjs('js/Leaflet.GoogleMutant.js', function () {
var roads = L.gridLayer.googleMutant({ var roads = L.gridLayer.googleMutant({
type: 'roadmap' // valid values are 'roadmap', 'satellite', 'terrain' and 'hybrid' type: 'roadmap' // valid values are 'roadmap', 'satellite', 'terrain' and 'hybrid'
}); });
@@ -331,7 +333,7 @@ function init_map(id, engine, api_key, config) {
}); });
}); });
} else if (engine === 'bing') { } else if (engine === 'bing') {
loadScript('js/leaflet-bing-layer.min.js', function () { loadjs('js/leaflet-bing-layer.min.js', function () {
var roads = L.tileLayer.bing({ var roads = L.tileLayer.bing({
bingMapsKey: api_key, bingMapsKey: api_key,
imagerySet: 'RoadOnDemand' imagerySet: 'RoadOnDemand'
@@ -451,3 +453,34 @@ function http_fallback(link) {
window.open(url, '_blank'); window.open(url, '_blank');
return false; return false;
} }
function init_select2(selector, type, data, selected) {
var $select = $(selector);
// allow function to be assigned to pass data
var data_function = function(params) {
data.term = params.term;
data.page = params.page || 1;
return data;
};
if ($.isFunction(data)) {
data_function = data;
}
$select.select2({
theme: "bootstrap",
dropdownAutoWidth : true,
width: "auto",
allowClear: true,
ajax: {
url: 'ajax/select/' + type,
delay: 150,
data: data_function
}
});
if (selected) {
$select.val(selected);
$select.trigger('change');
}
}

View File

@@ -1,64 +0,0 @@
<?php
/*
* LibreNMS
*
* Copyright (c) 2014 Neil Lathwood <https://github.com/laf/ http://www.lathwood.co.uk/fa>
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your
* option) any later version. Please see LICENSE.txt at the top level of
* the source code distribution for details.
* @package Laravel
* @author Taylor Otwell <taylor@laravel.com>
*/
use LibreNMS\Authentication\LegacyAuth;
$init_modules = ['web', 'auth'];
require realpath(__DIR__ . '/../..') . '/includes/init.php';
set_debug(isset($_REQUEST['debug']) && $_REQUEST['debug']);
header('Content-type: application/json');
if (!LegacyAuth::check()) {
$response = array(
'status' => 'error',
'message' => 'Unauthenticated',
);
echo _json_encode($response);
exit;
}
$type = isset($vars['type']) ? $vars['type'] : 'placeholder';
if ($type == 'placeholder') {
$output = "<span style='text-align:left;'><br><h3>Click on the Edit Dashboard button (next to the list of dashboards) to add widgets</h3><br><h4><strong>Remember:</strong> You can only move & resize widgets when you're in <strong>Edit Mode</strong>.</h4><span>";
$status = 'ok';
$title = 'Placeholder';
} elseif (is_file('includes/common/'.$type.'.inc.php')) {
$results_limit = 10;
$typeahead_limit = $config['webui']['global_search_result_limit'];
$no_form = true;
$unique_id = str_replace(array("-","."), "_", uniqid($type, true));
$widget_id = $vars['id'];
$widget_settings = json_decode(dbFetchCell('select settings from users_widgets where user_widget_id = ?', array($widget_id)), true);
$widget_dimensions = $vars['dimensions'];
if (!empty($vars['settings'])) {
define('SHOW_SETTINGS', true);
}
include 'includes/common/'.$type.'.inc.php';
$output = implode('', $common_output);
$status = 'ok';
$title = display($widget_settings['title']) ?: ucfirst(display($type));
}
$response = array(
'status' => $status,
'html' => $output,
'title' => $title,
);
echo _json_encode($response);

View File

@@ -102,7 +102,7 @@ if (empty($config['favicon'])) {
<link href="css/select2.min.css" rel="stylesheet" type="text/css" /> <link href="css/select2.min.css" rel="stylesheet" type="text/css" />
<link href="css/select2-bootstrap.min.css" rel="stylesheet" type="text/css" /> <link href="css/select2-bootstrap.min.css" rel="stylesheet" type="text/css" />
<link href="css/query-builder.default.min.css" rel="stylesheet" type="text/css" /> <link href="css/query-builder.default.min.css" rel="stylesheet" type="text/css" />
<link href="<?php echo($config['stylesheet']); ?>?ver=20181128" rel="stylesheet" type="text/css" /> <link href="<?php echo($config['stylesheet']); ?>?ver=20181201" rel="stylesheet" type="text/css" />
<link href="css/<?php echo $config['site_style']; ?>.css?ver=632417642" rel="stylesheet" type="text/css" /> <link href="css/<?php echo $config['site_style']; ?>.css?ver=632417642" rel="stylesheet" type="text/css" />
<?php <?php

View File

@@ -1,5 +1,5 @@
<?php <?php
$filter_device = $device['hostname']; $filter_device = $device['device_id'];
require_once 'includes/common/graylog.inc.php'; require_once 'includes/common/graylog.inc.php';
echo implode('', $common_output); echo implode('', $common_output);

View File

@@ -16,8 +16,6 @@
* Code for Gridster.sort_by_row_and_col_asc(serialization) call is from http://gridster.net/demos/grid-from-serialize.html * Code for Gridster.sort_by_row_and_col_asc(serialization) call is from http://gridster.net/demos/grid-from-serialize.html
*/ */
use LibreNMS\Authentication\LegacyAuth;
$no_refresh = true; $no_refresh = true;
$default_dash = get_user_pref('dashboard', 0); $default_dash = get_user_pref('dashboard', 0);
@@ -27,7 +25,7 @@ require_once 'includes/modal/alert_ack.inc.php';
// get all dashboards this user can access and put them into two lists user_dashboards and shared_dashboards // get all dashboards this user can access and put them into two lists user_dashboards and shared_dashboards
$dashboards = get_dashboards(); $dashboards = get_dashboards();
list($user_dashboards, $shared_dashboards) = array_reduce($dashboards, function ($ret, $dash) { list($user_dashboards, $shared_dashboards) = array_reduce($dashboards, function ($ret, $dash) {
if ($dash['user_id'] == LegacyAuth::id()) { if ($dash['user_id'] == Auth::id()) {
$ret[0][] = $dash; $ret[0][] = $dash;
} else { } else {
$ret[1][] = $dash; $ret[1][] = $dash;
@@ -45,16 +43,16 @@ if (!isset($dashboards[$default_dash])) {
if ($default_dash == 0 && empty($user_dashboards)) { if ($default_dash == 0 && empty($user_dashboards)) {
$new_dash = array( $new_dash = array(
'dashboard_name'=>'Default', 'dashboard_name'=>'Default',
'user_id'=>LegacyAuth::id(), 'user_id'=>Auth::id(),
); );
$dashboard_id = dbInsert($new_dash, 'dashboards'); $dashboard_id = dbInsert($new_dash, 'dashboards');
$new_dash['dashboard_id'] = $dashboard_id; $new_dash['dashboard_id'] = $dashboard_id;
$new_dash['username'] = LegacyAuth::user()->username; $new_dash['username'] = Auth::user()->username;
$vars['dashboard'] = $new_dash; $vars['dashboard'] = $new_dash;
if (dbFetchCell('select 1 from users_widgets where user_id = ? && dashboard_id = ?', array(LegacyAuth::id(),0)) == 1) { if (dbFetchCell('select 1 from users_widgets where user_id = ? && dashboard_id = ?', array(Auth::id(),0)) == 1) {
dbUpdate(array('dashboard_id'=>$dashboard_id), 'users_widgets', 'user_id = ? && dashboard_id = ?', array(LegacyAuth::id(), 0)); dbUpdate(array('dashboard_id'=>$dashboard_id), 'users_widgets', 'user_id = ? && dashboard_id = ?', array(Auth::id(), 0));
} }
} else { } else {
// load a dashboard // load a dashboard
@@ -94,7 +92,7 @@ if (empty($vars['bare']) || $vars['bare'] == "no") {
<div class="btn-group btn-lg"> <div class="btn-group btn-lg">
<button class="btn btn-default disabled" style="min-width:160px;"><span class="pull-left">Dashboards</span></button> <button class="btn btn-default disabled" style="min-width:160px;"><span class="pull-left">Dashboards</span></button>
<div class="btn-group"> <div class="btn-group">
<button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false" style="min-width:160px;"><span class="pull-left"><?php echo ($vars['dashboard']['user_id'] != LegacyAuth::id() ? $vars['dashboard']['username'].':' : ''); ?><?php echo $vars['dashboard']['dashboard_name']; ?></span> <button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false" style="min-width:160px;"><span class="pull-left"><?php echo ($vars['dashboard']['user_id'] != Auth::id() ? $vars['dashboard']['username'].':' : ''); ?><?php echo $vars['dashboard']['dashboard_name']; ?></span>
<span class="pull-right"> <span class="pull-right">
<span class="caret"></span> <span class="caret"></span>
<span class="sr-only">Toggle Dropdown</span> <span class="sr-only">Toggle Dropdown</span>
@@ -228,9 +226,6 @@ if (empty($vars['bare']) || $vars['bare'] == "no") {
<hr> <hr>
</div> </div>
<?php } //End Vars['bare'] If <?php } //End Vars['bare'] If
if (strpos($dash_config, 'globe') !== false) {
echo "<script src='https://www.google.com/jsapi'></script>";
}
?> ?>
<script src="js/jquery.gridster.min.js"></script> <script src="js/jquery.gridster.min.js"></script>
@@ -566,7 +561,7 @@ if (strpos($dash_config, 'globe') !== false) {
'</span>'+ '</span>'+
'<span class="fade-edit pull-right">'+ '<span class="fade-edit pull-right">'+
<?php <?php
if (($vars['dashboard']['access'] == 1 && LegacyAuth::id() === $vars['dashboard']['user_id']) || if (($vars['dashboard']['access'] == 1 && Auth::id() === $vars['dashboard']['user_id']) ||
($vars['dashboard']['access'] == 0 || $vars['dashboard']['access'] == 2)) { ($vars['dashboard']['access'] == 0 || $vars['dashboard']['access'] == 2)) {
echo "'<i class=\"fa fa-pencil-square-o edit-widget\" data-widget-id=\"'+data.user_widget_id+'\" aria-label=\"Settings\" data-toggle=\"tooltip\" data-placement=\"top\" title=\"Settings\">&nbsp;</i>&nbsp;'+"; echo "'<i class=\"fa fa-pencil-square-o edit-widget\" data-widget-id=\"'+data.user_widget_id+'\" aria-label=\"Settings\" data-toggle=\"tooltip\" data-placement=\"top\" title=\"Settings\">&nbsp;</i>&nbsp;'+";
} }
@@ -591,10 +586,21 @@ if (strpos($dash_config, 'globe') !== false) {
function widget_settings(data) { function widget_settings(data) {
var widget_settings = {}; var widget_settings = {};
var widget_id = 0; var widget_id = 0;
datas = $(data).serializeArray(); var datas = $(data).serializeArray();
for( var field in datas ) { for( var field in datas ) {
widget_settings[datas[field].name] = datas[field].value; var name = datas[field].name;
if (name.endsWith('[]')) {
name = name.slice(0, -2);
if (widget_settings[name]) {
widget_settings[name].push(datas[field].value);
} else {
widget_settings[name] = [datas[field].value];
}
} else {
widget_settings[name] = datas[field].value;
}
} }
$('.gridster').find('div[id^=widget_body_]').each(function() { $('.gridster').find('div[id^=widget_body_]').each(function() {
if(this.contains(data)) { if(this.contains(data)) {
widget_id = $(this).parent().attr('id'); widget_id = $(this).parent().attr('id');
@@ -604,9 +610,9 @@ if (strpos($dash_config, 'globe') !== false) {
}); });
if( widget_id > 0 && widget_settings != {} ) { if( widget_id > 0 && widget_settings != {} ) {
$.ajax({ $.ajax({
type: 'POST', type: 'PUT',
url: 'ajax_form.php', url: 'ajax/form/widget-settings/' + widget_id,
data: {type: 'widget-settings', id: widget_id, settings: widget_settings}, data: {settings: widget_settings},
dataType: "json", dataType: "json",
success: function (data) { success: function (data) {
if( data.status == "ok" ) { if( data.status == "ok" ) {
@@ -636,11 +642,10 @@ if (strpos($dash_config, 'globe') !== false) {
} }
$.ajax({ $.ajax({
type: 'POST', type: 'POST',
url: 'ajax_dash.php', url: 'ajax/dash/' + data_type,
data: { data: {
type: data_type,
id: id, id: id,
dimensions: {x:$("#widget_body_"+id).innerWidth()-50, y:$("#widget_body_"+id).innerHeight()-50}, dimensions: {x:$("#widget_body_"+id).width(), y:$("#widget_body_"+id).height()},
settings:settings settings:settings
}, },
dataType: "json", dataType: "json",
@@ -657,7 +662,7 @@ if (strpos($dash_config, 'globe') !== false) {
if (data.responseJSON.error) { if (data.responseJSON.error) {
$("#widget_body_"+id).html('<div class="alert alert-info">' + data.responseJSON.error + '</div>'); $("#widget_body_"+id).html('<div class="alert alert-info">' + data.responseJSON.error + '</div>');
} else { } else {
$("#widget_body_"+id).html('<div class="alert alert-info">Problem with backend</div>'); $("#widget_body_"+id).html('<div class="alert alert-info"><?php echo __('Problem with backend'); ?></div>');
} }
} }
}); });

View File

@@ -19,6 +19,7 @@
use LibreNMS\Authentication\LegacyAuth; use LibreNMS\Authentication\LegacyAuth;
use LibreNMS\Config; use LibreNMS\Config;
use LibreNMS\Exceptions\InvalidIpException; use LibreNMS\Exceptions\InvalidIpException;
use LibreNMS\Util\Html;
use LibreNMS\Util\IP; use LibreNMS\Util\IP;
function generate_priority_label($priority) function generate_priority_label($priority)
@@ -747,9 +748,7 @@ function c_echo($string, $enabled = true)
*/ */
function is_mib_graph($type, $subtype) function is_mib_graph($type, $subtype)
{ {
global $config; return \LibreNMS\Util\Graph::isMibGraph($type, $subtype);
return isset($config['graph_types'][$type][$subtype]['section']) &&
$config['graph_types'][$type][$subtype]['section'] == 'mib';
} // is_mib_graph } // is_mib_graph
@@ -1543,28 +1542,9 @@ function clean($value, $strip_tags = true)
* @param array $purifier_config (key, value pair) * @param array $purifier_config (key, value pair)
* @return string * @return string
*/ */
function display($value, $purifier_config = array()) function display($value, $purifier_config = [])
{ {
/** @var HTMLPurifier $purifier */ return Html::display($value, $purifier_config);
global $config, $purifier;
// If $purifier_config is non-empty then we don't want
// to convert html tags and allow these to be controlled
// by purifier instead.
if (empty($purifier_config)) {
$value = htmlentities($value);
}
if (!isset($purifier)) {
// initialize HTML Purifier here since this is the only user
$p_config = HTMLPurifier_Config::createDefault();
$p_config->set('Cache.SerializerPath', $config['temp_dir']);
foreach ($purifier_config as $k => $v) {
$p_config->set($k, $v);
}
$purifier = new HTMLPurifier($p_config);
}
return $purifier->purify(stripslashes($value));
} }
/** /**

View File

@@ -21,27 +21,27 @@
<link rel="shortcut icon" href="{{ LibreNMS\Config::get('favicon') }}" /> <link rel="shortcut icon" href="{{ LibreNMS\Config::get('favicon') }}" />
@endif @endif
<link href="css/bootstrap.min.css" rel="stylesheet" type="text/css" /> <link href="{{ asset('css/bootstrap.min.css') }}" rel="stylesheet" type="text/css" />
<link href="css/bootstrap-datetimepicker.min.css" rel="stylesheet" type="text/css" /> <link href="{{ asset('css/bootstrap-datetimepicker.min.css') }}" rel="stylesheet" type="text/css" />
<link href="css/bootstrap-switch.min.css" rel="stylesheet" type="text/css" /> <link href="{{ asset('css/bootstrap-switch.min.css') }}" rel="stylesheet" type="text/css" />
<link href="css/toastr.min.css" rel="stylesheet" type="text/css" /> <link href="{{ asset('css/toastr.min.css') }}" rel="stylesheet" type="text/css" />
<link href="css/jquery-ui.min.css" rel="stylesheet" type="text/css" /> <link href="{{ asset('css/jquery-ui.min.css') }}" rel="stylesheet" type="text/css" />
<link href="css/jquery.bootgrid.min.css" rel="stylesheet" type="text/css" /> <link href="{{ asset('css/jquery.bootgrid.min.css') }}" rel="stylesheet" type="text/css" />
<link href="css/tagmanager.css" rel="stylesheet" type="text/css" /> <link href="{{ asset('css/tagmanager.css') }}" rel="stylesheet" type="text/css" />
<link href="css/mktree.css" rel="stylesheet" type="text/css" /> <link href="{{ asset('css/mktree.css') }}" rel="stylesheet" type="text/css" />
<link href="css/vis.min.css" rel="stylesheet" type="text/css" /> <link href="{{ asset('css/vis.min.css') }}" rel="stylesheet" type="text/css" />
<link href="css/font-awesome.min.css" rel="stylesheet" type="text/css" /> <link href="{{ asset('css/font-awesome.min.css') }}" rel="stylesheet" type="text/css" />
<link href="css/jquery.gridster.min.css" rel="stylesheet" type="text/css" /> <link href="{{ asset('css/jquery.gridster.min.css') }}" rel="stylesheet" type="text/css" />
<link href="css/leaflet.css" rel="stylesheet" type="text/css" /> <link href="{{ asset('css/leaflet.css') }}" rel="stylesheet" type="text/css" />
<link href="css/MarkerCluster.css" rel="stylesheet" type="text/css" /> <link href="{{ asset('css/MarkerCluster.css') }}" rel="stylesheet" type="text/css" />
<link href="css/MarkerCluster.Default.css" rel="stylesheet" type="text/css" /> <link href="{{ asset('css/MarkerCluster.Default.css') }}" rel="stylesheet" type="text/css" />
<link href="css/L.Control.Locate.min.css" rel="stylesheet" type="text/css" /> <link href="{{ asset('css/L.Control.Locate.min.css') }}" rel="stylesheet" type="text/css" />
<link href="css/leaflet.awesome-markers.css" rel="stylesheet" type="text/css" /> <link href="{{ asset('css/leaflet.awesome-markers.css') }}" rel="stylesheet" type="text/css" />
<link href="css/select2.min.css" rel="stylesheet" type="text/css" /> <link href="{{ asset('css/select2.min.css') }}" rel="stylesheet" type="text/css" />
<link href="css/select2-bootstrap.min.css" rel="stylesheet" type="text/css" /> <link href="{{ asset('css/select2-bootstrap.min.css') }}" rel="stylesheet" type="text/css" />
<link href="css/query-builder.default.min.css" rel="stylesheet" type="text/css" /> <link href="{{ asset('css/query-builder.default.min.css') }}" rel="stylesheet" type="text/css" />
<link href="{{ LibreNMS\Config::get('stylesheet', 'css/styles.css') }}?ver=20181128" rel="stylesheet" type="text/css" /> <link href="{{ asset(LibreNMS\Config::get('stylesheet', 'css/styles.css')) }}?ver=20181201" rel="stylesheet" type="text/css" />
<link href="css/{{ LibreNMS\Config::get('site_style', 'light') }}.css?ver=632417642" rel="stylesheet" type="text/css" /> <link href="{{ asset('css/' . LibreNMS\Config::get('site_style', 'light') . '.css?ver=632417642') }}" rel="stylesheet" type="text/css" />
@foreach(LibreNMS\Config::get('webui.custom_css', []) as $custom_css) @foreach(LibreNMS\Config::get('webui.custom_css', []) as $custom_css)
<link href="{{ $custom_css }}" rel="stylesheet" type="text/css" /> <link href="{{ $custom_css }}" rel="stylesheet" type="text/css" />
@endforeach @endforeach

View File

@@ -0,0 +1,73 @@
<div class="row">
<div class="col-sm-12">
<span id="message"></span>
</div>
</div>
<div class="table-responsive">
<table id="alerts_{{ $id }}" class="table table-hover table-condensed alerts">
<thead>
<tr>
<th data-column-id="severity"></th>
<th data-column-id="timestamp">Timestamp</th>
<th data-column-id="rule">Rule</th>
<th data-column-id="details" data-sortable="false"></th>
<th data-column-id="hostname">Hostname</th>
<th data-column-id="ack_ico" data-sortable="false">ACK</th>
<th data-column-id="notes" data-sortable="false">Notes</th>
<th data-column-id="proc" data-sortable="false" data-visible="{{ $proc ? 'true' : 'false' }}">URL</th>
</tr>
</thead>
</table>
</div>
<script>
var alerts_grid = $("#alerts_{{ $id }}").bootgrid({
ajax: true,
post: function ()
{
return {
id: "alerts",
acknowledged: '{{ $acknowledged }}',
fired: '{{ $fired }}',
min_severity: '{{ $min_severity }}',
group: '{{ $group }}',
proc: '{{ $proc }}',
sort: '{{ $sort }}',
device_id: '{{ $device }}'
}
},
url: "ajax_table.php",
rowCount: [50, 100, 250, -1]
}).on("loaded.rs.jquery.bootgrid", function() {
alerts_grid = $(this);
alerts_grid.find(".incident-toggle").each( function() {
$(this).parent().addClass('incident-toggle-td');
}).on("click", function(e) {
var target = $(this).data("target");
$(target).collapse('toggle');
$(this).toggleClass('fa-plus fa-minus');
});
alerts_grid.find(".incident").each( function() {
$(this).parent().addClass('col-lg-4 col-md-4 col-sm-4 col-xs-4');
$(this).parent().parent().on("mouseenter", function() {
$(this).find(".incident-toggle").fadeIn(200);
}).on("mouseleave", function() {
$(this).find(".incident-toggle").fadeOut(200);
});
});
alerts_grid.find(".command-ack-alert").on("click", function(e) {
e.preventDefault();
var alert_state = $(this).data("alert_state");
var alert_id = $(this).data('alert_id');
$('#ack_alert_id').val(alert_id);
$('#ack_alert_state').val(alert_state);
$('#ack_msg').val('');
$("#alert_ack_modal").modal('show');
});
alerts_grid.find(".command-alert-note").on("click", function(e) {
e.preventDefault();
var alert_id = $(this).data('alert_id');
$('#alert_id').val(alert_id);
$("#alert_notes_modal").modal('show');
});
});
</script>

View File

@@ -0,0 +1,51 @@
@if($device_totals)
<div class="widget-availability-host">
<span>@lang('Total hosts')</span>
@if($show_disabled_and_ignored)
<span class="label label-default label-font-border label-border">@lang('ignored'): {{ $device_totals['ignored'] }}</span>
<span class="label blackbg label-font-border label-border">@lang('disabled'): {{ $device_totals['disabled'] }}</span>
@endif
<span class="label label-success label-font-border label-border">@lang('up'): {{ $device_totals['up'] }}</span>
<span class="label label-warning label-font-border label-border">@lang('warn'): {{ $device_totals['warn'] }}</span>
<span class="label label-danger label-font-border label-border">@lang('down'): {{ $device_totals['down'] }}</span>
</div>
@endif
@if($services_totals)
<div class="widget-availability-service">
<span>@lang('Total services')</span>
<span class="label label-success label-font-border label-border">@lang('up'): {{ $services_totals['up'] }}</span>
<span class="label label-warning label-font-border label-border">@lang('warn'): {{ $services_totals['warn'] }}</span>
<span class="label label-danger label-font-border label-border">@lang('down'): {{ $services_totals['down'] }}</span>
</div>
@endif
<br style="clear:both;">
@foreach($devices as $device)
<a href="{{ \LibreNMS\Util\Url::deviceUrl($device) }}" title="{{ $device->displayName() }} - {{ $device->formatUptime(true) }}">
@if($type == 0)
@if($color_only_select)
<span class="label {{ $device->labelClass }} widget-availability label-font-border">@lang($device->stateName)</span>
@else
<span class="label {{ $device->labelClass }} widget-availability-fixed widget-availability label-font-border"> </span>
@endif
@else
<div class="availability-map-oldview-box-{{ $device->stateName }}" style="width:{{ $tile_size }}px;height:{{ $tile_size }}px;"></div>
@endif
</a>
@endforeach
@foreach($services as $service)
<a href="{{ \LibreNMS\Util\Url::deviceUrl($service->device, ['tab' => 'services']) }}" title="{{ $service->device->displayName() }} - {{ $service->service_type }} - {{ $service->service_desc }}">
@if($type == 0)
@if($color_only_select)
<span class="label {{ $service->labelClass }} widget-availability label-font-border">{{ $service->service_type }} - {{ $service->stateName }}</span>
@else
<span class="label {{ $service->labelClass }} widget-availability-fixed widget-availability label-font-border"> </span>
@endif
@else
<div class="availability-map-oldview-box-{{ $service->stateName }}" style="width:{{ $tile_size }}px;height:{{ $tile_size }}px;"></div>
@endif
</a>
@endforeach

View File

@@ -0,0 +1,18 @@
<div>
<table id="component-status" class="table table-hover table-condensed table-striped">
<thead>
<tr>
<th data-column-id="status" data-order="desc">Status</th>
<th data-column-id="count">Count</th>
</tr>
</thead>
<tbody>
@foreach($status as $item)
<tr>
<td><p class="text-left {{ $item['color'] }}">{{ $item['text'] }}</p></td>
<td><p class="text-left {{ $item['color'] }}">{{ $item['total'] }}</p></td>
</tr>
@endforeach
</tbody>
</table>
</div>

View File

@@ -0,0 +1,54 @@
<div class="panel panel-default panel-condensed table-responsive">
<table class="table table-hover table-condensed table-striped">
<thead>
<tr>
<th>&nbsp;</th>
<th><span class="grey">@lang('Total')</span></th>
<th><span class="green">@lang('Up')</span></th>
<th><span class="red">@lang('Down')</span></th>
<th><span class="grey">@lang('Ignored')</span></th>
<th><span class="black">@lang('Disabled')</span></th>
@if($summary_errors)
<th class="black">@lang('Errored')</th>
@endif
</tr>
</thead>
<tbody>
<tr>
<td><a href="{{ url('devices') }}">@lang('Devices')</a></td>
<td><a href="{{ url('devices') }}"><span> {{ $devices['count'] }}</span></a></td>
<td><a href="{{ url('devices/state=up/format=list_detail') }}"><span class="green"> {{ $devices['up'] }}</span></a></td>
<td><a href="{{ url('devices/state=down/format=list_detail') }}"><span class="red"> {{ $devices['down'] }}</span></a></td>
<td><a href="{{ url('devices/ignore=1/format=list_detail') }}"><span class="grey"> {{ $devices['ignored'] }}</span></a></td>
<td><a href="{{ url('devices/disabled=1/format=list_detail') }}"><span class="black"> {{ $devices['disabled'] }}</span></a></td>
@if($summary_errors)
<th>-</th>
@endif
</tr>
<tr>
<td><a href="{{ url('ports') }}">@lang('Ports')</a></td>
<td><a href="{{ url('ports') }}"><span>{{ $ports['count'] }}</span></a></td>
<td><a href="{{ url('ports/format=list_detail/state=up') }}"><span class="green"> {{ $ports['up'] }}</span></a></td>
<td><a href="{{ url('ports/format=list_detail/state=down') }}"><span class="red"> {{ $ports['down'] }}</span></a></td>
<td><a href="{{ url('ports/format=list_detail/ignore=1') }}"><span class="grey"> {{ $ports['ignored'] }}</span></a></td>
<td><a href="{{ url('ports/format=list_detail/state=admindown') }}"><span class="black"> {{ $ports['shutdown'] }}</span></a></td>
@if($summary_errors)
<td><a href="{{ url('ports/format=list_detail/errors=1') }}"><span class="black"> {{ $ports['errored'] }}</span></a></td>
@endif
</tr>
@if($show_services)
<tr>
<td><a href="{{ url('services') }}">@lang('Services')</a></td>
<td><a href="{{ url('services') }}"><span>{{ $services['count'] }}</span></a></td>
<td><a href="{{ url('services/state=ok/view=details') }}"><span class="green">{{ $services['up'] }}</span></a></td>
<td><a href="{{ url('services/state=critical/view=details') }}"><span class="red"> {{ $services['down'] }}</span></a></td>
<td><a href="{{ url('services/ignore=1/view=details') }}"><span class="grey"> {{ $services['ignored'] }}</span></a></td>
<td><a href="{{ url('services/disabled=1/view=details') }}"><span class="black"> {{ $services['disabled'] }}</span></a></td>
@if($summary_errors)
<td>-</td>
@endif
</tr>
@endif
</tbody>
</table>
</div>

View File

@@ -0,0 +1,66 @@
<div class="panel panel-default panel-condensed table-responsive">
<table class="table table-hover table-condensed table-striped">
<thead>
<tr>
<th>@lang('Summary')</th>
<th><a href="{{ url('devices') }}">@lang('Devices')</a></th>
<th><a href="{{ url('ports') }}">@lang('Ports')</a></th>
@if($show_services)
<th><a href="{{ url('services') }}">@lang('Services')</a></th>
@endif
</tr>
</thead>
<tbody>
<tr>
<th><span class="green">@lang('Up')</span></th>
<td><a href="{{ url('devices/format=list_detail/state=up') }}"><span class="green"> {{ $devices['up'] }}</span></a></td>
<td><a href="{{ url('ports/format=list_detail/state=up') }}"><span class="green"> {{ $ports['up'] }}</span></a></td>
@if($show_services)
<td><a href="{{ url('services/view=details/state=ok') }}"><span class="green"> {{ $services['up'] }}</span></a></td>
@endif
</tr>
<tr>
<th><span class="red">@lang('Down')</span></th>
<td><a href="{{ url('devices/format=list_detail/state=down') }}"><span class="red"> {{ $devices['down'] }}</span></a></td>
<td><a href="{{ url('ports/format=list_detail/state=down') }}"><span class="red"> {{ $ports['down'] }}</span></a></td>
@if($show_services)
<td><a href="{{ url('services/view=details/state=critical') }}"><span class="red"> {{ $services['down'] }}</span></a></td>
@endif
</tr>
<tr>
<th><span class="grey">@lang('Ignored')</span></th>
<td><a href="{{ url('devices/format=list_detail/ignore=1') }}"><span class="grey"> {{ $devices['ignored'] }}</span></a></td>
<td><a href="{{ url('ports/format=list_detail/ignore=1') }}"><span class="grey"> {{ $ports['ignored'] }}</span></a></td>
@if($show_services)
<td><a href="{{ url('services/view=details/ignore=1') }}"><span class="grey"> {{ $services['ignored'] }}</span></a></td>
@endif
</tr>
<tr>
<th><span class="black">Disabled/Shutdown</span></th>
<td><a href="{{ url('devices/format=list_detail/disabled=1') }}"><span class="black"> {{ $devices['disabled'] }}</span></a></td>
<td><a href="{{ url('ports/format=list_detail/state=admindown') }}"><span class="black"> {{ $ports['shutdown'] }}</span></a></td>
@if($show_services)
<td><a href="{{ url('services/view=details/disabled=1') }}"><span class="black"> {{ $services['disabled'] }}</span></a></td>
@endif
</tr>
@if($summary_errors)
<tr>
<th><span class="black">@lang('Errored')</span></th>
<td>-</td>
<td><a href="{{ url('ports/format=list_detail/errors=1') }}"><span class="black"> {{ $ports['errored'] }}</span></a></td>
@if($show_services)
<td>-</td>
@endif
</tr>
@endif
<tr>
<th><span class="grey">@lang('Total')</span></th>
<td><a href="{{ url('devices') }}"><span> {{ $devices['count'] }}</span></a></td>
<td><a href="{{ url('ports') }}"><span> {{ $ports['count'] }}</span></a></td>
@if($show_services)
<td><a href="{{ url('services') }}"><span> {{ $services['count'] }}</span></a></td>
@endif
</tr>
</tbody>
</table>
</div>

View File

@@ -0,0 +1,27 @@
<div class="table-responsive">
<table id="eventlog" class="table table-hover table-condensed table-striped">
<thead>
<tr>
<th data-column-id="datetime" data-order="desc">Timestamp</th>
<th data-column-id="type">Type</th>
<th data-column-id="device_id">Hostname</th>
<th data-column-id="message">Message</th>
<th data-column-id="username">User</th>
</tr>
</thead>
</table>
</div>
<script>
$("#eventlog").bootgrid({
ajax: true,
rowCount: [50, 100, 250, -1],
post: function ()
{
return {
device: "{{ $device }}",
eventtype: "{{ $eventtype }}"
};
},
url: "ajax/table/eventlog"
});
</script>

View File

@@ -0,0 +1,29 @@
<div id='chart_div'></div>
<script type='text/javascript'>
loadjs('https://www.gstatic.com/charts/loader.js', function() {
google.charts.load('current', {'packages': ['geochart'], callback: function() {
var data = new google.visualization.DataTable();
data.addColumn('number', 'Latitude');
data.addColumn('number', 'Longitude');
data.addColumn('string', 'Label');
data.addColumn('number', 'Status');
data.addColumn('number', 'Size');
data.addColumn({type: 'string', role: 'tooltip', 'p': {'html': true}});
data.addRows({!! $locations !!});
var options = {
region: '{{ $region }}',
resolution: '{{ $resolution }}',
displayMode: 'markers',
keepAspectRatio: 1,
magnifyingGlass: {enable: true, zoomFactor: 100},
colorAxis: {minValue: 0, maxValue: 100, colors: ['green', 'yellow', 'red']},
markerOpacity: 0.90,
tooltip: {isHtml: true}
};
var chart = new google.visualization.GeoChart(document.getElementById('chart_div'));
chart.draw(data, options);
}
});
});
</script>

View File

@@ -0,0 +1,9 @@
<div class="dashboard-graph">
<a href="graphs/{{ $param }}/type={{ $graph_type }}/from={{ $from }}">
<img class="minigraph-image"
width="{{ $dimensions['x'] }}"
height="{{ $dimensions['y'] }}"
src="graph.php?{{ $param }}&from={{ $from }}&to={{ $to }}&width={{ $dimensions['x'] }}&height={{ $dimensions['y'] }}&type={{ $graph_type }}&legend={{ $graph_legend }}&absolute=1"
/>
</a>
</div>

View File

@@ -0,0 +1,39 @@
<div class="table-responsive">
<table id="graylog-{{ $id }}" class="table table-hover table-condensed graylog">
<thead>
<tr>
<th data-column-id="severity" data-sortable="false"></th>
<th data-column-id="timestamp" data-formatter="browserTime">@lang('Timestamp')</th>
<th data-column-id="level" data-sortable="false">@lang('Level')</th>
<th data-column-id="source">@lang('Source')</th>
<th data-column-id="message" data-sortable="false">@lang('Message')</th>
<th data-column-id="facility" data-sortable="false">@lang('Facility')</th>
</tr>
</thead>
</table>
</div>
<script>
$("#graylog-{{ $id }}").bootgrid({
ajax: true,
rowCount: ['{{ $limit }}', 25,50,100,250,-1],
formatters: {
"browserTime": function(column, row) {
@if(Config::get('graylog.timezone'))
return row.timestamp;
@else
return moment.parseZone(row.timestamp).local().format("YYYY-MM-DD HH:MM:SS");
@endif
}
},
post: function ()
{
return {
stream: "{{ $stream }}",
device: "{{ $device }}",
range: "{{ $range }}"
};
},
url: "ajax/table/graylog"
});
</script>

View File

@@ -0,0 +1,3 @@
<a target="_blank" rel="noopener" href="{{ $target_url }}">
<img class="dashboard-image" style="max-width: {{ $dimensions['x'] }}px; max-height: {{ $dimensions['y'] }}" src="{{ $image_url }}"/>
</a>

View File

@@ -0,0 +1,5 @@
<div>
<h3>Click on the Edit Dashboard button (next to the list of dashboards) to add widgets</h3>
<br />
<h4><strong>Remember:</strong> You can only move & resize widgets when you're in <strong>Edit Mode</strong>.</h4>
</div>

View File

@@ -0,0 +1,50 @@
<div class="col-sm-{{ $columns }}">
<div
id="cpu-{{ $id }}"
class="guage-{{ $id }}"
data-value="{{ $cpu }}"
data-max="100"
data-symbol="%"
data-title="CPU Usage"
></div>
</div>
@foreach($mempools as $key => $mem)
<div class="col-sm-{{ $columns }}">
<div
id="mem-{{ $key }}-{{ $id }}"
class="guage-{{ $id }}"
data-value="{{ $mem['used'] }}"
data-max="{{ $mem['total'] }}"
data-label="Mbytes"
data-title="{{ $mem['mempool_descr'] }} Usage"
></div>
</div>
@endforeach
@foreach($disks as $key => $disk)
<div class="col-sm-{{ $columns }}">
<div
id="disk-{{ $key }}-{{ $id }}"
class="guage-{{ $id }}"
data-value="{{ $disk['used'] }}"
data-max="{{ $disk['total'] }}"
data-label="Mbytes"
data-title="{{ $disk['storage_descr'] }} Usage"
></div>
</div>
@endforeach
<script type='text/javascript'>
loadjs('js/raphael-min.js', function() {
loadjs('js/justgage.js', function() {
$('.guage-{{ $id }}').each(function() {
new JustGage({
id: this.id,
min: 0,
valueFontSize: '2px'
});
});
});
});
</script>

View File

@@ -0,0 +1,65 @@
@extends('widgets.settings.base')
@section('form')
<div class="form-group row">
<label for="acknowledged-{{ $id }}" class="control-label">@lang('Show acknowledged'):</label>
<select class="form-control" name="acknowledged" id="acknowledged-{{ $id }}">
<option value="">@lang('not filtered')</option>
<option value="1" @if($acknowledged === '1') selected @endif>@lang('show only acknowledged')</option>
<option value="0" @if($acknowledged === '0') selected @endif>@lang('hide acknowledged')</option>
</select>
</div>
<div class="form-group row">
<label for="fired-{{ $id }}" class="control-label">@lang('Show only fired'):</label>
<select class="form-control" name="fired" id="fired-{{ $id }}">
<option value="">@lang('not filtered')</option>
<option value="1" @if($fired === '1') selected @endif>@lang('show only fired alerts')</option>
</select>
</div>
<div class="form-group row">
<label for="min_severity-{{ $id }}" class="control-label">@lang('Displayed severity'):</label>
<select class="form-control" name="min_severity" id="min_severity-{{ $id }}">
<option value="">@lang('any severity')</option>
@foreach($severities as $name => $val)
<option value="{{ $val }}" @if($min_severity == $val) selected @endif>{{ $name }}{{$val > 3 ? '' : ' ' . __('or higher')}}</option>
@endforeach
</select>
</div>
<div class="form-group row">
<label for="state-{{ $id }}" class="control-label">@lang('State'):</label>
<select class="form-control" name="state" id="state-{{ $id }}">
<option value="">@lang('any state')</option>
@foreach($states as $name => $val)
<option value="{{ $val }}" @if($state === $val) selected @endif>{{ $name }}</option>
@endforeach
</select>
</div>
<div class="form-group">
<label for="device_group-{{ $id }}" class="control-label">@lang('Device group')</label>
<select class="form-control" name="group" id="device_group-{{ $id }}" data-placeholder="@lang('All alerts')">
@if($device_group)
<option value="{{ $device_group->id }}" selected> {{ $device_group->name }} </option>
@endif
</select>
</div>
<div class="form-group row">
<label for="proc-{{ $id }}" class="control-label">@lang('Show Procedure field'):</label>
<select class="form-control" name="proc" id="proc-{{ $id }}">
<option value="1" @if($proc == 1) selected @endif>@lang('show')</option>
<option value="0" @if($proc == 0) selected @endif>@lang('hide')</option>
</select>
</div>
<div class="form-group row">
<label for="sort-{{ $id }}" class="control-label">@lang('Sort alerts by'):</label>
<select class="form-control" name="sort" id="sort-{{ $id }}">
<option value="" @if($sort == 1) selected @endif>@lang('timestamp, descending')</option>
<option value="severity" @if($sort == 0) selected @endif>@lang('severity, descending')</option>
</select>
</div>
@endsection
@section('javascript')
<script type="text/javascript">
init_select2('#device_group-{{ $id }}', 'device-group', {}, '{{ $group ?: '' }}');
</script>
@endsection

View File

@@ -0,0 +1,74 @@
@extends('widgets.settings.base')
@section('form')
<div class="form-group">
<label for="title-{{ $id }}" class="control-label">@lang('Widget title')</label>
<input type="text" class="form-control" name="title" id="title-{{ $id }}" placeholder="@lang('Custom title for widget')" value="{{ $title }}">
</div>
<div class="form-group">
<label for="type-{{ $id }}" class="control-label">@lang('Display type')</label>
<select class="form-control" name="type" id="type-{{ $id }}" onchange="toggle_availability_type(this, '{{ $id }}');">
<option value="0" @if($type == 0) selected @endif>@lang('boxes')</option>
<option value="1" @if($type == 1) selected @endif>@lang('compact')</option>
</select>
</div>
<div class="form-group" id="color_only_select-group-{{ $id }}" style="display: {{ $type == 0 ? 'block' : 'none' }};">
<label for="color_only_select-{{ $id }}" class="control-label">@lang('Uniform Tiles')</label>
<select class="form-control" name="color_only_select" id="color_only_select-{{ $id }}">
<option value="1" @if($color_only_select) selected @endif>@lang('yes')</option>
<option value="0" @unless($color_only_select) selected @endunless>@lang('no')</option>
</select>
</div>
<div class="form-group" id="tile_size-group-{{ $id }}" style="display: {{ $type == 1 ? 'block' : 'none' }};">
<label for="tile_size-{{ $id }}" class="control-label">@lang('Tile size')</label>
<input type="text" class="form-control" name="tile_size" id="tile_size-{{ $id }}" placeholder="@lang('Tile size')" value="{{ $tile_size }}">
</div>
<div class="form-group">
<label for="show_disabled_and_ignored-{{ $id }}" class="control-label">@lang('Disabled/ignored')</label>
<select class="form-control" name="show_disabled_and_ignored" id="show_disabled_and_ignored-{{ $id }}">
<option value="1" @if($show_disabled_and_ignored) selected @endif>@lang('yes')</option>
<option value="0" @unless($show_disabled_and_ignored) selected @endunless>@lang('no')</option>
</select>
</div>
<div class="form-group">
<label for="mode_select-{{ $id }}" class="control-label">@lang('Mode select')</label>
<select class="form-control" name="mode_select" id="mode_select-{{ $id }}">
<option value="0" @if($mode_select == 0) selected @endif>@lang('only devices')</option>
@config('show_services')
<option value="1" @if($mode_select == 1) selected @endif>@lang('only services')</option>
<option value="2" @if($mode_select == 2) selected @endif>@lang('devices and services')</option>
@endconfig
</select>
</div>
<div class="form-group">
<label for="device_group-{{ $id }}" class="control-label">@lang('Device group')</label>
<select class="form-control" name="device_group" id="device_group-{{ $id }}" data-placeholder="@lang('All Devices')">
@if($device_group)
<option value="{{ $device_group->id }}" selected> {{ $device_group->name }} </option>
@endif
</select>
</div>
@endsection
@section('javascript')
<script type="text/javascript">
init_select2('#device_group-{{ $id }}', 'device-group', {}, '{{ $device_group ? $device_group->id : '' }}');
function toggle_availability_type(el, id) {
console.log(el.value);
if (el.value === '0') {
$('#tile_size-group-' + id).hide();
$('#color_only_select-group-' + id).show();
} else {
$('#tile_size-group-' + id).show();
$('#color_only_select-group-' + id).hide();
}
}
</script>
@endsection

View File

@@ -0,0 +1,13 @@
<form role="form" class="dashboard-widget-settings" onsubmit="widget_settings(this); return false;">
@yield('form')
@hassection('form')
<div style="margin-top: 8px;">
<button type="submit" class="btn btn-primary pull-right">@lang('Save')</button>
</div>
@else
No settings for this widget
@endif
</form>
@yield('javascript')

View File

@@ -0,0 +1,19 @@
@extends('widgets.settings.base')
@section('form')
<div class="form-group">
<label for="show_services-{{ $id }}" class="control-label">@lang('Show Services')</label>
<select class="form-control" id="show_services-{{ $id }}" name="show_services">
<option value="0" @unless($show_services) selected @endunless>@lang('no')</option>
<option value="1" @if($show_services) selected @endif>@lang('yes')</option>
</select>
</div>
</div>
<div class="form-group">
<label for="summary_errors-{{ $id }}" class="control-label">@lang('Show Port Errors')</label>
<select class="form-control" id="summary_errors-{{ $id }}" name="summary_errors">
<option value="0" @unless($summary_errors) selected @endunless>@lang('no')</option>
<option value="1" @if($summary_errors) selected @endif>@lang('yes')</option>
</select>
</div>
@endsection

View File

@@ -0,0 +1,38 @@
@extends('widgets.settings.base')
@section('form')
<div class="form-group">
<label for="title-{{ $id }}" class="control-label">@lang('Widget title')</label>
<input type="text" class="form-control" name="title" id="title-{{ $id }}" placeholder="@lang('Custom title')" value="{{ $title }}">
</div>
<div class="form-group">
<label for="device-{{ $id }}" class="control-label">@lang('Device')</label>
<select class="form-control" id="device-{{ $id }}" name="device" data-placeholder="@lang('All devices')">
@if($device)
<option value="{{ $device->device_id }}">{{ $device->displayName() }}</option>
@endif
</select>
</div>
<div class="form-group">
<label for="eventtype-{{ $id }}" class="control-label">@lang('Event type')</label>
<select class="form-control" id="eventtype-{{ $id }}" name="eventtype" data-placeholder="@lang('All types')" data-tags="true">
@if($eventtype)
<option value="{{ $eventtype }}">{{ $eventtype }}</option>
@endif
</select>
</div>
@endsection
@section('javascript')
<script type="text/javascript">
init_select2('#device-{{ $id }}', 'device', {}, '{{ $device ? $device->device_id : '' }}');
init_select2('#eventtype-{{ $id }}', 'eventlog', function(params) {
return {
field: "type",
device: $('#device-{{ $id }}').val(),
term: params.term,
page: params.page || 1
}
}, '{{ $eventtype ?: "" }}');
</script>
@endsection

View File

@@ -0,0 +1,27 @@
@extends('widgets.settings.base')
@section('form')
<div class="form-group">
<label for="title-{{ $id }}" class="control-label">@lang('Widget title')</label>
<input type="text" class="form-control" name="title" id="title-{{ $id }}" placeholder="@lang('Default Title')" value="{{ $title }}">
</div>
<div class="form-group">
<label for="markers-{{ $id }}" class="control-label">@lang('Markers')</label>
<select class="form-control" id="markers-{{ $id }}" name="markers">
<option value="devices" @if($markers == 'devices') selected @endif>@lang('Devices')</option>
<option value="ports" @if($markers == 'ports') selected @endif>@lang('Ports')</option>
</select>
</div>
<div class="form-group">
<label for="resolution-{{ $id }}-{{ $id }}" class="control-label">@lang('Resolution')</label>
<select class="form-control" id="resolution-{{ $id }}" name="resolution">
<option value="countries" @if($resolution == 'countries') selected @endif>@lang('Contries')</option>
<option value="provinces" @if($resolution == 'provinces') selected @endif>@lang('Provinces')</option>
<option value="metros" @if($resolution == 'metros') selected @endif>@lang('Metros')</option>
</select>
</div>
<div class="form-group">
<label for="region-{{ $id }}" class="control-label">@lang('Region') <a target="_blank" href="https://developers.google.com/chart/interactive/docs/gallery/geochart#configuration-options">@lang('Help')</a></label>
<input type="text" class="form-control" name="region" id="region-{{ $id }}" value="{{ $region }}">
</div>
@endsection

View File

@@ -0,0 +1,126 @@
@extends('widgets.settings.base')
@section('form')
<div class="form-group">
<label for="title-{{ $id }}" class="control-label">@lang('Widget title')</label>
<input type="text" class="form-control" name="title" id="title-{{ $id }}" placeholder="@lang('Automatic Title')" value="{{ $title }}">
</div>
<div class="form-group">
<label for="graph_type-{{ $id }}" class="control-label">@lang('Graph type')</label>
<select class="form-control" id="graph_type-{{ $id }}" name="graph_type" required data-placeholder="@lang('Select a graph')" onchange="switch_graph_type{{ $id }}(this.value);">
@if($graph_type)
<option value="{{ $graph_type }}">{{ $graph_text }}</option>
@endif
</select>
</div>
<div class="form-group">
<label for="graph_legend-{{ $id }}" class="control-label">@lang('Show legend')</label>
<select class="form-control" id="graph_legend-{{ $id }}" name="graph_legend">
<option value="yes" @if($graph_legend == 'yes') selected @endif>@lang('yes')</option>
<option value="no" @if($graph_legend == 'no') selected @endif>@lang('no')</option>
</select>
</div>
<div class="form-group">
<label for="graph_range-{{ $id }}" class="control-label">@lang('Date range')</label>
<select class="form-control" id="graph_range-{{ $id }}" name="graph_range">
<option value="onehour" @if($graph_range == 'onehour') selected @endif>@lang('One Hour')</option>
<option value="fourhour" @if($graph_range == 'fourhour') selected @endif>@lang('Four Hours')</option>
<option value="sixhour" @if($graph_range == 'sixhour') selected @endif>@lang('Six Hours')</option>
<option value="twelvehour" @if($graph_range == 'twelvehour') selected @endif>@lang('Twelve Hours')</option>
<option value="day" @if($graph_range == 'day') selected @endif>@lang('One Day')</option>
<option value="week" @if($graph_range == 'week') selected @endif>@lang('One Week')</option>
<option value="twoweek" @if($graph_range == 'twoweek') selected @endif>@lang('Two Weeks')</option>
<option value="month" @if($graph_range == 'month') selected @endif>@lang('One Month')</option>
<option value="twomonth" @if($graph_range == 'twomonth') selected @endif>@lang('Two Months')</option>
<option value="threemonth" @if($graph_range == 'threemonth') selected @endif>@lang('Three Months')</option>
<option value="year" @if($graph_range == 'year') selected @endif>@lang('One Year')</option>
<option value="twoyear" @if($graph_range == 'twoyear') selected @endif>@lang('Two Years')</option>
</select>
</div>
<div class="form-group graph_select_extra-{{ $id }}" id="graph_select_device-{{ $id }}" style="display: none;">
<label for="graph_device-{{ $id }}" class="control-label">@lang('Device')</label>
<select class="form-control" id="graph_device-{{ $id }}" name="graph_device" data-placeholder="@lang('Select a device')">
@if($graph_device)
<option value="{{ $graph_device }}">{{ $device_text }}</option>
@endif
</select>
</div>
<div class="form-group graph_select_extra-{{ $id }}" id="graph_select_port-{{ $id }}" style="display: none;">
<label for="graph_port-{{ $id }}" class="control-label">@lang('Port')</label>
<select class="form-control" id="graph_port-{{ $id }}" name="graph_port" data-placeholder="@lang('Select a port')">
@if($graph_port)
<option value="{{ $graph_port }}">{{ $port_text }}</option>
@endif
</select>
</div>
<div class="form-group graph_select_extra-{{ $id }}" id="graph_select_application-{{ $id }}" style="display: none;">
<label for="graph_application-{{ $id }}" class="control-label">@lang('Application')</label>
<select class="form-control" id="graph_application-{{ $id }}" name="graph_application" data-placeholder="@lang('Select an application')">
@if($graph_application)
<option value="{{ $graph_application }}">{{ $application_text }}</option>
@endif
</select>
</div>
<div class="form-group graph_select_extra-{{ $id }}" id="graph_select_munin-{{ $id }}" style="display: none;">
<label for="graph_munin-{{ $id }}" class="control-label">@lang('Munin plugin')</label>
<select class="form-control" id="graph_munin-{{ $id }}" name="graph_munin" data-placeholder="@lang('Select a Munin plugin')">
@if($graph_munin)
<option value="{{ $graph_munin }}">{{ $munin_text }}</option>
@endif
</select>
</div>
<div class="form-group graph_select_extra-{{ $id }}" id="graph_select_bill-{{ $id }}" style="display: none;">
<label for="graph_bill-{{ $id }}" class="control-label">@lang('Bill')</label>
<select class="form-control" id="graph_bill-{{ $id }}" name="graph_bill" data-placeholder="@lang('Select a bill')">
@if($graph_bill)
<option value="{{ $graph_bill }}">{{ $bill_text }}</option>
@endif
</select>
</div>
<div class="form-group graph_select_extra-{{ $id }}" id="graph_select_custom-{{ $id }}" style="display: none;">
<label for="graph_custom-{{ $id }}" class="control-label">@lang('Custom Aggregator(s)')</label>
<select class="form-control" id="graph_custom-{{ $id }}" name="graph_custom[]" data-tags="true" multiple="multiple" data-placeholder="@lang('Select or add one or more')">
@foreach($graph_custom as $custom)
<option value="{{ $custom }}" selected>{{ ucwords($custom) }}</option>
@endforeach
</select>
</div>
<div class="form-group graph_select_extra-{{ $id }}" id="graph_select_ports-{{ $id }}" style="display: none;">
<label for="graph_ports-{{ $id }}" class="control-label">@lang('Ports')</label>
<select class="form-control" id="graph_ports-{{ $id }}" name="graph_ports[]" multiple="multiple" data-placeholder="@lang('Select one or more')">
@foreach($graph_ports as $port)
<option value="{{ $port->port_id }}" selected>{{ $port->device->shortDisplayName() . ' - ' . $port->getShortLabel() }}</option>
@endforeach
</select>
</div>
@endsection
@section('javascript')
<script>
init_select2('#graph_type-{{ $id }}', 'graph', {}, '{{ $graph_type ?: '' }}');
init_select2('#graph_device-{{ $id }}', 'device', {limit: 100}, '{{ $graph_device ?: '' }}');
init_select2('#graph_port-{{ $id }}', 'port', {limit: 100}, '{{ $graph_port ?: '' }}');
init_select2('#graph_application-{{ $id }}', 'application', function (params) {
var graph_type = $('#graph_type-{{ $id }}').val().split('_');
graph_type.shift();
return {
type: graph_type.shift(),
limit: 100,
term: params.term,
page: params.page || 1
};
}, '{{ $graph_application ?: '' }}');
init_select2('#graph_munin-{{ $id }}', 'munin', {limit: 100}, '{{ $graph_munin ?: '' }}');
init_select2('#graph_bill-{{ $id }}', 'bill', {limit: 100}, '{{ $graph_bill ?: '' }}');
init_select2('#graph_custom-{{ $id }}', 'graph-aggregate', {}, false);
init_select2('#graph_ports-{{ $id }}', 'port', {limit: 100}, {{ $graph_port_ids }});
function switch_graph_type{{ $id }}(data) {
$('.graph_select_extra-{{ $id }}').hide();
if (data !== undefined && data !== '') {
var type = data.split('_').shift();
$('#graph_select_' + type + '-{{ $id }}').show();
}
}
</script>
@endsection

View File

@@ -0,0 +1,57 @@
@extends('widgets.settings.base')
@section('form')
<div class="form-group">
<label for="title-{{ $id }}" class="control-label">@lang('Widget title')</label>
<input type="text" class="form-control" name="title" id="title-{{ $id }}" placeholder="@lang('Default Title')" value="{{ $title }}">
</div>
<div class="form-group">
<label for="stream-{{ $id }}" class="control-label">@lang('Stream')</label>
<select class="form-control" id="stream-{{ $id }}" name="stream" data-placeholder="@lang('All Messages')">
@if($stream)
<option value="{{ $stream }}">{{ $stream }}</option>
@endif
</select>
</div>
<div class="form-group">
<label for="device-{{ $id }}" class="control-label">@lang('Device')</label>
<select class="form-control" id="device-{{ $id }}" name="device" data-placeholder="@lang('All Devices')">
@if($device)
<option value="{{ $device->device_id }}">{{ $device->displayName() }}</option>
@endif
</select>
</div>
<div class="form-group">
<label for="limit-{{ $id }}" class="control-label">@lang('Page Size')</label>
<input type="number" min="1" class="form-control" name="limit" id="limit-{{ $id }}" placeholder="@lang('Page Size')" value="{{ $limit }}">
</div>
<div class="form-group">
<label for="range-{{ $id }}" class="control-label">@lang('Time Range')</label>
<select name="range" id="range-{{ $id }}" class="form-control">
<option value="0" @if($range == 0) selected @endif>@lang('Search all time')</option>
<option value="300" @if($range == 300) selected @endif>@lang('Search last 5 minutes')</option>
<option value="900" @if($range == 900) selected @endif>@lang('Search last 15 minutes')</option>
<option value="1800" @if($range == 1800) selected @endif>@lang('Search last 30 minutes')</option>
<option value="3600" @if($range == 3600) selected @endif>@lang('Search last 1 hour')</option>
<option value="7200" @if($range == 7200) selected @endif>@lang('Search last 2 hours')</option>
<option value="28800" @if($range == 28800) selected @endif>@lang('Search last 8 hours')</option>
<option value="86400" @if($range == 86400) selected @endif>@lang('Search last 1 day')</option>
<option value="172800" @if($range == 172800) selected @endif>@lang('Search last 2 days')</option>
<option value="432000" @if($range == 432000) selected @endif>@lang('Search last 5 days')</option>
<option value="604800" @if($range == 604800) selected @endif>@lang('Search last 7 days')</option>
<option value="1209600" @if($range == 1209600) selected @endif>@lang('Search last 14 days')</option>
<option value="2592000" @if($range == 2592000) selected @endif>@lang('Search last 30 days')</option>
</select>
</div>
@endsection
@section('javascript')
<script type="application/javascript">
init_select2('#device-{{ $id }}', 'device', {limit: 100}, '{{ $device ? $device->device_id : '' }}');
init_select2('#stream-{{ $id }}', 'graylog-streams', {}, '{{ $stream }}');
</script>
@endsection

Some files were not shown because too many files have changed in this diff Show More