Location based Alert Rule (#11128)

* Location base Alert Rule

* travis fix
This commit is contained in:
SourceDoctor 2020-02-12 19:53:26 +01:00 committed by GitHub
parent dfd6f2d3b6
commit 5bfc44f812
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 100 additions and 25 deletions

View File

@ -177,6 +177,7 @@ class AlertUtil
$query = "SELECT DISTINCT a.* FROM alert_rules a
LEFT JOIN alert_device_map d ON a.id=d.rule_id AND (a.invert_map = 0 OR a.invert_map = 1 AND d.device_id = ?)
LEFT JOIN alert_group_map g ON a.id=g.rule_id AND (a.invert_map = 0 OR a.invert_map = 1 AND g.group_id IN (SELECT DISTINCT device_group_id FROM device_group_device WHERE device_id = ?))
LEFT JOIN alert_location_map l ON a.id=l.rule_id AND (a.invert_map = 0 OR a.invert_map = 1 AND l.location_id IN (SELECT DISTINCT location_id FROM devices WHERE device_id = ?))
LEFT JOIN device_group_device dg ON g.group_id=dg.device_group_id AND dg.device_id = ?
WHERE a.disabled = 0 AND (
(d.device_id IS NULL AND g.group_id IS NULL)
@ -184,7 +185,7 @@ class AlertUtil
OR (a.invert_map = 1 AND (d.device_id != ? OR d.device_id IS NULL) AND (dg.device_id != ? OR dg.device_id IS NULL))
)";
$params = [$device_id, $device_id, $device_id, $device_id, $device_id, $device_id, $device_id];
$params = [$device_id, $device_id, $device_id, $device_id, $device_id, $device_id, $device_id, $device_id];
return dbFetchRows($query, $params);
}

View File

@ -0,0 +1,33 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
class CreateAlertLocationMapTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('alert_location_map', function (Blueprint $table) {
$table->increments('id');
$table->unsignedInteger('rule_id');
$table->unsignedInteger('location_id');
$table->unique(['rule_id','location_id'], 'alert_location_map_rule_id_location_id_uindex');
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::drop('alert_location_map');
}
}

View File

@ -1023,6 +1023,7 @@ function add_edit_rule(\Illuminate\Http\Request $request)
$rule_id = $data['rule_id'];
$tmp_devices = (array)$data['devices'];
$groups = (array)$data['groups'];
$locations = (array)$data['locations'];
if (empty($tmp_devices) && !isset($rule_id)) {
return api_error(400, 'Missing the devices or global device (-1)');
}
@ -1118,6 +1119,7 @@ function add_edit_rule(\Illuminate\Http\Request $request)
dbSyncRelationship('alert_device_map', 'rule_id', $rule_id, 'device_id', $devices);
dbSyncRelationship('alert_group_map', 'rule_id', $rule_id, 'group_id', $groups);
dbSyncRelationship('alert_location_map', 'rule_id', $rule_id, 'location_id', $locations);
return api_success_noresult(200);
}

View File

