Skip to content

Commit f8ddb29

Browse files
committed
Merge origin/master into WIP-add-restify-api
2 parents 3a3583d + 7a0e0fd commit f8ddb29

658 files changed

Lines changed: 151968 additions & 10068 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

LibreNMS/Authentication/RadiusAuthorizer.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ public function authenticate($credentials)
3636
$this->radius->setDebug(true);
3737
}
3838

39+
$this->radius->setIncludeMessageAuthenticator();
3940
$password = $credentials['password'] ?? null;
4041
if ($this->radius->accessRequest($credentials['username'], $password) === true) {
4142
$user = User::thisAuth()->firstOrNew(['username' => $credentials['username']], [

LibreNMS/Cache/PermissionsCache.php

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,9 @@
2828
use App\Facades\LibrenmsConfig;
2929
use App\Models\Bill;
3030
use App\Models\Device;
31+
use App\Models\DeviceGroup;
3132
use App\Models\Port;
33+
use App\Models\PortGroup;
3234
use App\Models\User;
3335
use Illuminate\Database\Query\Builder;
3436
use Illuminate\Support\Collection;
@@ -43,6 +45,9 @@ class PermissionsCache
4345
/** @var array<int, Collection<int>> */
4446
private array $deviceGroupMap = [];
4547

48+
/** @var array<int, Collection<int>> */
49+
private array $portGroupPermissions = [];
50+
4651
/** @var Collection<object{user_id: int, port_id: int}>|null */
4752
private ?Collection $portPermissions = null;
4853

@@ -59,6 +64,12 @@ public function canAccessDevice(Device|int $device, User|int|null $user = null):
5964
->contains('device_id', $this->getDeviceId($device));
6065
}
6166

67+
public function canAccessDeviceGroup(DeviceGroup|int $deviceGroup, User|int|null $user = null): bool
68+
{
69+
return $this->deviceGroupsForUser($user)
70+
->contains(is_int($deviceGroup) ? $deviceGroup : $deviceGroup->id);
71+
}
72+
6273
/**
6374
* Check if a access can be accessed by user (non-global read/admin)
6475
* If no user is given, use the logged in user
@@ -71,6 +82,16 @@ public function canAccessPort(Port|int $port, User|int|null $user = null): bool
7182
->isNotEmpty();
7283
}
7384

85+
/**
86+
* Check if a port group can be accessed by user (non-global read/admin)
87+
* If no user is given, use the logged in user
88+
*/
89+
public function canAccessPortGroup(PortGroup|int $portGroup, User|int|null $user = null): bool
90+
{
91+
return $this->portGroupsForUser($user)
92+
->contains(is_int($portGroup) ? $portGroup : $portGroup->id);
93+
}
94+
7495
/**
7596
* Check if a bill can be accessed by user (non-global read/admin)
7697
* If no user is given, use the logged in user
@@ -162,6 +183,31 @@ public function deviceGroupsForUser(User|int|null $user = null): Collection
162183
return $this->deviceGroupMap[$user_id];
163184
}
164185

186+
/**
187+
* Get the ids of all port groups the user can access
188+
*
189+
* @return Collection<int>
190+
*/
191+
public function portGroupsForUser(User|int|null $user = null): Collection
192+
{
193+
$user_id = $this->getUserId($user);
194+
195+
if (! isset($this->portGroupPermissions[$user_id])) {
196+
$this->portGroupPermissions[$user_id] = DB::table('port_groups')
197+
->leftJoin('port_group_port', 'port_groups.id', '=', 'port_group_port.port_group_id')
198+
->leftJoin('ports', 'ports.port_id', '=', 'port_group_port.port_id')
199+
->where(function ($query) use ($user): void {
200+
$query->whereNull('port_group_port.port_group_id')
201+
->orWhereIntegerInRaw('port_group_port.port_id', $this->portsForUser($user))
202+
->orWhereIntegerInRaw('ports.device_id', $this->devicesForUser($user));
203+
})
204+
->distinct('port_groups.id')
205+
->pluck('port_groups.id');
206+
}
207+
208+
return $this->portGroupPermissions[$user_id];
209+
}
210+
165211
/**
166212
* Get the cached data for device permissions. Use helpers instead.
167213
*
@@ -217,6 +263,7 @@ public function invalidateCache(): void
217263
{
218264
$this->devicePermissions = [];
219265
$this->deviceGroupMap = [];
266+
$this->portGroupPermissions = [];
220267
$this->portPermissions = null;
221268
$this->billPermissions = null;
222269
}

LibreNMS/Data/Graphing/GraphParameters.php

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,7 @@ public function toRrdOptions(): array
161161
}
162162

163163
// set up fonts
164+
array_push($options, '--font', 'TITLE:' . $this->font_size . ':' . $this->font);
164165
array_push($options, '--font', 'LEGEND:' . $this->font_size . ':' . $this->font);
165166
array_push($options, '--font', 'AXIS:' . ($this->font_size - 1) . ':' . $this->font);
166167
array_push($options, '--font-render-mode', 'normal');
@@ -214,8 +215,7 @@ public function toRrdOptions(): array
214215
}
215216

216217
if ($this->visible('title')) {
217-
// remove single quotes, because we can't drop out of the string if this is sent to rrdtool stdin
218-
$options[] = '--title=' . str_replace("'", '', $this->getTitle());
218+
$options[] = '--title=' . $this->formatTitle();
219219
}
220220

221221
if ($this->right_axis !== null) {
@@ -298,4 +298,27 @@ private function defaultTitle(): string
298298

299299
return $title;
300300
}
301+
302+
private function formatTitle(): string
303+
{
304+
$title = str_replace("'", '', $this->getTitle());
305+
306+
// linear approximation
307+
$slope = 0.1332;
308+
$intercept = 15.55;
309+
$sizeAdjustment = 8 / $this->font_size; // Adjust the slope if the font size deviates from 8
310+
$adjustedSlope = $slope * $sizeAdjustment;
311+
312+
$maxChars = (int) floor($this->width * $adjustedSlope + $intercept);
313+
314+
if ($maxChars <= 0) {
315+
return '';
316+
}
317+
318+
if (strlen($title) <= $maxChars) {
319+
return $title;
320+
}
321+
322+
return substr($title, 0, max(0, $maxChars - 3)) . '...';
323+
}
301324
}

LibreNMS/Enum/IfOperStatus.php

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,11 @@
22

33
namespace LibreNMS\Enum;
44

5-
enum IfOperStatus: string
5+
use Illuminate\Contracts\Database\Eloquent\Castable;
6+
use Illuminate\Contracts\Database\Eloquent\CastsAttributes;
7+
use Illuminate\Database\Eloquent\Model;
8+
9+
enum IfOperStatus: string implements Castable
610
{
711
case Up = 'up';
812
case Down = 'down';
@@ -11,4 +15,29 @@ enum IfOperStatus: string
1115
case Dormant = 'dormant';
1216
case NotPresent = 'notPresent';
1317
case LowerLayerDown = 'lowerLayerDown';
18+
19+
public static function tryFromNullable(mixed $value): ?self
20+
{
21+
return match (true) {
22+
$value instanceof self => $value,
23+
$value === null, $value === '' => null,
24+
default => self::tryFrom((string) $value),
25+
};
26+
}
27+
28+
public static function castUsing(array $arguments): CastsAttributes
29+
{
30+
return new class implements CastsAttributes
31+
{
32+
public function get(Model $model, string $key, mixed $value, array $attributes): ?IfOperStatus
33+
{
34+
return IfOperStatus::tryFromNullable($value);
35+
}
36+
37+
public function set(Model $model, string $key, mixed $value, array $attributes): ?string
38+
{
39+
return IfOperStatus::tryFromNullable($value)?->value;
40+
}
41+
};
42+
}
1443
}

LibreNMS/Enum/WirelessSensorType.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ enum WirelessSensorType: string
1515
case Capacity = 'capacity';
1616
case Utilization = 'utilization';
1717
case Rate = 'rate';
18+
case Mcs = 'mcs';
1819
case Ccq = 'ccq';
1920
case Snr = 'snr';
2021
case Sinr = 'sinr';
@@ -61,6 +62,7 @@ public function icon(): string
6162
self::Distance => 'space-shuttle',
6263
self::Cell => 'line-chart',
6364
self::Channel => 'line-chart',
65+
self::Mcs => 'signal',
6466
};
6567
}
6668
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
<?php
2+
3+
/**
4+
* WirelessMcsDiscovery.php
5+
*
6+
* Discover wireless MCS sensors
7+
*
8+
* This program is free software: you can redistribute it and/or modify
9+
* it under the terms of the GNU General Public License as published by
10+
* the Free Software Foundation, either version 3 of the License, or
11+
* (at your option) any later version.
12+
*
13+
* This program is distributed in the hope that it will be useful,
14+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
15+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
16+
* GNU General Public License for more details.
17+
*
18+
* You should have received a copy of the GNU General Public License
19+
* along with this program. If not, see <https://www.gnu.org/licenses/>.
20+
*
21+
* @link https://www.librenms.org
22+
*/
23+
24+
namespace LibreNMS\Interfaces\Discovery\Sensors;
25+
26+
use LibreNMS\Device\WirelessSensor;
27+
28+
interface WirelessMcsDiscovery
29+
{
30+
/**
31+
* Discover wireless MCS. Type is mcs.
32+
* Returns an array of LibreNMS\Device\Sensor objects that have been discovered
33+
*
34+
* @return WirelessSensor[]
35+
*/
36+
public function discoverWirelessMcs();
37+
}

LibreNMS/Interfaces/Polling/PortSecurityPolling.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,15 +28,15 @@
2828

2929
use App\Models\PortSecurity;
3030
use Illuminate\Support\Collection;
31+
use LibreNMS\OS;
3132

3233
interface PortSecurityPolling
3334
{
3435
/**
3536
* Poll the ports for port-security data
3637
*
37-
* @param mixed $os
38-
* @param mixed $device
38+
* @param OS $os
3939
* @return Collection<PortSecurity>
4040
*/
41-
public function pollPortSecurity($os, $device): Collection;
41+
public function pollPortSecurity(OS $os): Collection;
4242
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
<?php
2+
3+
/**
4+
* WirelessMcsPolling.php
5+
*
6+
* Custom polling interface for wireless MCS (Modulation and Coding Scheme)
7+
*
8+
* This program is free software: you can redistribute it and/or modify
9+
* it under the terms of the GNU General Public License as published by
10+
* the Free Software Foundation, either version 3 of the License, or
11+
* (at your option) any later version.
12+
*
13+
* This program is distributed in the hope that it will be useful,
14+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
15+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
16+
* GNU General Public License for more details.
17+
*
18+
* You should have received a copy of the GNU General Public License
19+
* along with this program. If not, see <https://www.gnu.org/licenses/>.
20+
*
21+
* @link https://www.librenms.org
22+
*/
23+
24+
namespace LibreNMS\Interfaces\Polling\Sensors;
25+
26+
use App\Models\WirelessSensor;
27+
28+
interface WirelessMcsPolling
29+
{
30+
/**
31+
* Poll wireless MCS (Modulation and Coding Scheme)
32+
* The returned array should be sensor_id => value pairs
33+
*
34+
* @param WirelessSensor[] $sensors Array of sensors needed to be polled
35+
* @return array<int, mixed> of polled data
36+
*/
37+
public function pollWirelessMcs(array $sensors);
38+
}

LibreNMS/Modules/Core.php

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -62,20 +62,25 @@ public function shouldDiscover(OS $os, ModuleStatus $status): bool
6262

6363
public function discover(OS $os): void
6464
{
65-
$snmpdata = SnmpQuery::numeric()->get(['SNMPv2-MIB::sysObjectID.0', 'SNMPv2-MIB::sysDescr.0', 'SNMPv2-MIB::sysName.0'])
66-
->values();
65+
$snmpdata = SnmpQuery::numeric()->get([
66+
'SNMPv2-MIB::sysObjectID.0',
67+
'SNMPv2-MIB::sysDescr.0',
68+
'SNMPv2-MIB::sysName.0',
69+
])->values();
70+
71+
$snmp_engine = SnmpQuery::get('SNMP-FRAMEWORK-MIB::snmpEngineID.0')->value();
6772

6873
$device = $os->getDevice();
6974
$device->fill([
7075
'sysObjectID' => $snmpdata['.1.3.6.1.2.1.1.2.0'] ?? null,
7176
'sysName' => $snmpdata['.1.3.6.1.2.1.1.5.0'] ?? null,
7277
'sysDescr' => $snmpdata['.1.3.6.1.2.1.1.1.0'] ?? null,
78+
'snmpEngineID' => $snmp_engine,
7379
]);
7480

75-
foreach (['sysObjectID', 'sysName', 'sysDescr'] as $attribute) {
81+
foreach (['sysObjectID', 'sysName', 'sysDescr', 'snmpEngineID'] as $attribute) {
7682
if ($device->isDirty($attribute)) {
77-
$message = DeviceObserver::attributeChangedMessage($attribute, $device->$attribute, $device->getOriginal($attribute));
78-
Eventlog::log($message, $device, 'system', Severity::Notice);
83+
Log::debug(DeviceObserver::attributeChangedMessage($attribute, $device->$attribute, $device->getOriginal($attribute)));
7984
$os->getDeviceArray()[$attribute] = $device->$attribute; // update device array
8085
}
8186
}

LibreNMS/Modules/PortSecurity.php

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -68,14 +68,12 @@ public function shouldPoll(OS $os, ModuleStatus $status): bool
6868

6969
/**
7070
* Poll data for this module and update the DB
71-
*
72-
* @param \LibreNMS\OS $os
7371
*/
7472
public function poll(OS $os, DataStorageInterface $datastore): void
7573
{
7674
if ($os instanceof PortSecurityPolling) {
7775
$device = $os->getDevice();
78-
$portsec = $os->pollPortSecurity($os, $device);
76+
$portsec = $os->pollPortSecurity($os);
7977
ModuleModelObserver::observe(\App\Models\PortSecurity::class);
8078
$this->syncModels($device, 'portSecurity', $portsec);
8179
}

0 commit comments

Comments
 (0)