Issues (2963)

includes/html/forms/alert-rules.inc.php (1 issue)

1
<?php
2
/**
3
 * alert-rules.inc.php
4
 *
5
 * LibreNMS alert-rules.inc.php
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 <https://www.gnu.org/licenses/>.
19
 *
20
 * @link       https://www.librenms.org
21
 *
22
 * @copyright  2018 Neil Lathwood
23
 * @author     Neil Lathwood <[email protected]>
24
 */
25
26
use Illuminate\Support\Str;
27
use LibreNMS\Alerting\QueryBuilderParser;
28
29
header('Content-type: application/json');
30
31
if (! Auth::user()->hasGlobalAdmin()) {
32
    exit(json_encode([
33
        'status' => 'error',
34
        'message' => 'ERROR: You need to be admin',
35
    ]));
36
}
37
38
$status = 'ok';
39
$message = '';
40
41
$builder_json = $vars['builder_json'];
42
$override_query = $vars['override_query'];
43
44
$options = [
45
    'override_query' => $override_query,
46
];
47
48
if ($override_query === 'on') {
49
    $query = $vars['adv_query'];
50
} else {
51
    $query = QueryBuilderParser::fromJson($builder_json)->toSql();
52
}
53
$rule_id = $_POST['rule_id'];
54
$count = $_POST['count'];
55
$delay = $_POST['delay'];
56
$interval = $_POST['interval'];
57
$mute = isset($_POST['mute']) ? $_POST['mute'] : null;
58
$invert = isset($_POST['invert']) ? $_POST['invert'] : null;
59
$name = $_POST['name'];
60
$proc = $_POST['proc'];
61
$recovery = ($vars['recovery']);
62
$invert_map = isset($_POST['invert_map']) ? $_POST['invert_map'] : null;
63
$severity = $_POST['severity'];
64
65
if (! is_numeric($count)) {
66
    $count = '-1';
67
}
68
69
$delay_sec = convert_delay($delay);
70
$interval_sec = convert_delay($interval);
71
72
if ($mute == 'on') {
73
    $mute = true;
74
} else {
75
    $mute = false;
76
}
77
78
if ($invert == 'on') {
79
    $invert = true;
80
} else {
81
    $invert = false;
82
}
83
84
$recovery = empty($recovery) ? $recovery = false : true;
85
86
if ($invert_map == 'on') {
87
    $invert_map = true;
88
} else {
89
    $invert_map = false;
90
}
91
92
$extra = [
93
    'mute'     => $mute,
94
    'count'    => $count,
95
    'delay'    => $delay_sec,
96
    'invert'   => $invert,
97
    'interval' => $interval_sec,
98
    'recovery' => $recovery,
99
    'options'  => $options,
100
];
101
102
$extra_json = json_encode($extra);
103
104
if (! is_array($vars['maps']) && $invert_map) {
105
    exit(json_encode([
106
        'status' => 'error',
107
        'message' => 'Invert map is on but no selection in devices, groups and locations match list<br />',
108
    ]));
109
}
110
111
if (is_numeric($rule_id) && $rule_id > 0) {
112
    if (dbUpdate(
113
        [
114
            'severity' => $severity,
115
            'extra' => $extra_json,
116
            'name' => $name,
117
            'proc' => $proc,
118
            'query' => $query,
119
            'builder' => $builder_json,
120
            'invert_map' => $invert_map,
121
        ],
122
        'alert_rules',
123
        'id=?',
124
        [$rule_id]
125
    ) >= 0) {
126
        $message = "Edited Rule: <i>$name</i>";
127
    } else {
128
        $message = "Failed to edit Rule <i>$name</i>";
129
        $status = 'error';
130
    }
131
} else {
132
    if (empty($name)) {
133
        $status = 'error';
134
        $message = 'No rule name provided';
135
    } elseif (empty($builder_json) || empty($query)) {
136
        $status = 'error';
137
        $message = 'No rules provided';
138
    } else {
139
        $rule_id = dbInsert([
140
            'rule' => '',
141
            'severity' => $severity,
142
            'extra' => $extra_json,
143
            'disabled' => 0,
144
            'name' => $name,
145
            'proc' => $proc,
146
            'query' => $query,
147
            'builder' => $builder_json,
148
            'invert_map' => $invert_map,
149
        ], 'alert_rules');
150
151
        if ($rule_id) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $rule_id of type integer|null is loosely compared to true; this is ambiguous if the integer can be 0. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For integer values, zero is a special case, in particular the following results might be unexpected:

0   == false // true
0   == null  // true
123 == false // false
123 == null  // false

// It is often better to use strict comparison
0 === false // false
0 === null  // false
Loading history...
152
            $message = "Added Rule: <i>$name</i>";
153
        } else {
154
            if (dbFetchCell('SELECT 1 FROM alert_rules WHERE name=?', [$name])) {
155
                $message = "Rule named <i>$name</i> already exists";
156
            } else {
157
                $message = "Failed to add Rule: <i>$name</i>";
158
            }
159
            $status = 'error';
160
        }
161
    }
