Fix alerting find owner contacts on old SQL server versions (#15355)

* Fix alerting find owner contacts on old SQL server versions
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.

* Fix style
This commit is contained in:
Tony Murray 2023-09-28 09:49:29 -05:00 committed by GitHub
parent ca5b75a200
commit 6f329a7595
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 26 additions and 23 deletions

View File

@ -28,8 +28,8 @@ namespace LibreNMS\Alert;
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;
@ -168,28 +168,16 @@ class AlertUtil
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();
}

View File

@ -228,6 +228,11 @@ class User extends Authenticatable
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
@ -236,6 +241,11 @@ class User extends Authenticatable
});
}
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');
@ -247,10 +257,15 @@ class User extends Authenticatable
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');