Update syslog display and backend (#9228)

* Update syslog display backend
select boxes now dynamically load instead of loading all on pageload
select and table ajax backends completely redone with Laravel (just syslog for now)
duplicate url creation to Url utility class for now (uses Device model instead of array)
build short hostname functionality into Device->displayName() helper

* Fix whitespace

* Some tidying up. Split out displayName() and shortDisplayName()

* Enable auto-sizing.
Fix small error in Url

* Eager load device
Use bootstrap theme for select2
This commit is contained in:
Tony Murray
2018-09-20 15:33:03 -05:00
committed by Neil Lathwood
parent c30d494505
commit 21ca8bf0b0
17 changed files with 915 additions and 160 deletions

216
LibreNMS/Util/Url.php Normal file
View File

@@ -0,0 +1,216 @@
<?php
/**
* Url.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 Auth;
use Carbon\Carbon;
use LibreNMS\Config;
class Url
{
/**
* @param Device $device
* @param string $text
* @param array $vars
* @param int $start
* @param int $end
* @param int $escape_text
* @param int $overlib
* @return string
*/
public static function deviceLink($device, $text = null, $vars = [], $start = 0, $end = 0, $escape_text = 1, $overlib = 1)
{
if (!$start) {
$start = Carbon::now()->subDay(1)->timestamp;
}
if (!$end) {
$end = Carbon::now()->timestamp;
}
if (!$text) {
$text = $device->displayName();
}
if ($escape_text) {
$text = htmlentities($text);
}
$class = self::deviceLinkDisplayClass($device);
$graphs = self::getOverviewGraphsForDevice($device);
$url = Url::deviceUrl($device, $vars);
// beginning of overlib box contains large hostname followed by hardware & OS details
$contents = '<div><span class="list-large">' . $device->displayName() . '</span>';
if ($device->hardware) {
$contents .= ' - ' . htmlentities($device->hardware);
}
if ($device->os) {
$contents .= ' - ' . htmlentities(Config::getOsSetting($device->os, 'text'));
}
if ($device->version) {
$contents .= ' ' . htmlentities($device->version);
}
if ($device->features) {
$contents .= ' (' . htmlentities($device->features) . ')';
}
if ($device->location) {
$contents .= ' - ' . htmlentities($device->location);
}
$contents .= '</div>';
foreach ((array)$graphs as $entry) {
$graph = isset($entry['graph']) ? $entry['graph'] : 'unknown';
$graphhead = isset($entry['text']) ? $entry['text'] : 'unknown';
$contents .= '<div class="overlib-box">';
$contents .= '<span class="overlib-title">' . $graphhead . '</span><br />';
$contents .= Url::minigraphImage($device, $start, $end, $graph);
$contents .= Url::minigraphImage($device, Carbon::now()->subWeek(1)->timestamp, $end, $graph);
$contents .= '</div>';
}
if ($overlib == 0) {
$link = $contents;
} else {
// escape quotes
$contents = str_replace(["'", '"'], "\'", $contents);
$link = Url::overlibLink($url, $text, $contents, $class);
}
if (Auth::user()->hasGlobalRead() || $device->users()->where('devices_perms.user_id', Auth::id())->exists()) {
return $link;
} else {
return $device->displayName();
}
}
public static function deviceUrl($device, $vars = [])
{
return self::generate(['page' => 'device', 'device' => $device->device_id], $vars);
}
public static function generate($vars, $new_vars = [])
{
$vars = array_merge($vars, $new_vars);
$url = $vars['page'] . '/';
unset($vars['page']);
foreach ($vars as $var => $value) {
if ($value == '0' || $value != '' && !str_contains($var, 'opt') && !is_numeric($var)) {
$url .= $var . '=' . urlencode($value) . '/';
}
}
return $url;
}
public static function overlibLink($url, $text, $contents, $class = null)
{
$contents = "<div style=\'background-color: #FFFFFF;\'>" . $contents . '</div>';
$contents = str_replace('"', "\'", $contents);
if ($class === null) {
$output = '<a href="' . $url . '"';
} else {
$output = '<a class="' . $class . '" href="' . $url . '"';
}
if (Config::get('web_mouseover', true)) {
$defaults = Config::get('overlib_defaults', ",FGCOLOR,'#ffffff', BGCOLOR, '#e5e5e5', BORDER, 5, CELLPAD, 4, CAPCOLOR, '#555555', TEXTCOLOR, '#3e3e3e'");
$output .= " onmouseover=\"return overlib('$contents'$defaults,WRAP,HAUTO,VAUTO); \" onmouseout=\"return nd();\">";
} else {
$output .= '>';
}
$output .= $text . '</a>';
return $output;
}
/**
* Generate minigraph image url
*
* @param Device $device
* @param int $start
* @param int $end
* @param string $type
* @param string $legend
* @param int $width
* @param int $height
* @param string $sep
* @param string $class
* @param int $absolute_size
* @return string
*/
public static function minigraphImage($device, $start, $end, $type, $legend = 'no', $width = 275, $height = 100, $sep = '&amp;', $class = 'minigraph-image', $absolute_size = 0)
{
$vars = ['device=' . $device->device_id, "from=$start", "to=$end", "width=$width", "height=$height", "type=$type", "legend=$legend", "absolute=$absolute_size"];
return '<img class="' . $class . '" width="' . $width . '" height="' . $height . '" src="graph.php?' . implode($sep, $vars) . '">';
}
private static function getOverviewGraphsForDevice($device)
{
if ($device->snmp_disable) {
return Config::getOsSetting('ping', 'over');
}
if ($graphs = Config::getOsSetting($device->os, 'over')) {
return $graphs;
}
if ($os_group = Config::getOsSetting($device->os, 'os_group')) {
$name = key($os_group);
if (isset($os_group[$name]['over'])) {
return $os_group[$name]['over'];
}
}
return Config::getOsSetting('default', 'over');
}
/**
* @param Device $device
* @return string
*/
private static function deviceLinkDisplayClass($device)
{
if ($device->disabled) {
return 'list-device-disabled';
}
if ($device->ignore) {
return $device->status ? 'list-device-ignored-up' : 'list-device-ignored';
}
return $device->status ? 'list-device' : 'list-device-down';
}
}

