Passed
Push — master ( 2ee843...cfc51d )
by Tony
09:10
created

DeviceGroup::updateDevices()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 3
dl 0
loc 5
rs 10
c 0
b 0
f 0
cc 2
nc 2
nop 0
1
<?php
2
/**
3
 * DeviceGroup.php
4
 *
5
 * Dynamic groups of devices
6
 *
7
 * This program is free software: you can redistribute it and/or modify
8
 * it under the terms of the GNU General Public License as published by
9
 * the Free Software Foundation, either version 3 of the License, or
10
 * (at your option) any later version.
11
 *
12
 * This program is distributed in the hope that it will be useful,
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
15
 * GNU General Public License for more details.
16
 *
17
 * You should have received a copy of the GNU General Public License
18
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
19
 *
20
 * @package    LibreNMS
21
 * @link       http://librenms.org
22
 * @copyright  2016 Tony Murray
23
 * @author     Tony Murray <[email protected]>
24
 */
25
26
namespace App\Models;
27
28
use LibreNMS\Alerting\QueryBuilderFluentParser;
29
use Log;
30
use Permissions;
31
32
class DeviceGroup extends BaseModel
33
{
34
    public $timestamps = false;
35
    protected $fillable = ['name', 'desc', 'type'];
36
    protected $casts = ['rules' => 'array'];
37
38
    public static function boot()
39
    {
40
        parent::boot();
41
42
        static::deleting(function (DeviceGroup $deviceGroup) {
43
            $deviceGroup->devices()->detach();
44
        });
45
46
        static::saving(function (DeviceGroup $deviceGroup) {
47
            if ($deviceGroup->isDirty('rules')) {
48
                $deviceGroup->updateDevices();
49
            }
50
        });
51
    }
52
53
    // ---- Helper Functions ----
54
55
    /**
56
     * Update devices included in this group (dynamic only)
57
     */
58
    public function updateDevices()
59
    {
60
        if ($this->type == 'dynamic') {
61
            $this->devices()->sync(QueryBuilderFluentParser::fromJSON($this->rules)->toQuery()
62
                ->distinct()->pluck('devices.device_id'));
63
        }
64
    }
65
66
    /**
67
     * Update the device groups for the given device or device_id
68
     *
69
     * @param Device|int $device
70
     * @return array
71
     */
72
    public static function updateGroupsFor($device)
73
    {
74
        $device = ($device instanceof Device ? $device : Device::find($device));
75
        if (!$device instanceof Device) {
76
            // could not load device
77
            return [
78
                "attached" => [],
79
                "detached" => [],
80
                "updated" => [],
81
            ];
82
        }
83
84
        $device_group_ids = static::query()
85
            ->with(['devices' => function ($query) {
86
                $query->select('devices.device_id');
87
            }])
88
            ->get()
89
            ->filter(function ($device_group) use ($device) {
90
                /** @var DeviceGroup $device_group */
91
                if ($device_group->type == 'dynamic') {
92
                    try {
93
                        return $device_group->getParser()
94
                            ->toQuery()
95
                            ->where('devices.device_id', $device->device_id)
96
                            ->exists();
97
                    } catch (\Illuminate\Database\QueryException $e) {
98
                        Log::error("Device Group '$device_group->name' generates invalid query: " . $e->getMessage());
99
                        return false;
100
                    }
101
                }
102
103
                // for static, if this device is include, keep it.
104
                return $device_group->devices
105
                    ->where('device_id', $device->device_id)
106
                    ->isNotEmpty();
107
            })->pluck('id');
108
109
        return $device->groups()->sync($device_group_ids);
110
    }
111
112
    /**
113
     * Get a query builder parser instance from this device group
114
     *
115
     * @return QueryBuilderFluentParser
116
     */
117
    public function getParser()
118
    {
119
        return !empty($this->rules) ?
120
            QueryBuilderFluentParser::fromJson($this->rules) :
121
            QueryBuilderFluentParser::fromOld($this->pattern);
122
    }
123
124
    // ---- Query Scopes ----
125
126
    public function scopeHasAccess($query, User $user)
127
    {
128
        if ($user->hasGlobalRead()) {
129
            return $query;
130
        }
131
132
        return $query->whereIn('id', Permissions::deviceGroupsForUser($user));
0 ignored issues
show
Bug introduced by
The method deviceGroupsForUser() does not exist on App\Facades\Permissions. Since you implemented __callStatic, consider adding a @method annotation. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

132
        return $query->whereIn('id', Permissions::/** @scrutinizer ignore-call */ deviceGroupsForUser($user));
Loading history...
133
    }
134
135
    // ---- Define Relationships ----
136
137
    public function devices()
138
    {
139
        return $this->belongsToMany('App\Models\Device', 'device_group_device', 'device_group_id', 'device_id');
140
    }
141
142
    public function services()
143
    {
144
        return $this->belongsToMany('App\Models\Service', 'device_group_device', 'device_group_id', 'device_id');
145
    }
146
}
147