Skip to content

Commit

Permalink
Fix alerting find owner contacts on old SQL server versions
Browse files Browse the repository at this point in the history
Older SQL server versions had a bug where they didn't accept parenthesis around the first query of a union statement.
It was difficult to remove these parenthesis, so use whereHas instead.
  • Loading branch information
murrant committed Sep 27, 2023
1 parent 723c51b commit def01a3
Show file tree
Hide file tree
Showing 2 changed files with 26 additions and 23 deletions.
32 changes: 10 additions & 22 deletions LibreNMS/Alert/AlertUtil.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@
use App\Models\Device;
use App\Models\User;
use DeviceCache;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Arr;
use Illuminate\Support\Facades\DB;
use LibreNMS\Config;
use PHPMailer\PHPMailer\PHPMailer;

Expand Down Expand Up @@ -168,28 +168,16 @@ public static function findContactsSysContact(array $results): array

public static function findContactsOwners(array $results): array
{
return User::whereNot('email', '')->whereIn('user_id', function (\Illuminate\Database\Query\Builder $query) use ($results) {
$tables = [
'bill_id' => 'bill_perms',
'port_id' => 'ports_perms',
'device_id' => 'devices_perms',
];

$first = true;
foreach ($tables as $column => $table) {
$ids = array_filter(Arr::pluck($results, $column)); // find IDs for this type

if (! empty($ids)) {
if ($first) {
$query->select('user_id')->from($table)->whereIn($column, $ids);
$first = false;
} else {
$query->union(DB::table($table)->select('user_id')->whereIn($column, $ids));
}
}
return User::whereNot('email', '')->where(function (Builder $query) use ($results) {
if ($device_ids = array_filter(Arr::pluck($results, 'device_id'))) {
$query->orWhereHas('devicesOwned', fn($q) => $q->whereIn('devices_perms.device_id', $device_ids));
}
if ($port_ids = array_filter(Arr::pluck($results, 'port_id'))) {
$query->orWhereHas('portsOwned', fn($q) => $q->whereIn('ports_perms.port_id', $port_ids));
}
if ($bill_ids = array_filter(Arr::pluck($results, 'bill_id'))) {
$query->orWhereHas('bills', fn($q) => $q->whereIn('bill_perms.bill_id', $bill_ids));
}

return $query;
})->pluck('realname', 'email')->all();
}

Expand Down
17 changes: 16 additions & 1 deletion app/Models/User.php
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,11 @@ public function apiTokens(): HasMany
return $this->hasMany(\App\Models\ApiToken::class, 'user_id', 'user_id');
}

public function bills(): BelongsToMany
{
return $this->belongsToMany(\App\Models\Bill::class, 'bill_perms', 'user_id', 'bill_id');
}

public function devices()
{
// pseudo relation
Expand All @@ -236,6 +241,11 @@ public function devices()
});
}

public function devicesOwned(): BelongsToMany
{
return $this->belongsToMany(\App\Models\Device::class, 'devices_perms', 'user_id', 'device_id');
}

public function deviceGroups(): BelongsToMany
{
return $this->belongsToMany(\App\Models\DeviceGroup::class, 'devices_group_perms', 'user_id', 'device_group_id');
Expand All @@ -247,10 +257,15 @@ public function ports()
return Port::query();
} else {
//FIXME we should return all ports for a device if the user has been given access to the whole device.
return $this->belongsToMany(\App\Models\Port::class, 'ports_perms', 'user_id', 'port_id');
return $this->portsOwned();
}
}

public function portsOwned(): BelongsToMany
{
return $this->belongsToMany(\App\Models\Port::class, 'ports_perms', 'user_id', 'port_id');
}

public function dashboards(): HasMany
{
return $this->hasMany(\App\Models\Dashboard::class, 'user_id');
Expand Down

0 comments on commit def01a3

Please sign in to comment.