View File

@@ -0,0 +1,125 @@
<?php
/**
* AjaxController.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;
use Illuminate\Contracts\Pagination\Paginator;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Http\Request;
use Illuminate\Support\Collection;
abstract class PaginatedAjaxController extends Controller
{
/**
* Base rules for this controller.
*
* @return mixed
*/
abstract protected function baseRules();
/**
* Defines the base query for this resource
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Database\Eloquent\Builder|\Illuminate\Database\Query\Builder
*/
abstract public function baseQuery($request);
/**
* @param Paginator $paginator
* @return \Illuminate\Http\JsonResponse
*/
abstract protected function formatResponse($paginator);
/**
* Defines validation rules (will override base validation rules for select2 responses too)
*
* @return array
*/
public function rules()
{
return [];
}
/**
* Defines search fields will be searched in order
*
* @param \Illuminate\Http\Request $request
* @return array
*/
public function searchFields($request)
{
return [];
}
/**
* Format an item for display. Default is pass-through
*
* @param Model $model
* @return array|Collection|Model
*/
public function formatItem($model)
{
return $model;
}
/**
* @param string
* @param Builder $query
* @param array $fields
* @return Builder
*/
protected function search($search, $query, $fields)
{
if ($search) {
$query->where(function ($query) use ($fields, $search) {
/** @var Builder $query */
foreach ($fields as $field) {
$query->orWhere($field, 'like', '%' . $search . '%');
}
});
}
return $query;
}
/**
* 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($this->baseRules(), $rules);
parent::validate($request, $full_rules, $messages, $customAttributes);
}
}

View File

@@ -4,11 +4,9 @@ namespace App\Http\Controllers;
use Illuminate\Http\Request;
class AjaxController extends Controller
class ResolutionController extends Controller
{
// FIXME do not just pile functions on this controller, create separate controllers
public function setResolution(Request $request)
public function set(Request $request)
{
$this->validate($request, [
'width' => 'required|numeric',

View File

@@ -0,0 +1,50 @@
<?php
/**
* DeviceController.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\Device;
class DeviceController extends SelectController
{
public function searchFields($request)
{
return ['hostname', 'sysName'];
}
public function baseQuery($request)
{
return Device::hasAccess($request->user())->select('device_id', 'hostname', 'sysName');
}
public function formatItem($device)
{
/** @var Device $device */
return [
'id' => $device->device_id,
'text' => $device->displayName(),
];
}
}

