Skip to content

Commit

Permalink
Convert the inventory page to Laravel (librenms#15004)
Browse files Browse the repository at this point in the history
* Convert the inventory page to Laravel
Fix several XSS issues (hopefully no new ones snuck in)
Small improvement to the SelectController to allow filtering by filterFields()

* style fixes

* Fix lint issues

* Fix part device filter
  • Loading branch information
murrant authored Apr 28, 2023
1 parent 75f8fe2 commit 5c25cec
Show file tree
Hide file tree
Showing 14 changed files with 345 additions and 208 deletions.
50 changes: 50 additions & 0 deletions app/Http/Controllers/InventoryController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
<?php

namespace App\Http\Controllers;

use App\Models\EntPhysical;
use Illuminate\Contracts\View\View;
use Illuminate\Http\Request;

class InventoryController extends Controller
{
public function __invoke(Request $request): View
{
$this->validate($request, [
'device' => 'nullable|int',
'descr' => 'nullable|string',
'model' => 'nullable|string',
'serial' => 'nullable|string',
]);

$device = \App\Models\Device::hasAccess($request->user())
->select(['device_id', 'hostname', 'ip', 'sysName', 'display'])
->firstWhere('device_id', $request->get('device'));

$model_filter = ['field' => 'model'];
$device_selected = '';
if ($device) {
$device_selected = ['id' => $device->device_id, 'text' => $device->displayName()];
$model_filter['device_id'] = $device->device_id;
}

return view('inventory', [
'device_selected' => $device_selected,
'filter' => [
'device' => $device?->device_id,
'descr' => $request->get('descr'),
'model' => $request->get('model'),
'serial' => $request->get('serial'),
],
'model_filter' => $model_filter,
'show_purge' => EntPhysical::whereDoesntHave('device')->exists(),
]);
}

public function purge()
{
EntPhysical::whereDoesntHave('device')->delete();

return redirect()->back();
}
}
70 changes: 70 additions & 0 deletions app/Http/Controllers/Select/InventoryController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
<?php
/**
* EntPhysicalController.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 <https://www.gnu.org/licenses/>.
*
* @link https://www.librenms.org
*
* @copyright 2023 Tony Murray
* @author Tony Murray <murraytony@gmail.com>
*/

namespace App\Http\Controllers\Select;

use App\Models\EntPhysical;

class InventoryController extends SelectController
{
protected function rules()
{
return [
'field' => 'required|in:name,model,descr,class',
'device' => 'nullable|int',
];
}

protected function filterFields($request)
{
return ['device_id'];
}

protected function searchFields($request)
{
return [$this->fieldToColumn($request->get('field'))];
}

protected function baseQuery($request)
{
$column = $this->fieldToColumn($request->get('field'));

return EntPhysical::hasAccess($request->user())
->select($column)
->orderBy($column)
->distinct();
}

private function fieldToColumn(string $field): string
{
return match ($field) {
'name' => 'entPhysicalName',
'model' => 'entPhysicalModelName',
'descr' => 'entPhysicalDescr',
'class' => 'entPhysicalClass',
default => 'entPhysicalName',
};
}
}
22 changes: 14 additions & 8 deletions app/Http/Controllers/Select/PortFieldController.php
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,19 @@ protected function rules()
];
}

/**
* Defines fields that can be used as filters
*
* @param $request
* @return string[]
*/
protected function filterFields($request)
{
return [
'device_id' => 'device',
];
}

/**
* Defines search fields will be searched in order
*
Expand All @@ -61,14 +74,7 @@ protected function searchFields($request)
*/
protected function baseQuery($request)
{
/** @var \Illuminate\Database\Eloquent\Builder $query */
$query = Port::hasAccess($request->user())
return Port::hasAccess($request->user())
->select($request->get('field'))->distinct();

if ($device_id = $request->get('device')) {
$query->where('ports.device_id', $device_id);
}

return $query;
}
}
3 changes: 2 additions & 1 deletion app/Http/Controllers/Select/SelectController.php
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,8 @@ public function __invoke(Request $request)
$query = $this->baseQuery($request)->when($request->has('id'), function ($query) {
return $query->whereKey(request('id'));
});
$query = $this->search($request->get('term'), $query, $this->searchFields($request));
$this->filter($request, $query, $this->filterFields($request));
$this->search($request->get('term'), $query, $this->searchFields($request));
$this->sort($request, $query);
$paginator = $query->simplePaginate($limit);

Expand Down
96 changes: 96 additions & 0 deletions app/Http/Controllers/Table/InventoryController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
<?php
/**
* InventoryController.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 <https://www.gnu.org/licenses/>.
*
* @link https://www.librenms.org
*
* @copyright 2023 Tony Murray
* @author Tony Murray <murraytony@gmail.com>
*/

namespace App\Http\Controllers\Table;