162
}//end if
163
164
// update maps
165
if (is_numeric($rule_id) && $rule_id > 0) {
166
    $devices = [];
167
    $groups = [];
168
    $locations = [];
169
    foreach ((array) $vars['maps'] as $item) {
170
        if (Str::startsWith($item, 'l')) {
171
            $locations[] = (int) substr($item, 1);
172
        } elseif (Str::startsWith($item, 'g')) {
173
            $groups[] = (int) substr($item, 1);
174
        } else {
175
            $devices[] = (int) $item;
176
        }
177
    }
178
179
    dbSyncRelationship('alert_device_map', 'rule_id', $rule_id, 'device_id', $devices);
180
    dbSyncRelationship('alert_group_map', 'rule_id', $rule_id, 'group_id', $groups);
181
    dbSyncRelationship('alert_location_map', 'rule_id', $rule_id, 'location_id', $locations);
182
183
    //Update transport groups and transports - can't use dbSyncRelationship
184
    $transports = [];
185
    $groups = [];
186
    foreach ((array) $vars['transports'] as $item) {
187
        if (Str::startsWith($item, 'g')) {
188
            $groups[] = (int) substr($item, 1);
189
        } else {
190
            $transports[] = (int) $item;
191
        }
192
    }
193
194
    // Fetch transport/group mappings already in db
195
    $sql = "SELECT `transport_or_group_id` FROM `alert_transport_map` WHERE `target_type`='single' AND `rule_id`=?";
196
    $db_transports = dbFetchColumn($sql, [$rule_id]);
197
    $sql = "SELECT `transport_or_group_id` FROM `alert_transport_map` WHERE `target_type`='group' AND `rule_id`=?";
198
    $db_groups = dbFetchColumn($sql, [$rule_id]);
199
200
    // Compare arrays to get add and removed transports/groups
201
    $t_add = array_diff($transports, $db_transports);
202
    $t_del = array_diff($db_transports, $transports);
203
    $g_add = array_diff($groups, $db_groups);
204
    $g_del = array_diff($db_groups, $groups);
205
206
    // Insert any new mappings
207
    $insert = [];
208
    foreach ($t_add as $transport_id) {
209
        $insert[] = [
210
            'transport_or_group_id' => $transport_id,
211
            'target_type' => 'single',
212
            'rule_id' => $rule_id,
213
        ];
214
    }
215
    foreach ($g_add as $group_id) {
216
        $insert[] = [
217
            'transport_or_group_id' => $group_id,
218
            'target_type' => 'group',
219
            'rule_id' => $rule_id,
220
        ];
221
    }
222
    if (! empty($insert)) {
223
        $res = dbBulkInsert($insert, 'alert_transport_map');
224
    }
225
    // Remove old mappings
226
    if (! empty($t_del)) {
227
        $db_t_values = array_merge([$rule_id], $t_del);
228
        dbDelete('alert_transport_map', 'target_type="single" AND rule_id=? AND transport_or_group_id IN ' . dbGenPlaceholders(count($t_del)), $db_t_values);
229
    }
230
    if (! empty($g_del)) {
231
        $db_g_values = array_merge([$rule_id], $g_del);
232
        dbDelete('alert_transport_map', 'target_type="group" AND rule_id=? AND transport_or_group_id IN ' . dbGenPlaceholders(count($g_del)), $db_g_values);
233
    }
234
}
235
236
exit(json_encode([
237
    'status'       => $status,
238
    'message'      => $message,
239
]));
240