diff --git a/app/Helpers/response_helper.php b/app/Helpers/response_helper.php
index d738ce091..47de56870 100644
--- a/app/Helpers/response_helper.php
+++ b/app/Helpers/response_helper.php
@@ -431,7 +431,10 @@ function response_create($instance = null)
$received_data = $response->meta->received_data;
$response->meta->received_data = array();
}
-
+ if ($response->meta->collection === 'devices' and $response->meta->action === 'update' and !empty($response->meta->received_data->attributes->tags)) {
+ $received_data = $response->meta->received_data;
+ $response->meta->received_data = array();
+ }
if ($response->meta->collection === 'search' and $response->meta->action === 'create') {
$received_data = $response->meta->received_data;
$response->meta->received_data = array();
@@ -515,6 +518,9 @@ function response_create($instance = null)
if ($response->meta->collection === 'credentials' and $response->meta->action === 'create') {
$response->meta->received_data = $received_data;
}
+ if ($response->meta->collection === 'devices' and $response->meta->action === 'update' and !empty($received_data->attributes->tags)) {
+ $response->meta->received_data = $received_data;
+ }
// TODO - Why does enterprise return this as a string?
$response->meta->limit = intval($response->meta->limit);
if (!empty($response->errors)) {
diff --git a/app/Models/DevicesModel.php b/app/Models/DevicesModel.php
index 97c540559..3d873c7d9 100644
--- a/app/Models/DevicesModel.php
+++ b/app/Models/DevicesModel.php
@@ -46,6 +46,11 @@ public function collection(object $resp): array
$joined_tables = array();
foreach ($resp->meta->filter as $filter) {
if (in_array($filter->operator, ['!=', '>=', '<=', '=', '>', '<'])) {
+ if ($filter->name === 'devices.tags' and $filter->operator === '=') {
+ $filter->function = 'like';
+ $filter->operator = '';
+ $filter->value = '"' . $filter->value . '"';
+ }
$this->builder->{$filter->function}($filter->name . ' ' . $filter->operator, $filter->value);
} else {
$this->builder->{$filter->function}($filter->name, $filter->value);
@@ -71,9 +76,10 @@ public function collection(object $resp): array
return array();
}
$result = $query->getResult();
+ $count = count($result);
if (isset($result[0]->type) and isset($result[0]->last_seen_by) and $instance->config->product !== 'community') {
- for ($i=0; $i < count($result); $i++) {
+ for ($i=0; $i < $count; $i++) {
# BAD
if ($result[$i]->last_seen_by === 'nmap' and ($result[$i]->type === 'unclassified' or $result[$i]->type === 'unknown')) {
$result[$i]->audit_class = 'fa fa-times text-danger';
@@ -113,6 +119,18 @@ public function collection(object $resp): array
}
}
}
+
+ if (isset($result[0]->tags)) {
+ for ($i=0; $i < $count; $i++) {
+ if (!empty($result[$i]->tags)) {
+ $result[$i]->tags = @json_decode($result[$i]->tags);
+ }
+ if (empty($result[$i]->tags)) {
+ $result[$i]->tags = array();
+ }
+ }
+ }
+
return format_data($result, $resp->meta->collection);
}
@@ -591,6 +609,14 @@ public function read(int $id = 0): array
return array();
}
$device = $query->getResult();
+ if (isset($device[0]->tags)) {
+ if (!empty($device[0]->tags)) {
+ $device[0]->tags = @json_decode($device[0]->tags);
+ }
+ if (empty($device[0]->tags)) {
+ $device[0]->tags = array();
+ }
+ }
if (!empty($device[0]->instance_tags)) {
$device[0]->instance_tags = json_decode($device[0]->instance_tags);
}
diff --git a/app/Models/db_upgrades/db_5.1.0.php b/app/Models/db_upgrades/db_5.1.0.php
index a29e0c9aa..0e866518f 100644
--- a/app/Models/db_upgrades/db_5.1.0.php
+++ b/app/Models/db_upgrades/db_5.1.0.php
@@ -8,6 +8,18 @@
log_message('info', (string)$db->getLastQuery());
}
+if (!$db->fieldExists('tags', 'devices')) {
+ $sql = "ALTER TABLE `devices` ADD `tags` text NOT NULL DEFAULT '[]' AFTER kernel_version";
+ $query = $db->query($sql);
+ $output .= str_replace("\n", " ", (string)$db->getLastQuery()) . "\n\n";
+ log_message('info', (string)$db->getLastQuery());
+}
+
+$sql = "UPDATE `configuration` SET `value` = CONCAT(`value`, ',devices.tags') WHERE `name` = 'devices_default_retrieve_columns' AND `value` NOT LIKE '%devices.tags%'";
+$db->query($sql);
+$output .= str_replace("\n", " ", (string)$db->getLastQuery()) . "\n\n";
+log_message('info', (string)$db->getLastQuery());
+
$sql = "DELETE FROM `dashboards` WHERE `name` = 'Summary Dashboard' and `description` = 'Summary Information'";
$db->query($sql);
$output .= str_replace("\n", " ", (string)$db->getLastQuery()) . "\n\n";
diff --git a/app/Views/devicesCollection.php b/app/Views/devicesCollection.php
index ecdbecaf7..1090caeeb 100644
--- a/app/Views/devicesCollection.php
+++ b/app/Views/devicesCollection.php
@@ -159,6 +159,12 @@
}
} else if ($key === 'ip' and !empty($item->attributes->ip_padded)) {
echo "
= device_panel('Windows', $user->toolbar_style, $resource->id, '', $update); ?>
@@ -2397,5 +2419,12 @@
$("#oa_panel_buttons").append('
');
+ $("#device_panel_tags").append('
');
+
+ $(document).on('click', '#add_tags', function (e) {
+ $("#tags_control").css('display', 'block');
+ });
+
+
}
diff --git a/app/Views/shared/read_functions.php b/app/Views/shared/read_functions.php
index 76a4fbb1e..17d75bdd7 100644
--- a/app/Views/shared/read_functions.php
+++ b/app/Views/shared/read_functions.php
@@ -310,6 +310,15 @@ function device_panel(string $name = '', string $toolbar = '', int $device_id =
$panel_add_button = "
" . __("Add") . "";
}
}
+ if ($name === 'tags') {
+ if ($toolbar === 'icontext') {
+ $panel_add_button = "
" . __("Add") . "";
+ } else if ($toolbar === 'icon') {
+ $panel_add_button = "
";
+ } else {
+ $panel_add_button = "
" . __("Add") . "";
+ }
+ }
}
if (!in_array(strtolower($export_name), ['audit_log', 'bios', 'certificate', 'change_log', 'discovery_log', 'disk', 'dns', 'edit_log', 'file', 'ip', 'log', 'memory', 'module', 'monitor', 'motherboard', 'netstat', 'network', 'nmap', 'optical', 'pagefile', 'partition', 'policy', 'print_queue', 'processor', 'radio', 'route', 'san', 'scsi', 'server', 'server_item', 'service', 'share', 'software', 'software_key', 'sound', 'task', 'usb', 'user', 'user_group', 'variable', 'video', 'vm', 'windows']) or empty($device_id)) {
diff --git a/other/open-audit.sql b/other/open-audit.sql
index e47476e33..e014634c6 100644
--- a/other/open-audit.sql
+++ b/other/open-audit.sql
@@ -891,7 +891,7 @@ INSERT INTO `configuration` VALUES (NULL,'delete_noncurrent_windows','n','bool',
INSERT INTO `configuration` VALUES (NULL,'device_auto_delete','n','bool','y','system','2000-01-01 00:00:00','Should we delete the device data completely from the database when the device status is set to Deleted.');
INSERT INTO `configuration` VALUES (NULL,'devices_default_display_columns','devices.id,devices.icon,devices.type,devices.name,devices.ip,devices.dns_fqdn,devices.identification,devices.description,devices.manufacturer,devices.os_family,devices.status','text','y','system','2000-01-01 00:00:00','When requesting a list of devices, display these columns.');
INSERT INTO `configuration` VALUES (NULL,'devices_default_group_columns','devices.id,devices.icon,devices.type,devices.name,devices.ip,devices.dns_fqdn,devices.identification,devices.description,devices.manufacturer,devices.os_family,devices.status,devices.org_id','text','y','system','2000-01-01 00:00:00','When requesting a group of devices, retrieve and display these columns.');
-INSERT INTO `configuration` VALUES (NULL,'devices_default_retrieve_columns','devices.id,devices.icon,devices.type,devices.name,devices.ip,devices.uuid,devices.hostname,devices.dns_hostname,devices.domain,devices.dns_domain,devices.dbus_identifier,devices.fqdn,devices.dns_fqdn,devices.description,devices.os_group,devices.os_family,devices.os_name,devices.os_version,devices.manufacturer,devices.model,devices.serial,devices.form_factor,devices.status,devices.environment,devices.class,devices.function,devices.org_id,devices.location_id,devices.snmp_oid,devices.sysDescr,devices.sysObjectID,devices.sysUpTime,devices.sysContact,devices.sysName,devices.sysLocation,devices.first_seen,devices.last_seen,devices.last_seen_by,devices.identification','text','y','system','2000-01-01 00:00:00','When requesting a list of devices, provide these columns.');
+INSERT INTO `configuration` VALUES (NULL,'devices_default_retrieve_columns','devices.id,devices.icon,devices.type,devices.name,devices.ip,devices.uuid,devices.hostname,devices.dns_hostname,devices.domain,devices.dns_domain,devices.dbus_identifier,devices.fqdn,devices.dns_fqdn,devices.description,devices.os_group,devices.os_family,devices.os_name,devices.os_version,devices.manufacturer,devices.model,devices.serial,devices.form_factor,devices.status,devices.environment,devices.class,devices.function,devices.org_id,devices.location_id,devices.snmp_oid,devices.sysDescr,devices.sysObjectID,devices.sysUpTime,devices.sysContact,devices.sysName,devices.sysLocation,devices.first_seen,devices.last_seen,devices.last_seen_by,devices.identification,devices.tags','text','y','system','2000-01-01 00:00:00','When requesting a list of devices, provide these columns.');
INSERT INTO `configuration` VALUES (NULL,'discovery_default_scan_option','1','number','y','system','2000-01-01 00:00:00','The default discovery options for Nmap.');
INSERT INTO `configuration` VALUES (NULL,'discovery_ip_exclude','','text','y','system','2000-01-01 00:00:00','Populate this list with ip addresses to be excluded from discovery. IPs should be separated by a space.');
INSERT INTO `configuration` VALUES (NULL,'discovery_limit','20','number','y','system','2000-01-01 00:00:00','The maximum number of concurrent discoveries we should run.');
@@ -1133,6 +1133,7 @@ CREATE TABLE `devices` (
`os_version` varchar(200) NOT NULL DEFAULT '',
`os_cpe` varchar(200) NOT NULL DEFAULT '',
`kernel_version` varchar(200) NOT NULL DEFAULT '',
+ `tags` text NOT NULL DEFAULT '[]',
`attached_device_id` int(10) unsigned DEFAULT NULL,
`manufacturer` varchar(100) NOT NULL DEFAULT '',
`manufacturer_code` varchar(200) NOT NULL DEFAULT '',
diff --git a/public/icons/tags.svg b/public/icons/tags.svg
new file mode 100755
index 000000000..fc4febde8
--- /dev/null
+++ b/public/icons/tags.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/public/js/open-audit.js b/public/js/open-audit.js
index e8c4e4d5b..2ef688db7 100644
--- a/public/js/open-audit.js
+++ b/public/js/open-audit.js
@@ -77,6 +77,10 @@ $(document).ready(function () {
return;
}
}
+ if (attribute == 'tags' && collection == 'devices') {
+ value = JSON.parse($("#tags_add").attr("data-tags"));
+ value.push($("#tags_add").val());
+ }
if (attribute.indexOf(".") === -1) {
data["data"]["attributes"][attribute] = value;
} else {
@@ -113,7 +117,11 @@ $(document).ready(function () {
data: {data : data},
success: function (data) {
$("#liveToastSuccess-header").text("Update Succeeded");
- $("#liveToastSuccess-body").text(attribute + " has been updated.");
+ if (attribute == 'tags' && collection == 'devices') {
+ $("#liveToastSuccess-body").text(attribute + " has been updated. Refresh page to update.");
+ } else {
+ $("#liveToastSuccess-body").text(attribute + " has been updated.");
+ }
var toastElList = [].slice.call(document.querySelectorAll('.toast-success'));
var toastList = toastElList.map(function(toastEl) {
return new bootstrap.Toast(toastEl)
@@ -147,6 +155,9 @@ $(document).ready(function () {
$(".submit[data-attribute='" + attribute.replace(/\./g, '\\.') + "']").hide();
$(".cancel[data-attribute='" + attribute.replace(/\./g, '\\.') + "']").hide();
$(".form-help[data-attribute='" + attribute.replace(/\./g, '\\.') + "']").html('
');
+ if (attribute == 'tags' && collection == 'devices') {
+ $("#tags_control").css('display', 'none');
+ }
});
/* Delete links */
@@ -217,6 +228,51 @@ $(document).ready(function () {
});
});
+
+ /* Inline edit, click DELETE on tags */
+ $(document).on('click', '.delete_tags', function (e) {
+ if (confirm("Are you sure you want to delete this tag?") !== true) {
+ return;
+ }
+ var attribute = 'tags';
+ var value = $(this).attr("data-tags");
+ var data = {};
+ data["data"] = {};
+ data["data"]["id"] = id;
+ data["data"]["type"] = collection;
+ data["data"]["attributes"] = {};
+ data["data"]["attributes"]["tags"] = value;
+ data = JSON.stringify(data);
+ console.log(data);
+ $.ajax({
+ type: "PATCH",
+ url: id,
+ contentType: "application/json",
+ data: {data : data},
+ success: function (data) {
+ $("#liveToastSuccess-header").text("Update Succeeded");
+ $("#liveToastSuccess-body").text(attribute + " has been updated. Refresh page to update.");
+ var toastElList = [].slice.call(document.querySelectorAll('.toast-success'));
+ var toastList = toastElList.map(function(toastEl) {
+ return new bootstrap.Toast(toastEl)
+ });
+ toastList.forEach(toast => toast.show());
+ },
+ error: function (data) {
+ data = JSON.parse(data.responseText);
+ $("#liveToastFailure-header").text("Update Failed");
+ $("#liveToastFailure-body").text(data.message);
+ var toastElList = [].slice.call(document.querySelectorAll('.toast-failure'));
+ var toastList = toastElList.map(function(toastEl) {
+ return new bootstrap.Toast(toastEl)
+ });
+ toastList.forEach(toast => toast.show());
+ console.log(data);
+
+ }
+ });
+ });
+
/* Toasts for the various feature / edition items */
$('.toastEnterprise').on('click', function() {
var toastElList = [].slice.call(document.querySelectorAll('.toast-ent'));