View File

@@ -0,0 +1,90 @@
<?php
/**
* SelectController.php
*
* Controller class for select2 ajax controllers.
*
* 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\PaginatedAjaxController;
use Illuminate\Contracts\Pagination\Paginator;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Http\Request;
abstract class SelectController extends PaginatedAjaxController
{
final protected function baseRules()
{
return [
'limit' => 'int',
'page' => 'int',
'term' => 'nullable|string',
];
}
/**
* The default method called by the route handler
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\JsonResponse
*/
public function __invoke(Request $request)
{
$this->validate($request, $this->rules());
$limit = $request->get('limit', 20);
$query = $this->search($request->get('term'), $this->baseQuery($request), $this->searchFields($request));
$paginator = $query->simplePaginate($limit);
return $this->formatResponse($paginator);
}
/**
* @param Paginator $paginator
* @return \Illuminate\Http\JsonResponse
*/
protected function formatResponse($paginator)
{
return response()->json([
'results' => collect($paginator->items())->map([$this, 'formatItem']),
'pagination' => ['more' => $paginator->hasMorePages()]
]);
}
/**
* Default item formatting, should supply at least id and text keys
* Check select2 docs.
* Default implementation uses primary key and the first value in the model
* If only one value is in the model attributes, that is the id and text.
*
* @param Model $model
* @return array
*/
public function formatItem($model)
{
$attributes = collect($model->getAttributes());
return [
'id' => $attributes->count() == 1 ? $attributes->first() : $model->getKey(),
'text' => $attributes->forget($model->getKeyName())->first(),
];
}
}

View File

@@ -0,0 +1,72 @@
<?php
/**
* Syslog.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;
class SyslogController extends SelectController
{
/**
* Defines validation rules (will override base validation rules for select2 responses too)
*
* @return array
*/
public function rules()
{
return [
'field' => 'required|in:program,priority',
'device' => 'nullable|int',
];
}
/**
* Defines search fields will be searched in order
*
* @param \Illuminate\Http\Request $request
* @return array
*/
public 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
*/
public function baseQuery($request)
{
/** @var \Illuminate\Database\Eloquent\Builder $query */
$query = \App\Models\Syslog::hasAccess($request->user())
->select($request->get('field'))->distinct();
if ($device_id = $request->get('device')) {
$query->where('device_id', $device_id);
}
return $query;
}
}

View File

@@ -0,0 +1,96 @@
<?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\Table;
use App\Models\Syslog;
use Illuminate\Database\Eloquent\Builder;
class SyslogController extends TableController
{
public function searchFields($request)
{
return ['msg'];
}
public function rules()
{
return [
'device' => 'nullable|int',
'program' => 'nullable|string',
'priority' => 'nullable|string',
'to' => 'nullable|date',
'from' => 'nullable|date',
];
}
/**
* Defines the base query for this resource
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Database\Eloquent\Builder|\Illuminate\Database\Query\Builder
*/
public function baseQuery($request)
{
/** @var Builder $query */
$query = Syslog::hasAccess($request->user())->with('device');
if ($device_id = $request->get('device')) {
$query->where('device_id', $device_id);
}
if ($program = $request->get('program')) {
$query->where('program', $program);
}
if ($priority = $request->get('priority')) {
$query->where('priority', $priority);
}
if ($from = $request->get('from')) {
$query->where('timestamp', '>=', $from);
}
if ($to = $request->get('to')) {
$query->where('timestamp', '<=', $to);
}
return $query;
}
public function formatItem($syslog)
{
$device = $syslog->device;
return [
'timestamp' => $syslog->timestamp,
'level' => $syslog->level,
'device_id' => $device ? \LibreNMS\Util\Url::deviceLink($device, $device->shortDisplayName()) : '',
'program' => $syslog->program,
'msg' => $syslog->msg,
'priority' => $syslog->priority,
];
}
}

View File