@ -103,7 +103,7 @@ $extra_json = json_encode($extra);
if (is_numeric($rule_id) && $rule_id > 0) {
if (dbUpdate(
array(
'severity' => $severity,
'severity' => $severity,
'extra' => $extra_json,
'name' => $name,
'proc' => $proc,
@ -157,8 +157,11 @@ if (is_numeric($rule_id) && $rule_id > 0) {
if (is_numeric($rule_id) && $rule_id > 0) {
$devices = [];
$groups = [];
$locations = [];
foreach ((array)$vars['maps'] as $item) {
if (starts_with($item, 'g')) {
if (starts_with($item, 'l')) {
$locations[] = (int)substr($item, 1);
} elseif (starts_with($item, 'g')) {
$groups[] = (int)substr($item, 1);
} else {
$devices[] = (int)$item;
@ -167,6 +170,7 @@ if (is_numeric($rule_id) && $rule_id > 0) {
dbSyncRelationship('alert_device_map', 'rule_id', $rule_id, 'device_id', $devices);
dbSyncRelationship('alert_group_map', 'rule_id', $rule_id, 'group_id', $groups);
dbSyncRelationship('alert_location_map', 'rule_id', $rule_id, 'location_id', $locations);
//Update transport groups and transports - can't use dbSyncRelationship
$transports = [];
@ -178,7 +182,7 @@ if (is_numeric($rule_id) && $rule_id > 0) {
$transports[] = (int)$item;
}
}
// Fetch transport/group mappings already in db
$sql = "SELECT `transport_or_group_id` FROM `alert_transport_map` WHERE `target_type`='single' AND `rule_id`=?";
$db_transports = dbFetchColumn($sql, [$rule_id]);

View File

@ -33,6 +33,7 @@ if (!is_numeric($vars['alert_id'])) {
if (dbDelete('alert_rules', '`id` = ?', array($vars['alert_id']))) {
dbDelete('alert_device_map', 'rule_id=?', [$vars['alert_id']]);
dbDelete('alert_group_map', 'rule_id=?', [$vars['alert_id']]);
dbDelete('alert_location_map', 'rule_id=?', [$vars['alert_id']]);
dbDelete('alert_transport_map', 'rule_id=?', [$vars['alert_id']]);
dbDelete('alert_template_map', 'alert_rule_id=?', [$vars['alert_id']]);
echo $alert_msg_prefix . ' has been deleted.';

View File

@ -35,6 +35,10 @@ if (is_numeric($alert_id) && $alert_id > 0) {
foreach ($groups as $group) {
$maps[] = ['id' => 'g' . $group['group_id'], 'text' => $group['name']];
}
$locations = dbFetchRows('SELECT `location_id`, `location` FROM `alert_location_map` LEFT JOIN `locations` ON `locations`.`id`=`alert_location_map`.`location_id` WHERE `rule_id`=?', [$alert_id]);
foreach ($locations as $location) {
$maps[] = ['id' => 'l' . $location['location_id'], 'text' => $location['location']];
}
$transports = [];
$members = dbFetchRows('SELECT `transport_or_group_id`, `transport_name`, `transport_type` FROM `alert_transport_map` LEFT JOIN `alert_transports` ON `transport_or_group_id` = `transport_id` WHERE `target_type`="single" AND `rule_id`=?', [$alert_id]);

View File

@ -307,7 +307,7 @@ if (Auth::user()->hasGlobalAdmin()) {
$maps.empty();
$maps.val(null).trigger('change');
setRuleDevice();// pre-populate device in the maps if this is a per-device rule
var $transports = $("#transports");
$transports.empty();
$transports.val(null).trigger('change');
@ -408,13 +408,13 @@ if (Auth::user()->hasGlobalAdmin()) {
$("#maps").select2({
width: '100%',
placeholder: "Devices or Groups",
placeholder: "Devices, Groups or Locations",
ajax: {
url: 'ajax_list.php',
delay: 250,
data: function (params) {
return {
type: 'devices_groups',
type: 'devices_groups_locations',
search: params.term
};
}

View File

@ -133,7 +133,10 @@ if (isset($device['device_id']) && $device['device_id'] > 0) {
$device_group_rules = "SELECT ar3.* FROM alert_rules AS ar3 WHERE ar3.id IN (SELECT agm3.rule_id FROM alert_group_map AS agm3 LEFT JOIN device_group_device AS dgd3 ON agm3.group_id=dgd3.device_group_id WHERE dgd3.device_id=?)";
$param[] = $device['device_id'];
$full_query = '('. $global_rules .') UNION DISTINCT ('. $device_rules .') UNION DISTINCT ('. $device_group_rules .')';
$device_location_rules = "SELECT ar4.* FROM alert_rules AS ar4 WHERE ar4.id IN (SELECT alm4.rule_id FROM alert_location_map AS alm4 LEFT JOIN devices AS d4 ON alm4.location_id=d4.location_id WHERE d4.device_id=?)";
$param[] = $device['device_id'];
$full_query = '('. $global_rules .') UNION DISTINCT ('. $device_rules .') UNION DISTINCT ('. $device_group_rules .') UNION DISTINCT ('. $device_location_rules .')';
} else {
// no device selected
$full_query = 'SELECT alert_rules.* FROM alert_rules';
@ -220,22 +223,31 @@ foreach ($rule_list as $rule) {
$device_count = dbFetchCell('SELECT COUNT(*) FROM alert_device_map WHERE rule_id=?', [$rule['id']]);
$group_count = dbFetchCell('SELECT COUNT(*) FROM alert_group_map WHERE rule_id=?', [$rule['id']]);
$location_count = dbFetchCell('SELECT COUNT(*) FROM alert_location_map WHERE rule_id=?', [$rule['id']]);
$popover_msg_parts = [];
$icon_indicator = 'fa fa-globe fa-fw text-success';
if ($device_count) {
$popover_msg = 'Device restricted rule #' . $rule['id'];
$popover_msg_parts[] = 'Device';
$icon_indicator = 'fa fa-server fa-fw text-primary';
}
if ($group_count) {
$popover_msg = 'Group restricted rule #' . $rule['id'];
$popover_msg_parts[] = 'Group';
$icon_indicator = 'fa fa-th fa-fw text-primary';
}
if ($device_count && $group_count) {
$popover_msg = 'Device and Group restricted rule #' . $rule['id'];
$icon_indicator = 'fa fa-connectdevelop fa-fw text-primary';
if ($location_count) {
$popover_msg_parts[] = 'Location';
$icon_indicator = 'fa fa-th fa-fw text-primary';
}
if (!$device_count && !$group_count) {
$popover_msg = 'Global alert rule #' . $rule['id'];
$icon_indicator = 'fa fa-globe fa-fw text-success';
if (count($popover_msg_parts)) {
$popover_msg = implode(', ', $popover_msg_parts);
} else {
$popover_msg = 'Global';
}
$popover_msg .= ' alert Rule #' . $rule['id'];
echo "<tr class='".$extra."' id='rule_id_".$rule['id']."'>";
@ -261,38 +273,48 @@ foreach ($rule_list as $rule) {
$except_device_or_group = '<strong><em>EXCEPT</em></strong> ';
}
$devices_and_groups_popover='right';
$popover_position = 'right';
$groups=null;
$locations = null;
if ($location_count) {
$location_query = 'SELECT locations.location, locations.id FROM alert_location_map, locations WHERE alert_location_map.rule_id=? and alert_location_map.location_id = locations.id ORDER BY location';
$location_maps = dbFetchRows($location_query, [$rule['id']]);
foreach ($location_maps as $location_map) {
$locations .= "$except_device_or_group<a href=\"/devices\/location=".$location_map['id']."\" data-container='body' data-toggle='popover' data-placement='$popover_position' data-content='View Devices for Location' target=\"_blank\">".$location_map['location']."</a><br>";
}
}
$groups = null;
if ($group_count) {
$group_query = 'SELECT device_groups.name, device_groups.id FROM alert_group_map, device_groups WHERE alert_group_map.rule_id=? and alert_group_map.group_id = device_groups.id ORDER BY name';
$group_maps = dbFetchRows($group_query, [$rule['id']]);
foreach ($group_maps as $group_map) {
$groups .= "$except_device_or_group<a href=\"/device-groups/" . $group_map['id'] . "/edit\" data-container='body' data-toggle='popover' data-placement='$devices_and_groups_popover' data-content='Edit device group " . $group_map['name'] . "' title='$groups_msg' target=\"_blank\">" . $group_map['name'] . "</a><br>";
$groups .= "$except_device_or_group<a href=\"/device-groups/" . $group_map['id'] . "/edit\" data-container='body' data-toggle='popover' data-placement='$popover_position' data-content='" . $group_map['name'] . "' title='$groups_msg' target=\"_blank\">" . $group_map['name'] . "</a><br>";
}
}
$devices=null;
$devices = null;
if ($device_count) {
$device_query = 'SELECT devices.device_id,devices.hostname FROM alert_device_map, devices WHERE alert_device_map.rule_id=? and alert_device_map.device_id = devices.device_id ORDER BY hostname';
$device_maps = dbFetchRows($device_query, [$rule['id']]);
foreach ($device_maps as $device_map) {
$devices .= "$except_device_or_group<a href=\"/device/device=" . $device_map['device_id'] . "/tab=edit/\" data-container='body' data-toggle='popover' data-placement='$devices_and_groups_popover' data-content='Edit device " . $device_map['hostname'] . "' title='$devices_msg' target=\"_blank\">" . $device_map['hostname'] . "</a><br>";
$devices .= "$except_device_or_group<a href=\"/device/device=" . $device_map['device_id'] . "/tab=edit/\" data-container='body' data-toggle='popover' data-placement='$popover_position' data-content='" . $device_map['hostname'] . "' title='$devices_msg' target=\"_blank\">" . $device_map['hostname'] . "</a><br>";
}
}
echo "<td colspan='2'>";
if ($locations) {
echo $locations;
}
if ($groups) {
// Individual Groups first
echo $groups;
}
if ($devices) {
// Individual Devices last
echo $devices;
}
if (!$devices && !$groups) {
if (!$devices && !$groups && !$locations) {
// All Devices
echo "<a href=\"/devices\" data-container='body' data-toggle='popover' data-placement='$devices_and_groups_popover' data-content='View All Devices' target=\"_blank\">All Devices</a><br>";
echo "<a href=\"/devices\" data-container='body' data-toggle='popover' data-placement='$popover_position' data-content='View All Devices' target=\"_blank\">All Devices</a><br>";
}
echo "</td>";

View File

@ -51,6 +51,14 @@ alert_group_map:
Indexes:
PRIMARY: { Name: PRIMARY, Columns: [id], Unique: true, Type: BTREE }
alert_group_map_rule_id_group_id_uindex: { Name: alert_group_map_rule_id_group_id_uindex, Columns: [rule_id, group_id], Unique: true, Type: BTREE }
alert_location_map:
Columns:
- { Field: id, Type: 'int(10) unsigned', 'Null': false, Extra: auto_increment }
- { Field: rule_id, Type: 'int(10) unsigned', 'Null': false, Extra: '' }
- { Field: location_id, Type: 'int(10) unsigned', 'Null': false, Extra: '' }
Indexes:
PRIMARY: { Name: PRIMARY, Columns: [id], Unique: true, Type: BTREE }
alert_location_map_rule_id_location_id_uindex: { Name: alert_location_map_rule_id_location_id_uindex, Columns: [rule_id, location_id], Unique: true, Type: BTREE }
alert_log:
Columns:
- { Field: id, Type: 'int(10) unsigned', 'Null': false, Extra: auto_increment }