use App\Models\EntPhysical;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Collection;
use LibreNMS\Util\Url;

class InventoryController extends TableController
{
public function rules()
{
return [
'device' => 'nullable|int',
'descr' => 'nullable|string',
'model'=> 'nullable|string',
'serial' => 'nullable|string',
];
}

protected function filterFields($request)
{
return [
'device_id' => 'device',
];
}

protected function searchFields($request)
{
return ['entPhysicalDescr', 'entPhysicalModelName', 'entPhysicalSerialNum'];
}

protected function sortFields($request)
{
return [
'device' => 'device_id',
'name' => 'entPhysicalName',
'descr' => 'entPhysicalDescr',
'model' => 'entPhysicalModelName',
'serial' => 'entPhysicalSerialNum',
];
}

protected function baseQuery($request)
{
$query = EntPhysical::hasAccess($request->user())
->with('device')
->select(['entPhysical_id', 'device_id', 'entPhysicalDescr', 'entPhysicalName', 'entPhysicalModelName', 'entPhysicalSerialNum']);

// apply specific field filters
$this->search($request->get('descr'), $query, ['entPhysicalDescr']);
$this->search($request->get('model'), $query, ['entPhysicalModelName']);
$this->search($request->get('serial'), $query, ['entPhysicalSerialNum']);

return $query;
}

/**
* @param EntPhysical $entPhysical
* @return array|Model|Collection
*/
public function formatItem($entPhysical)
{
return [
'device' => Url::deviceLink($entPhysical->device),
'descr' => htmlspecialchars($entPhysical->entPhysicalDescr),
'name' => htmlspecialchars($entPhysical->entPhysicalName),
'model' => htmlspecialchars($entPhysical->entPhysicalModelName),
'serial' => htmlspecialchars($entPhysical->entPhysicalSerialNum),
];
}
}
2 changes: 1 addition & 1 deletion app/Http/Controllers/Table/TableController.php
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,8 @@ public function __invoke(Request $request)
/** @var Builder $query */
$query = $this->baseQuery($request);

$this->search($request->get('searchPhrase'), $query, $this->searchFields($request));
$this->filter($request, $query, $this->filterFields($request));
$this->search($request->get('searchPhrase'), $query, $this->searchFields($request));
$this->sort($request, $query);

$limit = $request->get('rowCount', 25);
Expand Down
2 changes: 1 addition & 1 deletion html/css/app.css

Large diffs are not rendered by default.

16 changes: 8 additions & 8 deletions html/mix-manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,15 @@
"/js/app.js": "/js/app.js?id=5ddec7f7302f146a8dcc",
"/js/manifest.js": "/js/manifest.js?id=2951ae529be231f05a93",
"/css/vendor.css": "/css/vendor.css?id=2568831af31dbfc3128a",
"/css/app.css": "/css/app.css?id=bd093a6a2e2682bb59ef",
"/css/app.css": "/css/app.css?id=1cd88608bf4eaee000d8",
"/js/vendor.js": "/js/vendor.js?id=c5fd3d75a63757080dbb",
"/js/lang/de.js": "/js/lang/de.js?id=613b5ca9cd06ca15e384",
"/js/lang/en.js": "/js/lang/en.js?id=efa23897934359283288",
"/js/lang/fr.js": "/js/lang/fr.js?id=4540d71a19d8ca7c824b",
"/js/lang/it.js": "/js/lang/it.js?id=71c68fae57a4a3647e43",
"/js/lang/de.js": "/js/lang/de.js?id=d74df23e729c5dabfee8",
"/js/lang/en.js": "/js/lang/en.js?id=20e52084af3a0a8f4724",
"/js/lang/fr.js": "/js/lang/fr.js?id=22902d30358443ef2877",
"/js/lang/it.js": "/js/lang/it.js?id=6220e138068a7e58387f",
"/js/lang/ru.js": "/js/lang/ru.js?id=f6b7c078755312a0907c",
"/js/lang/sr.js": "/js/lang/sr.js?id=388e38b41f63e3517506",
"/js/lang/uk.js": "/js/lang/uk.js?id=72f81fcbf77df09d0c82",
"/js/lang/zh-CN.js": "/js/lang/zh-CN.js?id=4e081fbac70d969894bf",
"/js/lang/zh-TW.js": "/js/lang/zh-TW.js?id=ed26425647721a42ee9d"
"/js/lang/uk.js": "/js/lang/uk.js?id=fdfb4cfa77a3340e50f8",
"/js/lang/zh-CN.js": "/js/lang/zh-CN.js?id=cc4309e63a32a671f107",
"/js/lang/zh-TW.js": "/js/lang/zh-TW.js?id=2248687ad44f27299377"
}
100 changes: 0 additions & 100 deletions includes/html/pages/inventory.inc.php

This file was deleted.

Loading

0 comments on commit 5c25cec

Please sign in to comment.