@@ -0,0 +1,79 @@
<?php
/**
* TableController.php
*
* Controller class for bootgrid ajax controllers.
*
* 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\PaginatedAjaxController;
use Illuminate\Contracts\Pagination\LengthAwarePaginator;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Http\Request;
abstract class TableController extends PaginatedAjaxController
{
final protected function baseRules()
{
return [
'current' => 'int',
'rowCount' => 'int',
'searchPhrase' => 'nullable|string',
'sort.*' => 'in:asc,desc',
];
}
public function __invoke(Request $request)
{
$this->validate($request, $this->rules());
/** @var Builder $query */
$query = $this->baseQuery($request);
$this->search($request->get('searchPhrase'), $query, $this->searchFields($request));
$sort = $request->get('sort', []);
foreach ($sort as $column => $direction) {
$query->orderBy($column, $direction);
}
$limit = $request->get('rowCount', 25);
$page = $request->get('current', 1);
$paginator = $query->paginate($limit, ['*'], 'page', $page);
return $this->formatResponse($paginator);
}
/**
* @param LengthAwarePaginator $paginator
* @return \Illuminate\Http\JsonResponse
*/
protected function formatResponse($paginator)
{
return response()->json([
'current' => $paginator->currentPage(),
'rowCount' => $paginator->count(),
'rows' => collect($paginator->items())->map([$this, 'formatItem']),
'total' => $paginator->total(),
]);
}
}

View File

