mirror of
https://github.com/jokob-sk/NetAlertX.git
synced 2025-12-07 01:26:11 -08:00
Workflows v0.1.1 🆕
This commit is contained in:
@@ -52,7 +52,8 @@ services:
|
||||
- ${DEV_LOCATION}/front/settings.php:/home/pi/pialert/front/settings.php
|
||||
- ${DEV_LOCATION}/front/systeminfo.php:/home/pi/pialert/front/systeminfo.php
|
||||
- ${DEV_LOCATION}/front/report.php:/home/pi/pialert/front/report.php
|
||||
- ${DEV_LOCATION}/front/flows.php:/home/pi/pialert/front/flows.php
|
||||
- ${DEV_LOCATION}/front/workflows.php:/home/pi/pialert/front/workflows.php
|
||||
- ${DEV_LOCATION}/front/appEventsCore.php:/home/pi/pialert/front/appEventsCore.php
|
||||
- ${DEV_LOCATION}/front/donations.php:/home/pi/pialert/front/donations.php
|
||||
- ${DEV_LOCATION}/front/plugins:/home/pi/pialert/front/plugins
|
||||
# DELETE END anyone trying to use this file: comment out / delete ABOVE lines, they are only for development purposes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
## How to setup your Network page
|
||||
|
||||
Make sure you have a root device with the MAC `Internet` (No other MAC addresses are currently supported as the root node).
|
||||
Make sure you have a root device with the MAC `Internet` (No other MAC addresses are currently supported as the root node) set to a network device type (e.g.: **Type**:`Router`).
|
||||
|
||||
> 💡 Tip: You can add dummy devices via the [Undiscoverables plugin](https://github.com/jokob-sk/Pi.Alert/blob/main/front/plugins/undiscoverables/README.md)
|
||||
|
||||
|
||||
86
front/appEventsCore.php
Executable file
86
front/appEventsCore.php
Executable file
@@ -0,0 +1,86 @@
|
||||
<section class="content">
|
||||
<div class="nav-tabs-custom app-event-content" style="margin-bottom: 0px;">
|
||||
<ul id="tabs-location" class="nav nav-tabs col-sm-2">
|
||||
<li class="left-nav"><a class="col-sm-12" href="#" id="" data-toggle="tab">Events</a></li>
|
||||
</ul>
|
||||
<div id="tabs-content-location" class="tab-content col-sm-10">
|
||||
<table class="table table-striped" id="appevents-table" data-my-dbtable="AppEvents"></table>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<script>
|
||||
$(document).ready(function() {
|
||||
// Load JSON data from the provided URL
|
||||
$.getJSON('/api/table_appevents.json', function(data) {
|
||||
// Process the JSON data and generate UI dynamically
|
||||
processData(data)
|
||||
});
|
||||
});
|
||||
|
||||
function processData(data) {
|
||||
// Create an object to store unique ObjectType values as app event identifiers
|
||||
var appEventIdentifiers = {};
|
||||
|
||||
// Array to accumulate data for DataTable
|
||||
var allData = [];
|
||||
|
||||
// Iterate through the data and generate tabs and content dynamically
|
||||
$.each(data.data, function(index, item) {
|
||||
|
||||
// Accumulate data for DataTable
|
||||
allData.push(item);
|
||||
|
||||
});
|
||||
|
||||
// Initialize DataTable for all app events
|
||||
|
||||
$('#appevents-table').DataTable({
|
||||
data: allData,
|
||||
paging: true,
|
||||
lengthChange: true,
|
||||
lengthMenu: [[10, 25, 50, 100, 500, -1], [10, 25, 50, 100, 500, 'All']],
|
||||
searching: true,
|
||||
ordering: true,
|
||||
info: true,
|
||||
autoWidth: false,
|
||||
pageLength: 25, // Set the default paging to 25
|
||||
columns: [
|
||||
{ data: 'DateTimeCreated', title: getString('AppEvents_DateTimeCreated') },
|
||||
{ data: 'AppEventType', title: getString('AppEvents_Type') },
|
||||
{ data: 'ObjectType', title: getString('AppEvents_ObjectType') },
|
||||
{ data: 'ObjectMAC', title: getString('AppEvents_ObjectMAC') },
|
||||
{ data: 'ObjectIP', title: getString('AppEvents_ObjectIP') },
|
||||
{ data: 'ObjectStatus', title: getString('AppEvents_ObjectStatus') },
|
||||
{ data: 'Extra', title: getString('AppEvents_Extra') },
|
||||
// Add other columns as needed
|
||||
],
|
||||
// Add column-specific configurations if needed
|
||||
columnDefs: [
|
||||
{ className: 'text-center', targets: [3] },
|
||||
{ width: '80px', targets: [6] },
|
||||
// ... Add other columnDefs as needed
|
||||
// Full MAC
|
||||
{targets: [3],
|
||||
'createdCell': function (td, cellData, rowData, row, col) {
|
||||
if (!emptyArr.includes(cellData)){
|
||||
$(td).html (createDeviceLink(cellData));
|
||||
} else {
|
||||
$(td).html ('');
|
||||
}
|
||||
} },
|
||||
]
|
||||
});
|
||||
|
||||
|
||||
// Activate the first tab
|
||||
$('#tabs-location li:first-child').addClass('active');
|
||||
$('#tabs-content-location .tab-pane:first-child').addClass('active');
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<!-- Datatable -->
|
||||
<link rel="stylesheet" href="lib/AdminLTE/bower_components/datatables.net-bs/css/dataTables.bootstrap.min.css"/>
|
||||
<script src="lib/AdminLTE/bower_components/datatables.net/js/jquery.dataTables.min.js"></script>
|
||||
<script src="lib/AdminLTE/bower_components/datatables.net-bs/js/dataTables.bootstrap.min.js"></script>
|
||||
@@ -1475,7 +1475,7 @@ function updateApi()
|
||||
{
|
||||
|
||||
// value has to be in format event|param. e.g. run|ARPSCAN
|
||||
action = `update_api|devices`
|
||||
action = `update_api|devices,appevents`
|
||||
|
||||
$.ajax({
|
||||
method: "POST",
|
||||
|
||||
@@ -418,6 +418,14 @@ function saveData(functionName, id, value) {
|
||||
}
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// create a link to the device
|
||||
function createDeviceLink(mac)
|
||||
{
|
||||
return `<span class="anonymizeMac"><a href="/deviceDetails.php?mac=${mac}" target="_blank">${getNameByMacAddress(mac)}</a><span>`
|
||||
}
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// remove an item from an array
|
||||
function removeItemFromArray(arr, value) {
|
||||
|
||||
@@ -252,9 +252,9 @@ if ($ENABLED_DARKMODE === True) {
|
||||
<li class=" <?php if (in_array (basename($_SERVER['SCRIPT_NAME']), array('settings.php') ) ){ echo 'active'; } ?>">
|
||||
<a href="settings.php"><i class="fa fa-cog"></i> <span><?= lang('Navigation_Settings');?></span></a>
|
||||
</li>
|
||||
<!-- <li class=" <?php if (in_array (basename($_SERVER['SCRIPT_NAME']), array('flows.php') ) ){ echo 'active'; } ?>">
|
||||
<a href="flows.php"><i class="fa fa-shuffle"></i> <span><?= lang('Navigation_Flows');?></span></a>
|
||||
</li> -->
|
||||
<li class=" <?php if (in_array (basename($_SERVER['SCRIPT_NAME']), array('flows.php') ) ){ echo 'active'; } ?>">
|
||||
<a href="workflows.php"><i class="fa fa-shuffle"></i> <span><?= lang('Navigation_Workflows');?></span></a>
|
||||
</li>
|
||||
<li class=" <?php if (in_array (basename($_SERVER['SCRIPT_NAME']), array('systeminfo.php') ) ){ echo 'active'; } ?>">
|
||||
<a href="systeminfo.php"><i class="fa fa-microchip"></i> <span><?= lang('Navigation_SystemInfo');?></span></a>
|
||||
</li>
|
||||
|
||||
@@ -3,6 +3,25 @@
|
||||
"About_Title": "Open Source Network Guard",
|
||||
"About_Design" : "Designed for:",
|
||||
"About_Exit" : "Sign out",
|
||||
"AppEvents_GUID" : "Application Event GUID",
|
||||
"AppEvents_DateTimeCreated" : "Logged",
|
||||
"AppEvents_ObjectType" : "Object Type",
|
||||
"AppEvents_ObjectPlugin" : "Linked Plugin",
|
||||
"AppEvents_ObjectMAC" : "Linked MAC (at log time)",
|
||||
"AppEvents_ObjectIP" : "Linked IP (at log time)",
|
||||
"AppEvents_ObjectPrimaryID" : "Primary ID",
|
||||
"AppEvents_ObjectSecondaryID" : "Secondary ID",
|
||||
"AppEvents_ObjectForeignKey" : "Foreign Key",
|
||||
"AppEvents_ObjectIndex" : "Index",
|
||||
"AppEvents_ObjectIsNew" : "Is new (at log time)",
|
||||
"AppEvents_ObjectIsArchived" : "Is archived (at log time)",
|
||||
"AppEvents_ObjectStatusColumn" : "Status column",
|
||||
"AppEvents_ObjectStatus" : "Status (at log time)",
|
||||
"AppEvents_Type" : "Type",
|
||||
"AppEvents_Helper1" : "Helper 1",
|
||||
"AppEvents_Helper2" : "Helper 2",
|
||||
"AppEvents_Helper3" : "Helper 3",
|
||||
"AppEvents_Extra" : "Extra",
|
||||
"Gen_Delete" : "Delete",
|
||||
"Gen_DeleteAll" : "Delete all",
|
||||
"Gen_Cancel" : "Cancel",
|
||||
@@ -44,7 +63,7 @@
|
||||
"Navigation_Maintenance" : "Maintenance",
|
||||
"Navigation_Settings" : "Settings",
|
||||
"Navigation_SystemInfo" : "System info",
|
||||
"Navigation_Flows" : "Flows",
|
||||
"Navigation_Workflows" : "Workflows",
|
||||
"Navigation_HelpFAQ" : "Help / FAQ",
|
||||
"Navigation_Donations" : "Donations",
|
||||
"Device_Title" : "Devices",
|
||||
|
||||
0
front/php/templates/language/fr_fr.json
Normal file → Executable file
0
front/php/templates/language/fr_fr.json
Normal file → Executable file
@@ -188,7 +188,7 @@
|
||||
"description": [
|
||||
{
|
||||
"language_code": "en_us",
|
||||
"string": "How many historical entries of Notifications should be kept. This influences how mane entries are also available in the Report section in the UI"
|
||||
"string": "How many historical entries of Notifications should be kept. This influences how many entries are also available in the Report section in the UI"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -66,17 +66,20 @@ def cleanup_database (dbPath, DAYS_TO_KEEP_EVENTS, PHOLUS_DAYS_DATA, HRS_TO_KEEP
|
||||
conn = sqlite3.connect(dbPath)
|
||||
cursor = conn.cursor()
|
||||
|
||||
# -----------------------------------------------------
|
||||
# Cleanup Online History
|
||||
mylog('verbose', [f'[{pluginName}] Online_History: Delete all but keep latest 150 entries'])
|
||||
cursor.execute ("""DELETE from Online_History where "Index" not in (
|
||||
SELECT "Index" from Online_History
|
||||
order by Scan_Date desc limit 150)""")
|
||||
mylog('verbose', [f'[{pluginName}] Optimize Database'])
|
||||
|
||||
|
||||
# -----------------------------------------------------
|
||||
# Cleanup Events
|
||||
mylog('verbose', [f'[{pluginName}] Events: Delete all older than {str(DAYS_TO_KEEP_EVENTS)} days (DAYS_TO_KEEP_EVENTS setting)'])
|
||||
cursor.execute (f"""DELETE FROM Events
|
||||
WHERE eve_DateTime <= date('now', '-{str(DAYS_TO_KEEP_EVENTS)} day')""")
|
||||
|
||||
# -----------------------------------------------------
|
||||
# Trim Plugins_History entries to less than PLUGINS_KEEP_HIST setting per unique "Plugin" column entry
|
||||
mylog('verbose', [f'[{pluginName}] Plugins_History: Trim Plugins_History entries to less than {str(PLUGINS_KEEP_HIST)} per Plugin (PLUGINS_KEEP_HIST setting)'])
|
||||
|
||||
@@ -94,7 +97,7 @@ def cleanup_database (dbPath, DAYS_TO_KEEP_EVENTS, PHOLUS_DAYS_DATA, HRS_TO_KEEP
|
||||
|
||||
cursor.execute(delete_query)
|
||||
|
||||
|
||||
# -----------------------------------------------------
|
||||
# Trim Notifications entries to less than DBCLNP_NOTIFI_HIST setting
|
||||
|
||||
histCount = get_setting_value('DBCLNP_NOTIFI_HIST')
|
||||
@@ -115,19 +118,58 @@ def cleanup_database (dbPath, DAYS_TO_KEEP_EVENTS, PHOLUS_DAYS_DATA, HRS_TO_KEEP
|
||||
|
||||
cursor.execute(delete_query)
|
||||
|
||||
# Cleanup Pholus_Scan
|
||||
if PHOLUS_DAYS_DATA != 0:
|
||||
mylog('verbose', [f'[{pluginName}] Pholus_Scan: Delete all older than ' + str(PHOLUS_DAYS_DATA) + ' days (PHOLUS_DAYS_DATA setting)'])
|
||||
# todo: improvement possibility: keep at least N per mac
|
||||
cursor.execute (f"""DELETE FROM Pholus_Scan
|
||||
WHERE Time <= date('now', '-{str(PHOLUS_DAYS_DATA)} day')""")
|
||||
|
||||
# -----------------------------------------------------
|
||||
# Trim Workflow entries to less than WORKFLOWS_AppEvents_hist setting
|
||||
histCount = get_setting_value('WORKFLOWS_AppEvents_hist')
|
||||
|
||||
mylog('verbose', [f'[{pluginName}] Trim AppEvents to less than {histCount}'])
|
||||
|
||||
# Build the SQL query to delete entries
|
||||
delete_query = f"""DELETE FROM AppEvents
|
||||
WHERE "Index" NOT IN (
|
||||
SELECT "Index"
|
||||
FROM (
|
||||
SELECT "Index",
|
||||
ROW_NUMBER() OVER(PARTITION BY "AppEvents" ORDER BY DateTimeCreated DESC) AS row_num
|
||||
FROM AppEvents
|
||||
) AS ranked_objects
|
||||
WHERE row_num <= {histCount}
|
||||
);"""
|
||||
|
||||
cursor.execute(delete_query)
|
||||
|
||||
|
||||
# -----------------------------------------------------
|
||||
# Cleanup New Devices
|
||||
if HRS_TO_KEEP_NEWDEV != 0:
|
||||
mylog('verbose', [f'[{pluginName}] Devices: Delete all New Devices older than {str(HRS_TO_KEEP_NEWDEV)} hours (HRS_TO_KEEP_NEWDEV setting)'])
|
||||
cursor.execute (f"""DELETE FROM Devices
|
||||
WHERE dev_NewDevice = 1 AND dev_FirstConnection < date('now', '+{str(HRS_TO_KEEP_NEWDEV)} hour')""")
|
||||
|
||||
# -----------------------------------------------------
|
||||
# Cleanup Pholus_Scan
|
||||
if PHOLUS_DAYS_DATA != 0:
|
||||
mylog('verbose', [f'[{pluginName}] Pholus_Scan: Delete all older than ' + str(PHOLUS_DAYS_DATA) + ' days (PHOLUS_DAYS_DATA setting)'])
|
||||
# todo: improvement possibility: keep at least N per mac
|
||||
cursor.execute (f"""DELETE FROM Pholus_Scan
|
||||
WHERE Time <= date('now', '-{str(PHOLUS_DAYS_DATA)} day')""")
|
||||
|
||||
|
||||
|
||||
# -----------------------------------------------------
|
||||
# De-Dupe (de-duplicate - remove duplicate entries) from the Pholus_Scan table
|
||||
mylog('verbose', [f'[{pluginName}] Pholus_Scan: Delete all duplicates'])
|
||||
cursor.execute ("""DELETE FROM Pholus_Scan
|
||||
WHERE rowid > (
|
||||
SELECT MIN(rowid) FROM Pholus_Scan p2
|
||||
WHERE Pholus_Scan.MAC = p2.MAC
|
||||
AND Pholus_Scan.Value = p2.Value
|
||||
AND Pholus_Scan.Record_Type = p2.Record_Type
|
||||
);""")
|
||||
|
||||
|
||||
# -----------------------------------------------------
|
||||
# De-dupe (de-duplicate) from the Plugins_Objects table
|
||||
# TODO This shouldn't be necessary - probably a concurrency bug somewhere in the code :(
|
||||
mylog('verbose', [f'[{pluginName}] Plugins_Objects: Delete all duplicates'])
|
||||
@@ -142,15 +184,6 @@ def cleanup_database (dbPath, DAYS_TO_KEEP_EVENTS, PHOLUS_DAYS_DATA, HRS_TO_KEEP
|
||||
)
|
||||
""")
|
||||
|
||||
# De-Dupe (de-duplicate - remove duplicate entries) from the Pholus_Scan table
|
||||
mylog('verbose', [f'[{pluginName}] Pholus_Scan: Delete all duplicates'])
|
||||
cursor.execute ("""DELETE FROM Pholus_Scan
|
||||
WHERE rowid > (
|
||||
SELECT MIN(rowid) FROM Pholus_Scan p2
|
||||
WHERE Pholus_Scan.MAC = p2.MAC
|
||||
AND Pholus_Scan.Value = p2.Value
|
||||
AND Pholus_Scan.Record_Type = p2.Record_Type
|
||||
);""")
|
||||
|
||||
conn.commit()
|
||||
|
||||
|
||||
7
front/plugins/workflows/README.md
Executable file
7
front/plugins/workflows/README.md
Executable file
@@ -0,0 +1,7 @@
|
||||
## Overview
|
||||
|
||||
TBC
|
||||
|
||||
### Usage
|
||||
|
||||
- Check the Settings page for details.
|
||||
57
front/plugins/workflows/config.json
Executable file
57
front/plugins/workflows/config.json
Executable file
@@ -0,0 +1,57 @@
|
||||
{
|
||||
"code_name": "workflows",
|
||||
"unique_prefix": "WORKFLOWS",
|
||||
"plugin_type": "system",
|
||||
"enabled": true,
|
||||
"data_source": "script",
|
||||
"show_ui": false,
|
||||
"localized": ["display_name", "description", "icon"],
|
||||
|
||||
"display_name": [
|
||||
{
|
||||
"language_code": "en_us",
|
||||
"string": "Workflows"
|
||||
}
|
||||
],
|
||||
"icon": [
|
||||
{
|
||||
"language_code": "en_us",
|
||||
"string": "<i class=\"fa-solid fa-shuffle\"></i>"
|
||||
}
|
||||
],
|
||||
"description": [
|
||||
{
|
||||
"language_code": "en_us",
|
||||
"string": "A plugin to adjust behavior of workflows."
|
||||
}
|
||||
],
|
||||
"params" : [
|
||||
],
|
||||
|
||||
"settings": [
|
||||
{
|
||||
"function": "AppEvents_hist",
|
||||
"type": "integer",
|
||||
"default_value": 10000,
|
||||
"options": [],
|
||||
"localized": ["name", "description"],
|
||||
"name": [
|
||||
{
|
||||
"language_code": "en_us",
|
||||
"string": "App Events History"
|
||||
}
|
||||
],
|
||||
"description": [
|
||||
{
|
||||
"language_code": "en_us",
|
||||
"string": "How many historical entries of Application Events should be kept. This influences how many entries are also available in the Workflows section in the UI."
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
|
||||
"database_column_definitions":
|
||||
[
|
||||
|
||||
]
|
||||
}
|
||||
@@ -123,7 +123,7 @@ function processColumnValue(dbColumnDef, value, index, type) {
|
||||
<span>`;
|
||||
break;
|
||||
case 'device_name_mac':
|
||||
value = `<span class="anonymizeMac"><a href="/deviceDetails.php?mac=${value}" target="_blank">${getNameByMacAddress(value)}</a><span>`;
|
||||
value = createDeviceLink(value);
|
||||
break;
|
||||
case 'device_mac':
|
||||
value = `<span class="anonymizeMac"><a href="/deviceDetails.php?mac=${value}" target="_blank">${value}</a><span>`;
|
||||
|
||||
@@ -13,14 +13,14 @@
|
||||
<section class="content-header">
|
||||
|
||||
<h1 id="pageTitle">
|
||||
<i class="fa fa-fw fa-plug"></i> <?= lang('Navigation_Flows');?>
|
||||
<i class="fa fa-fw fa-plug"></i> <?= lang('Navigation_Workflows');?>
|
||||
<span class="pageHelp"> <a target="_blank" href="https://github.com/jokob-sk/Pi.Alert/tree/main/front/plugins"><i class="fa fa-circle-question"></i></a><span>
|
||||
</h1>
|
||||
</section>
|
||||
|
||||
|
||||
<?php
|
||||
// require 'pluginsCore.php';
|
||||
require 'appEventsCore.php';
|
||||
?>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ import json
|
||||
|
||||
# pialert modules
|
||||
import conf
|
||||
from const import (apiPath, sql_devices_all, sql_events_pending_alert, sql_settings, sql_plugins_events, sql_plugins_history, sql_plugins_objects,sql_language_strings, sql_notifications_all)
|
||||
from const import (apiPath, sql_appevents, sql_devices_all, sql_events_pending_alert, sql_settings, sql_plugins_events, sql_plugins_history, sql_plugins_objects,sql_language_strings, sql_notifications_all)
|
||||
from logger import mylog
|
||||
from helper import write_file
|
||||
|
||||
@@ -23,6 +23,7 @@ def update_api(db, isNotification = False, updateOnlyDataSources = []):
|
||||
|
||||
# prepare database tables we want to expose
|
||||
dataSourcesSQLs = [
|
||||
["appevents", sql_appevents],
|
||||
["devices", sql_devices_all],
|
||||
["events_pending_alert", sql_events_pending_alert],
|
||||
["settings", sql_settings],
|
||||
|
||||
@@ -16,6 +16,15 @@ class AppEvent_obj:
|
||||
def __init__(self, db):
|
||||
self.db = db
|
||||
|
||||
# drop table
|
||||
self.db.sql.execute("""DROP TABLE IF EXISTS "AppEvents" """)
|
||||
|
||||
# Drop all triggers
|
||||
self.db.sql.execute('DROP TRIGGER IF EXISTS trg_create_device;')
|
||||
self.db.sql.execute('DROP TRIGGER IF EXISTS trg_read_device;')
|
||||
self.db.sql.execute('DROP TRIGGER IF EXISTS trg_update_device;')
|
||||
self.db.sql.execute('DROP TRIGGER IF EXISTS trg_delete_device;')
|
||||
|
||||
# Create AppEvent table if missing
|
||||
self.db.sql.execute("""CREATE TABLE IF NOT EXISTS "AppEvents" (
|
||||
"Index" INTEGER,
|
||||
@@ -29,18 +38,133 @@ class AppEvent_obj:
|
||||
"ObjectPrimaryID" TEXT,
|
||||
"ObjectSecondaryID" TEXT,
|
||||
"ObjectForeignKey" TEXT,
|
||||
"ObjectIndex" TEXT,
|
||||
"ObjectRowID" TEXT,
|
||||
"ObjectIndex" TEXT,
|
||||
"ObjectIsNew" BOOLEAN,
|
||||
"ObjectIsArchived" BOOLEAN,
|
||||
"ObjectStatusColumn" TEXT, -- Status (Notifications, Plugins), eve_EventType (Events)
|
||||
"ObjectStatus" TEXT, -- new_devices, down_devices, events, new, watched-changed, watched-not-changed, missing-in-last-scan, Device down, New Device, IP Changed, Connected, Disconnected, VOIDED - Disconnected, VOIDED - Connected, <missing event>
|
||||
"AppEventStatus" TEXT, -- TBD "new", "used", "cleanup-next"
|
||||
"Extra" TEXT,
|
||||
"ObjectStatus" TEXT, -- new_devices, down_devices, events, new, watched-changed, watched-not-changed, missing-in-last-scan, Device down, New Device, IP Changed, Connected, Disconnected, VOIDED - Disconnected, VOIDED - Connected, <missing event>
|
||||
"AppEventType" TEXT, -- "create", "update", "delete" (+TBD)
|
||||
"Helper1" TEXT,
|
||||
"Helper2" TEXT,
|
||||
"Helper3" TEXT,
|
||||
"Extra" TEXT,
|
||||
PRIMARY KEY("Index" AUTOINCREMENT)
|
||||
);
|
||||
""")
|
||||
|
||||
# Generate a GUID
|
||||
sql_generateGuid = '''
|
||||
lower(
|
||||
hex(randomblob(4)) || '-' || hex(randomblob(2)) || '-' || '4' ||
|
||||
substr(hex( randomblob(2)), 2) || '-' ||
|
||||
substr('AB89', 1 + (abs(random()) % 4) , 1) ||
|
||||
substr(hex(randomblob(2)), 2) || '-' ||
|
||||
hex(randomblob(6))
|
||||
)
|
||||
'''
|
||||
|
||||
sql_mappedColumns = '''
|
||||
"GUID",
|
||||
"DateTimeCreated",
|
||||
"ObjectType",
|
||||
"ObjectMAC",
|
||||
"ObjectIP",
|
||||
"ObjectStatus",
|
||||
"ObjectStatusColumn",
|
||||
"ObjectIsNew",
|
||||
"ObjectIsArchived",
|
||||
"ObjectForeignKey",
|
||||
"AppEventType"
|
||||
'''
|
||||
|
||||
# Trigger for create event
|
||||
self.db.sql.execute(f'''
|
||||
CREATE TRIGGER IF NOT EXISTS "trg_create_device"
|
||||
AFTER INSERT ON "Devices"
|
||||
BEGIN
|
||||
INSERT INTO "AppEvents" (
|
||||
{sql_mappedColumns}
|
||||
)
|
||||
VALUES (
|
||||
-- below generates a GUID
|
||||
{sql_generateGuid},
|
||||
DATETIME('now'),
|
||||
'Devices',
|
||||
NEW.dev_MAC,
|
||||
NEW.dev_LastIP,
|
||||
CASE WHEN NEW.dev_PresentLastScan = 1 THEN 'online' ELSE 'offline' END,
|
||||
'dev_PresentLastScan',
|
||||
NEW.dev_NewDevice,
|
||||
NEW.dev_Archived,
|
||||
NEW.dev_MAC,
|
||||
'create'
|
||||
);
|
||||
END;
|
||||
''')
|
||||
|
||||
# 🔴 This would generate too many events, disabled for now
|
||||
# # Trigger for read event
|
||||
# self.db.sql.execute('''
|
||||
# TODO
|
||||
# ''')
|
||||
|
||||
# Trigger for update event
|
||||
self.db.sql.execute(f'''
|
||||
CREATE TRIGGER IF NOT EXISTS "trg_update_device"
|
||||
AFTER UPDATE ON "Devices"
|
||||
BEGIN
|
||||
INSERT INTO "AppEvents" (
|
||||
{sql_mappedColumns}
|
||||
)
|
||||
VALUES (
|
||||
-- below generates a GUID
|
||||
{sql_generateGuid},
|
||||
DATETIME('now'),
|
||||
'Devices',
|
||||
NEW.dev_MAC,
|
||||
NEW.dev_LastIP,
|
||||
CASE WHEN NEW.dev_PresentLastScan = 1 THEN 'online' ELSE 'offline' END,
|
||||
'dev_PresentLastScan',
|
||||
NEW.dev_NewDevice,
|
||||
NEW.dev_Archived,
|
||||
NEW.dev_MAC,
|
||||
'update'
|
||||
);
|
||||
END;
|
||||
''')
|
||||
|
||||
# Trigger for delete event
|
||||
self.db.sql.execute(f'''
|
||||
CREATE TRIGGER IF NOT EXISTS "trg_delete_device"
|
||||
AFTER DELETE ON "Devices"
|
||||
BEGIN
|
||||
INSERT INTO "AppEvents" (
|
||||
{sql_mappedColumns}
|
||||
)
|
||||
VALUES (
|
||||
-- below generates a GUID
|
||||
{sql_generateGuid},
|
||||
DATETIME('now'),
|
||||
'Devices',
|
||||
OLD.dev_MAC,
|
||||
OLD.dev_LastIP,
|
||||
CASE WHEN OLD.dev_PresentLastScan = 1 THEN 'online' ELSE 'offline' END,
|
||||
'dev_PresentLastScan',
|
||||
OLD.dev_NewDevice,
|
||||
OLD.dev_Archived,
|
||||
OLD.dev_MAC,
|
||||
'delete'
|
||||
);
|
||||
END;
|
||||
''')
|
||||
|
||||
self.save()
|
||||
|
||||
# -------------------------------------------------------------------------------
|
||||
# -------------------------------------------------------------------------------
|
||||
# below code is unused
|
||||
# -------------------------------------------------------------------------------
|
||||
|
||||
# Create a new DB entry if new notifications are available, otherwise skip
|
||||
def create(self, Extra="", **kwargs):
|
||||
# Check if nothing to report, end
|
||||
@@ -72,11 +196,6 @@ class AppEvent_obj:
|
||||
|
||||
return True
|
||||
|
||||
# Update the status of the entry
|
||||
def updateStatus(self, newStatus):
|
||||
self.ObjectStatus = newStatus
|
||||
self.upsert()
|
||||
|
||||
def upsert(self):
|
||||
self.db.sql.execute("""
|
||||
INSERT OR REPLACE INTO AppEvents (
|
||||
|
||||
@@ -23,6 +23,7 @@ vendorsPath = '/usr/share/arp-scan/ieee-oui.txt'
|
||||
# SQL queries
|
||||
#===============================================================================
|
||||
sql_devices_all = """select rowid, * from Devices"""
|
||||
sql_appevents = """select * from AppEvents"""
|
||||
sql_devices_stats = """SELECT Online_Devices as online, Down_Devices as down, All_Devices as 'all', Archived_Devices as archived,
|
||||
(select count(*) from Devices a where dev_NewDevice = 1 ) as new,
|
||||
(select count(*) from Devices a where dev_Name = '(unknown)' or dev_Name = '(name not found)' ) as unknown
|
||||
|
||||
@@ -7,6 +7,7 @@ from const import fullDbPath, sql_devices_stats, sql_devices_all
|
||||
|
||||
from logger import mylog
|
||||
from helper import json_obj, initOrSetParam, row_to_json, timeNowTZ #, updateState
|
||||
from appevent import AppEvent_obj
|
||||
|
||||
|
||||
|
||||
@@ -83,8 +84,8 @@ class DB():
|
||||
|
||||
# indicates, if Online_History table is available
|
||||
onlineHistoryAvailable = self.sql.execute("""
|
||||
SELECT name FROM sqlite_master WHERE type='table'
|
||||
AND name='Online_History';
|
||||
SELECT name FROM sqlite_master WHERE type='table'
|
||||
AND name='Online_History';
|
||||
""").fetchall() != []
|
||||
|
||||
# Check if it is incompatible (Check if table has all required columns)
|
||||
@@ -92,8 +93,8 @@ class DB():
|
||||
|
||||
if onlineHistoryAvailable :
|
||||
isIncompatible = self.sql.execute ("""
|
||||
SELECT COUNT(*) AS CNTREC FROM pragma_table_info('Online_History') WHERE name='Archived_Devices'
|
||||
""").fetchone()[0] == 0
|
||||
SELECT COUNT(*) AS CNTREC FROM pragma_table_info('Online_History') WHERE name='Archived_Devices'
|
||||
""").fetchone()[0] == 0
|
||||
|
||||
# Drop table if available, but incompatible
|
||||
if onlineHistoryAvailable and isIncompatible:
|
||||
@@ -119,35 +120,35 @@ class DB():
|
||||
# -------------------------------------------------------------------------
|
||||
# dev_Network_Node_MAC_ADDR column
|
||||
dev_Network_Node_MAC_ADDR_missing = self.sql.execute ("""
|
||||
SELECT COUNT(*) AS CNTREC FROM pragma_table_info('Devices') WHERE name='dev_Network_Node_MAC_ADDR'
|
||||
SELECT COUNT(*) AS CNTREC FROM pragma_table_info('Devices') WHERE name='dev_Network_Node_MAC_ADDR'
|
||||
""").fetchone()[0] == 0
|
||||
|
||||
if dev_Network_Node_MAC_ADDR_missing :
|
||||
mylog('verbose', ["[upgradeDB] Adding dev_Network_Node_MAC_ADDR to the Devices table"])
|
||||
self.sql.execute("""
|
||||
ALTER TABLE "Devices" ADD "dev_Network_Node_MAC_ADDR" TEXT
|
||||
ALTER TABLE "Devices" ADD "dev_Network_Node_MAC_ADDR" TEXT
|
||||
""")
|
||||
|
||||
# dev_Network_Node_port column
|
||||
dev_Network_Node_port_missing = self.sql.execute ("""
|
||||
SELECT COUNT(*) AS CNTREC FROM pragma_table_info('Devices') WHERE name='dev_Network_Node_port'
|
||||
SELECT COUNT(*) AS CNTREC FROM pragma_table_info('Devices') WHERE name='dev_Network_Node_port'
|
||||
""").fetchone()[0] == 0
|
||||
|
||||
if dev_Network_Node_port_missing :
|
||||
mylog('verbose', ["[upgradeDB] Adding dev_Network_Node_port to the Devices table"])
|
||||
self.sql.execute("""
|
||||
ALTER TABLE "Devices" ADD "dev_Network_Node_port" INTEGER
|
||||
ALTER TABLE "Devices" ADD "dev_Network_Node_port" INTEGER
|
||||
""")
|
||||
|
||||
# dev_Icon column
|
||||
dev_Icon_missing = self.sql.execute ("""
|
||||
SELECT COUNT(*) AS CNTREC FROM pragma_table_info('Devices') WHERE name='dev_Icon'
|
||||
SELECT COUNT(*) AS CNTREC FROM pragma_table_info('Devices') WHERE name='dev_Icon'
|
||||
""").fetchone()[0] == 0
|
||||
|
||||
if dev_Icon_missing :
|
||||
mylog('verbose', ["[upgradeDB] Adding dev_Icon to the Devices table"])
|
||||
self.sql.execute("""
|
||||
ALTER TABLE "Devices" ADD "dev_Icon" TEXT
|
||||
ALTER TABLE "Devices" ADD "dev_Icon" TEXT
|
||||
""")
|
||||
|
||||
|
||||
@@ -263,61 +264,61 @@ class DB():
|
||||
|
||||
# Plugin state
|
||||
sql_Plugins_Objects = """ CREATE TABLE IF NOT EXISTS Plugins_Objects(
|
||||
"Index" INTEGER,
|
||||
Plugin TEXT NOT NULL,
|
||||
Object_PrimaryID TEXT NOT NULL,
|
||||
Object_SecondaryID TEXT NOT NULL,
|
||||
DateTimeCreated TEXT NOT NULL,
|
||||
DateTimeChanged TEXT NOT NULL,
|
||||
Watched_Value1 TEXT NOT NULL,
|
||||
Watched_Value2 TEXT NOT NULL,
|
||||
Watched_Value3 TEXT NOT NULL,
|
||||
Watched_Value4 TEXT NOT NULL,
|
||||
Status TEXT NOT NULL,
|
||||
Extra TEXT NOT NULL,
|
||||
UserData TEXT NOT NULL,
|
||||
ForeignKey TEXT NOT NULL,
|
||||
PRIMARY KEY("Index" AUTOINCREMENT)
|
||||
"Index" INTEGER,
|
||||
Plugin TEXT NOT NULL,
|
||||
Object_PrimaryID TEXT NOT NULL,
|
||||
Object_SecondaryID TEXT NOT NULL,
|
||||
DateTimeCreated TEXT NOT NULL,
|
||||
DateTimeChanged TEXT NOT NULL,
|
||||
Watched_Value1 TEXT NOT NULL,
|
||||
Watched_Value2 TEXT NOT NULL,
|
||||
Watched_Value3 TEXT NOT NULL,
|
||||
Watched_Value4 TEXT NOT NULL,
|
||||
Status TEXT NOT NULL,
|
||||
Extra TEXT NOT NULL,
|
||||
UserData TEXT NOT NULL,
|
||||
ForeignKey TEXT NOT NULL,
|
||||
PRIMARY KEY("Index" AUTOINCREMENT)
|
||||
); """
|
||||
self.sql.execute(sql_Plugins_Objects)
|
||||
|
||||
# Plugin execution results
|
||||
sql_Plugins_Events = """ CREATE TABLE IF NOT EXISTS Plugins_Events(
|
||||
"Index" INTEGER,
|
||||
Plugin TEXT NOT NULL,
|
||||
Object_PrimaryID TEXT NOT NULL,
|
||||
Object_SecondaryID TEXT NOT NULL,
|
||||
DateTimeCreated TEXT NOT NULL,
|
||||
DateTimeChanged TEXT NOT NULL,
|
||||
Watched_Value1 TEXT NOT NULL,
|
||||
Watched_Value2 TEXT NOT NULL,
|
||||
Watched_Value3 TEXT NOT NULL,
|
||||
Watched_Value4 TEXT NOT NULL,
|
||||
Status TEXT NOT NULL,
|
||||
Extra TEXT NOT NULL,
|
||||
UserData TEXT NOT NULL,
|
||||
ForeignKey TEXT NOT NULL,
|
||||
PRIMARY KEY("Index" AUTOINCREMENT)
|
||||
"Index" INTEGER,
|
||||
Plugin TEXT NOT NULL,
|
||||
Object_PrimaryID TEXT NOT NULL,
|
||||
Object_SecondaryID TEXT NOT NULL,
|
||||
DateTimeCreated TEXT NOT NULL,
|
||||
DateTimeChanged TEXT NOT NULL,
|
||||
Watched_Value1 TEXT NOT NULL,
|
||||
Watched_Value2 TEXT NOT NULL,
|
||||
Watched_Value3 TEXT NOT NULL,
|
||||
Watched_Value4 TEXT NOT NULL,
|
||||
Status TEXT NOT NULL,
|
||||
Extra TEXT NOT NULL,
|
||||
UserData TEXT NOT NULL,
|
||||
ForeignKey TEXT NOT NULL,
|
||||
PRIMARY KEY("Index" AUTOINCREMENT)
|
||||
); """
|
||||
self.sql.execute(sql_Plugins_Events)
|
||||
|
||||
# Plugin execution history
|
||||
sql_Plugins_History = """ CREATE TABLE IF NOT EXISTS Plugins_History(
|
||||
"Index" INTEGER,
|
||||
Plugin TEXT NOT NULL,
|
||||
Object_PrimaryID TEXT NOT NULL,
|
||||
Object_SecondaryID TEXT NOT NULL,
|
||||
DateTimeCreated TEXT NOT NULL,
|
||||
DateTimeChanged TEXT NOT NULL,
|
||||
Watched_Value1 TEXT NOT NULL,
|
||||
Watched_Value2 TEXT NOT NULL,
|
||||
Watched_Value3 TEXT NOT NULL,
|
||||
Watched_Value4 TEXT NOT NULL,
|
||||
Status TEXT NOT NULL,
|
||||
Extra TEXT NOT NULL,
|
||||
UserData TEXT NOT NULL,
|
||||
ForeignKey TEXT NOT NULL,
|
||||
PRIMARY KEY("Index" AUTOINCREMENT)
|
||||
"Index" INTEGER,
|
||||
Plugin TEXT NOT NULL,
|
||||
Object_PrimaryID TEXT NOT NULL,
|
||||
Object_SecondaryID TEXT NOT NULL,
|
||||
DateTimeCreated TEXT NOT NULL,
|
||||
DateTimeChanged TEXT NOT NULL,
|
||||
Watched_Value1 TEXT NOT NULL,
|
||||
Watched_Value2 TEXT NOT NULL,
|
||||
Watched_Value3 TEXT NOT NULL,
|
||||
Watched_Value4 TEXT NOT NULL,
|
||||
Status TEXT NOT NULL,
|
||||
Extra TEXT NOT NULL,
|
||||
UserData TEXT NOT NULL,
|
||||
ForeignKey TEXT NOT NULL,
|
||||
PRIMARY KEY("Index" AUTOINCREMENT)
|
||||
); """
|
||||
self.sql.execute(sql_Plugins_History)
|
||||
|
||||
@@ -328,12 +329,12 @@ class DB():
|
||||
# Dynamically generated language strings
|
||||
self.sql.execute("DROP TABLE IF EXISTS Plugins_Language_Strings;")
|
||||
self.sql.execute(""" CREATE TABLE IF NOT EXISTS Plugins_Language_Strings(
|
||||
"Index" INTEGER,
|
||||
Language_Code TEXT NOT NULL,
|
||||
String_Key TEXT NOT NULL,
|
||||
String_Value TEXT NOT NULL,
|
||||
Extra TEXT NOT NULL,
|
||||
PRIMARY KEY("Index" AUTOINCREMENT)
|
||||
"Index" INTEGER,
|
||||
Language_Code TEXT NOT NULL,
|
||||
String_Key TEXT NOT NULL,
|
||||
String_Value TEXT NOT NULL,
|
||||
Extra TEXT NOT NULL,
|
||||
PRIMARY KEY("Index" AUTOINCREMENT)
|
||||
); """)
|
||||
|
||||
self.commitDB()
|
||||
@@ -355,6 +356,9 @@ class DB():
|
||||
);
|
||||
""")
|
||||
|
||||
# Init the AppEvent database table
|
||||
AppEvent_obj(self)
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
# DELETING OBSOLETE TABLES - to remove with updated db file after 1/1/2024
|
||||
# -------------------------------------------------------------------------
|
||||
|
||||
@@ -194,6 +194,8 @@ def create_new_devices (db):
|
||||
'{get_setting_value('NEWDEV_dev_Icon')}'
|
||||
"""
|
||||
|
||||
# Bulk-inserting devices from the CurrentScan table as new devices in the table Devices ...
|
||||
# ... with new device defaults and ignoring specidfied IPs and MACs)
|
||||
sqlQuery = f"""INSERT OR IGNORE INTO Devices (dev_MAC, dev_name, dev_Vendor,
|
||||
dev_LastIP, dev_FirstConnection, dev_LastConnection,
|
||||
{newDevColumns})
|
||||
|
||||
@@ -374,7 +374,7 @@ def execute_plugin(db, plugin, pluginsState = plugins_state() ):
|
||||
pluginsState = process_plugin_events(db, plugin, pluginsState, sqlParams)
|
||||
|
||||
# update API endpoints
|
||||
update_api(db, False, ["plugins_events","plugins_objects", "plugins_history"])
|
||||
update_api(db, False, ["plugins_events","plugins_objects", "plugins_history", "appevents"])
|
||||
|
||||
return pluginsState
|
||||
|
||||
|
||||
Reference in New Issue
Block a user