@@ -6,6 +6,7 @@ use Fico7489\Laravel\Pivot\Traits\PivotEventTrait;
use Illuminate\Database\Eloquent\ModelNotFoundException;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Query\JoinClause;
use LibreNMS\Config;
use LibreNMS\Exceptions\InvalidIpException;
use LibreNMS\Util\IP;
use LibreNMS\Util\IPv4;
@@ -143,13 +144,38 @@ class Device extends BaseModel
*/
public function displayName()
{
if (\LibreNMS\Config::get('force_ip_to_sysname') && $this->sysName && IP::isValid($this->hostname)) {
if (Config::get('force_ip_to_sysname') && $this->sysName && IP::isValid($this->hostname)) {
return $this->sysName;
}
return $this->hostname;
}
/**
* Get the shortened display name of this device.
* Length is always overridden by shorthost_target_length.
*
* @param int $length length to shorten to, will not break up words so may be longer
* @return string
*/
public function shortDisplayName($length = 12)
{
$name = $this->displayName();
// IP addresses should not be shortened
if (IP::isValid($name)) {
return $name;
}
$length = Config::get('shorthost_target_length', $length);
if ($length < strlen($name)) {
$take = substr_count($name, '.', 0, $length) + 1;
return implode('.', array_slice(explode('.', $name), 0, $take));
}
return $name;
}
public function formatUptime($short = false)
{
$result = '';

47
app/Models/Syslog.php Normal file
View File

@@ -0,0 +1,47 @@
<?php
/**
* Syslog.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 Syslog extends BaseModel
{
protected $table = 'syslog';
protected $primaryKey = 'seq';
public $timestamps = false;
// ---- 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', 'device_id');
}
}

View File

@@ -13,6 +13,7 @@
/** @var \Illuminate\Database\Eloquent\Factory $factory */
use Carbon\Carbon;
use LibreNMS\Util\IPv4;
$factory->define(App\User::class, function (Faker\Generator $faker) {
@@ -82,3 +83,18 @@ $factory->define(\App\Models\Ipv4Network::class, function (Faker\Generator $fake
'ipv4_network' => $faker->ipv4 . '/' . $faker->numberBetween(0, 32),
];
});
$factory->define(\App\Models\Syslog::class, function (Faker\Generator $faker) {
$facilities = ['kern', 'user', 'mail', 'daemon', 'auth', 'syslog', 'lpr', 'news', 'uucp', 'cron', 'authpriv', 'ftp', 'ntp', 'security', 'console', 'solaris-cron', 'local0', 'local1', 'local2', 'local3', 'local4', 'local5', 'local6', 'local7'];
$levels = ['emerg', 'alert', 'crit', 'err', 'warning', 'notice', 'info', 'debug'];
return [
'facility' => $faker->randomElement($facilities),
'priority' => $faker->randomElement($levels),
'level' => $faker->randomElement($levels),
'tag' => $faker->asciify(str_repeat('*', $faker->numberBetween(0, 10))),
'timestamp' => Carbon::now(),
'program' => $faker->asciify(str_repeat('*', $faker->numberBetween(0, 32))),
'msg' => $faker->text(),
];
});

View File

@@ -37,15 +37,14 @@ var syslog_grid = $("#syslog").bootgrid({
post: function ()
{
return {
id: "syslog",
device: "'.mres($vars['device']) .'",
program: "'.mres($vars['program']).'",
priority: "'.mres($vars['priority']).'",
to: "'.mres($vars['to']).'",
from: "'.mres($vars['from']).'",
device: "' . addcslashes($vars['device'], '"') . '",
program: "' . addcslashes($vars['program'], '"') . '",
priority: "' . addcslashes($vars['priority'], '"') . '",
to: "' . addcslashes($vars['to'], '"') . '",
from: "' . addcslashes($vars['from'], '"') . '",
};
},
url: "ajax_table.php"
url: "ajax/table/syslog"
});
</script>

View File

@@ -1,102 +0,0 @@
<?php
/*
* 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 LibreNMS
* @subpackage webui
* @link http://librenms.org
* @copyright 2018 LibreNMS
* @author LibreNMS Contributors
*/
use LibreNMS\Authentication\LegacyAuth;
$where = '1';
$param = array();
if (!empty($vars['searchPhrase'])) {
$where .= ' AND S.msg LIKE "%'.mres($vars['searchPhrase']).'%"';
}
if ($vars['program']) {
$where .= ' AND S.program = ?';
$param[] = $vars['program'];
}
if (is_numeric($vars['device'])) {
$where .= ' AND S.device_id = ?';
$param[] = $vars['device'];
}
if ($vars['priority']) {
$where .= ' AND S.priority = ?';
$param[] = $vars['priority'];
}
if (!empty($vars['from'])) {
$where .= ' AND timestamp >= ?';
$param[] = $vars['from'];
}
if (!empty($vars['to'])) {
$where .= ' AND timestamp <= ?';
$param[] = $vars['to'];
}
if (LegacyAuth::user()->hasGlobalRead()) {
$sql = 'FROM syslog AS S';
$sql .= ' WHERE '.$where;
} else {
$sql = 'FROM syslog AS S, devices_perms AS P ';
$sql .= 'WHERE S.device_id = P.device_id AND P.user_id = ? AND ';
$sql .= $where;
$param = array_merge(array(LegacyAuth::id()), $param);
}
$count_sql = "SELECT COUNT(*) $sql";
$total = dbFetchCell($count_sql, $param);
if (empty($total)) {
$total = 0;
}
if (!isset($sort) || empty($sort)) {
$sort = 'timestamp DESC';
}
$sql .= " ORDER BY $sort";
if (isset($current)) {
$limit_low = (($current * $rowCount) - ($rowCount));
$limit_high = $rowCount;
}
if ($rowCount != -1) {
$sql .= " LIMIT $limit_low,$limit_high";
}
$sql = "SELECT S.*, DATE_FORMAT(timestamp, '".$config['dateformat']['mysql']['compact']."') AS date $sql";
foreach (dbFetchRows($sql, $param) as $syslog) {
$dev = device_by_id_cache($syslog['device_id']);
$response[] = array(
'label' => generate_priority_label($syslog['priority']),
'timestamp' => $syslog['date'],
'level' => $syslog['priority'],
'device_id' => generate_device_link($dev, shorthost($dev['hostname'])),
'program' => $syslog['program'],
'msg' => display($syslog['msg']),
'priority' => generate_priority_status($syslog['priority']),
);
}
$output = array(
'current' => $current,
'rowCount' => $rowCount,
'rows' => $response,
'total' => $total,
);
echo _json_encode($output);

View File

@@ -99,6 +99,7 @@ if (empty($config['favicon'])) {
<link href="css/MarkerCluster.Default.css" rel="stylesheet" type="text/css" />
<link href="css/leaflet.awesome-markers.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/query-builder.default.min.css" rel="stylesheet" type="text/css" />
<link href="<?php echo($config['stylesheet']); ?>?ver=291727421" rel="stylesheet" type="text/css" />
<link href="css/<?php echo $config['site_style']; ?>.css?ver=632417642" rel="stylesheet" type="text/css" />

View File

@@ -13,12 +13,14 @@
* @author LibreNMS Contributors
*/
use LibreNMS\Authentication\LegacyAuth;
use Carbon\Carbon;
use LibreNMS\Config;
$no_refresh = true;
$param = array();
$param = [];
$device_id = (int)$vars['device'];
if ($vars['action'] == 'expunge' && LegacyAuth::user()->hasGlobalAdmin()) {
if ($vars['action'] == 'expunge' && \Auth::user()->hasGlobalAdmin()) {
dbQuery('TRUNCATE TABLE `syslog`');
print_message('syslog truncated');
}
@@ -35,7 +37,6 @@ $pagetitle[] = 'Syslog';
echo implode('', $common_output);
?>
</div>
<script>
$('.actionBar').append(
'<div class="pull-left">' +
@@ -44,73 +45,49 @@ $pagetitle[] = 'Syslog';
<?php
if (!isset($vars['fromdevice'])) {
?>
'<select name="device" id="device" class="form-control input-sm">' +
'<select name="device" id="device" class="form-control">' +
'<option value="">All Devices&nbsp;&nbsp;</option>' +
<?php
foreach (get_all_devices() as $data) {
if (device_permitted($data['device_id'])) {
echo "'<option value=\"" . $data['device_id'] . "\"";
if ($data['device_id'] == $vars['device']) {
echo ' selected';
}
echo ">" . format_hostname($data) . "</option>' + ";
}
if ($device_id) {
echo "'<option value=$device_id>" . format_hostname(device_by_id_cache($device_id)) . "</option>' +";
}
?>
'</select>' +
<?php
} else {
echo "'&nbsp;&nbsp;<input type=\"hidden\" name=\"device\" id=\"device\" value=\"" . $vars['device'] . "\">' + ";
echo "'&nbsp;&nbsp;<input type=\"hidden\" name=\"device\" id=\"device\" value=\"" . $device_id . "\">' + ";
}
?>
'</div>' +
'&nbsp;&nbsp;<div class="form-group">' +
'<select name="program" id="program" class="form-control input-sm">' +
'<select name="program" id="program" class="form-control">' +
'<option value="">All Programs&nbsp;&nbsp;</option>' +
<?php
$sqlstatement = 'SELECT DISTINCT `program` FROM `syslog`';
if (is_numeric($vars['device'])) {
$sqlstatement = $sqlstatement . ' WHERE device_id=?';
$param[] = $vars['device'];
}
$sqlstatement = $sqlstatement . ' ORDER BY `program`';
foreach (dbFetchRows($sqlstatement, $param) as $data) {
echo "'<option value=\"" . $data['program'] . "\"";
if ($data['program'] == $vars['program']) {
echo ' selected';
}
echo ">" . $data['program'] . "</option>' + ";
if ($vars['program']) {
$js_program = addcslashes(htmlentities($vars['program']), "'");
echo "'<option value=\"$js_program\">$js_program</option>' +";
}
?>
'</select>' +
'</div>' +
'&nbsp;&nbsp;<div class="form-group">' +
'<select name="priority" id="priority" class="form-control input-sm">' +
'<select name="priority" id="priority" class="form-control">' +
'<option value="">All Priorities</option>' +
<?php
$sqlstatement = 'SELECT DISTINCT `priority` FROM `syslog`';
if (is_numeric($vars['device'])) {
$sqlstatement = $sqlstatement . ' WHERE device_id=?';
$param[] = $vars['device'];
}
$sqlstatement = $sqlstatement . ' ORDER BY `level`';
foreach (dbFetchRows($sqlstatement, $param) as $data) {
echo "'<option value=\"" . $data['priority'] . "\"";
if ($data['priority'] == $vars['priority']) {
echo ' selected';
}
echo ">" . $data['priority'] . "</option>' + ";
if ($vars['priority']) {
$js_priority = addcslashes(htmlentities($vars['priority']), "'");
echo "'<option value=\"$js_priority\">$js_priority</option>' +";
}
?>
'</select>' +
'</div>' +
'&nbsp;&nbsp;<div class="form-group">' +
'<input name="from" type="text" class="form-control input-sm" id="dtpickerfrom" maxlength="16" value="<?php echo $vars['from']; ?>" placeholder="From" data-date-format="YYYY-MM-DD HH:mm">' +
'<input name="from" type="text" class="form-control" id="dtpickerfrom" maxlength="16" value="<?php echo $vars['from']; ?>" placeholder="From" data-date-format="YYYY-MM-DD HH:mm">' +
'</div>' +
'<div class="form-group">' +
'&nbsp;&nbsp;<input name="to" type="text" class="form-control input-sm" id="dtpickerto" maxlength="16" value="<?php echo $vars['to']; ?>" placeholder="To" data-date-format="YYYY-MM-DD HH:mm">' +
'&nbsp;&nbsp;<input name="to" type="text" class="form-control" id="dtpickerto" maxlength="16" value="<?php echo $vars['to']; ?>" placeholder="To" data-date-format="YYYY-MM-DD HH:mm">' +
'</div>' +
'&nbsp;&nbsp;<button type="submit" class="btn btn-default input-sm">Filter</button>' +
'&nbsp;&nbsp;<button type="submit" class="btn btn-default">Filter</button>' +
'</form>' +
'</div>' +
'</div>' +
@@ -130,7 +107,8 @@ $pagetitle[] = 'Syslog';
today: 'fa fa-calendar-check-o',
clear: 'fa fa-trash-o',
close: 'fa fa-close'
}
},
defaultDate: '<?php echo Carbon::now()->subDay()->format(Config::get('dateformat.byminute', 'Y-m-d H:i')); ?>'
});
$("#dtpickerfrom").on("dp.change", function (e) {
$("#dtpickerto").data("DateTimePicker").minDate(e.date);
@@ -157,8 +135,62 @@ $pagetitle[] = 'Syslog';
if ($("#dtpickerto").val() != "") {
$("#dtpickerfrom").data("DateTimePicker").maxDate($("#dtpickerto").val());
} else {
$("#dtpickerto").data("DateTimePicker").maxDate('<?php echo date($config['dateformat']['byminute']); ?>');
$("#dtpickerto").data("DateTimePicker").maxDate('<?php echo Carbon::now()->format(Config::get('dateformat.byminute', 'Y-m-d H:i')); ?>');
}
});
<?php if (!isset($vars['fromdevice'])) { ?>
$("#device").select2({
theme: "bootstrap",
dropdownAutoWidth : true,
width: "auto",
allowClear: true,
placeholder: "All Devices",
ajax: {
url: 'ajax/select/device',
delay: 200
}
})<?php echo $device_id ? ".val($device_id).trigger('change');" : ''; ?>;
<?php } ?>
$("#program").select2({
theme: "bootstrap",
dropdownAutoWidth : true,
width: "auto",
allowClear: true,
placeholder: "All Programs",
ajax: {
url: 'ajax/select/syslog',
delay: 200,
data: function(params) {
return {
field: "program",
device: $('#device').val(),
term: params.term,
page: params.page || 1
}
}
}
})<?php echo $vars['program'] ? ".val('" . addcslashes($vars['program'], "'") . "').trigger('change');" : ''; ?>;
$("#priority").select2({
theme: "bootstrap",
dropdownAutoWidth : true,
width: "auto",
allowClear: true,
placeholder: "All Priorities",
ajax: {
url: 'ajax/select/syslog',
delay: 200,
data: function(params) {
return {
field: "priority",
device: $('#device').val(),
term: params.term,
page: params.page || 1
}
}
}
})<?php echo $vars['priority'] ? ".val('" . addcslashes($vars['priority'], "'") . "').trigger('change');" : ''; ?>;
</script>

View File

@@ -37,6 +37,7 @@
<link href="css/MarkerCluster.Default.css" rel="stylesheet" type="text/css" />
<link href="css/leaflet.awesome-markers.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/query-builder.default.min.css" rel="stylesheet" type="text/css" />
<link href="{{ LibreNMS\Config::get('stylesheet', 'css/styles.css') }}?ver=20180512" rel="stylesheet" type="text/css" />
<link href="css/{{ LibreNMS\Config::get('site_style', 'light') }}.css?ver=632417642" rel="stylesheet" type="text/css" />

View File

@@ -30,7 +30,16 @@ Route::group(['middleware' => ['auth', '2fa'], 'guard' => 'auth'], function () {
// Ajax routes
Route::group(['prefix' => 'ajax'], function () {
Route::post('set_resolution', 'AjaxController@setResolution');
Route::post('set_resolution', 'ResolutionController@set');
Route::group(['prefix' => 'select', 'namespace' => 'Select'], function () {
Route::get('syslog', 'SyslogController');
Route::get('device', 'DeviceController');
});
Route::group(['prefix' => 'table', 'namespace' => 'Table'], function () {
Route::post('syslog', 'SyslogController');
});
});
// Debugbar routes need to be here because of catch-all