This commit is contained in:
jokob-sk
2025-03-15 13:19:58 +11:00
parent 9b340532be
commit 1efdf66c19
6 changed files with 302 additions and 402 deletions

View File

@@ -67,7 +67,8 @@ function processData(data) {
{ data: 'ObjectSecondaryID', title: getString('AppEvents_ObjectSecondaryID') },
{ data: 'ObjectStatus', title: getString('AppEvents_ObjectStatus') },
{ data: 'ObjectPlugin', title: getString('AppEvents_Plugin') },
{ data: 'ObjectGUID', title: "GUID" },
{ data: 'ObjectGUID', title: "Object GUID" },
{ data: 'GUID', title: "Event GUID" },
// Add other columns as needed
],
// Add column-specific configurations if needed

View File

@@ -1849,10 +1849,28 @@ input[readonly] {
padding: 5px;
}
.workflows .section-title
{
padding: 10px;
font-weight: bolder;
font-size: large;
}
.workflows .panel, .workflows .box {
padding-top: 10px;
padding-bottom: 10px;
}
.workflows .btn-secondary{
color: #000;
}
.workflows .bottom-buttons button
{
margin: 5px;
}
.workflows .condition-list button
{
margin: 2px;

View File

@@ -40,7 +40,7 @@
}
]
},
"default_value": 5000,
"default_value": 100,
"options": [],
"localized": ["name", "description"],
"name": [

View File

@@ -10,21 +10,20 @@
<div id="workflowContainer"></div>
</div>
<div id="buttons" class="buttons col-sm-12">
<div class="add-workflow col-sm-6">
<button type="button" class="btn btn-primary btn-default pa-btn bg-green" id="save" onclick="addWorkflow()">
<div id="buttons" class="bottom-buttons col-sm-12">
<div class="add-workflow col-sm-12">
<button type="button" class="btn btn-primary add-workflow-btn col-sm-12" id="save">
<?= lang('Gen_Add');?>
</button>
</div>
<div class="save-workflows col-sm-6">
<button type="button" class="btn btn-primary btn-default pa-btn bg-green" id="save" onclick="saveWorkflows()">
<div class="save-workflows col-sm-12">
<button type="button" class="btn btn-primary col-sm-12" id="save" onclick="saveWorkflows()">
<?= lang('DevDetail_button_Save');?>
</button>
</div>
</div>
</section>
<script>
let workflows = [];
@@ -142,12 +141,18 @@ function generateWorkflowUI(wf, wfIndex) {
$wfCollapsiblePanel.append($wfNameInput)
let $triggerTitle = $("<div>",
{
class:"section-title"
}
).text("Trigger:")
// Trigger Section with dropdowns
let $triggerSection = $("<div>",
{
class: "condition-list box box-secondary"
}
).append("<strong>Trigger:</strong> ");
).append($triggerTitle);
let $triggerTypeDropdown = createEditableDropdown(
`[${wfIndex}].trigger.object_type`,
@@ -170,22 +175,36 @@ function generateWorkflowUI(wf, wfIndex) {
$wfCollapsiblePanel.append($triggerSection);
// Conditions
let $conditionsContainer = $("<div>").append("<strong>Conditions:</strong>");
let $conditionsTitle = $("<div>",
{
class:"section-title"
}
).text("Conditions:")
let $conditionsContainer = $("<div>").append($conditionsTitle);
$conditionsContainer.append(renderConditions(wfIndex, `[${wfIndex}]`, 0, wf.conditions));
$wfCollapsiblePanel.append($conditionsContainer);
let $actionsTitle = $("<div>",
{
class:"section-title"
}
).text("Actions:")
// Actions with action.field as dropdown
let $actionsContainer = $("<div>",
{
class: "actions-list box box-secondary"
}
).append("<strong>Actions:</strong>");
).append($actionsTitle);
lastActionIndex = 0
$.each(wf.actions, function (actionIndex, action) {
let $actionEl = $("<div>");
let $actionEl = $("<div>", {
class: "panel"
});
// Dropdown for action.field
let $fieldDropdown = createEditableDropdown(
@@ -220,30 +239,60 @@ function generateWorkflowUI(wf, wfIndex) {
$actionEl.append($fieldDropdown);
$actionEl.append($actionValueInput);
// add actions group button
let $actionRemoveButton = $("<button>", {
class : "btn btn-secondary remove-action",
actionIndex : actionIndex,
wfIndex: wfIndex
}).text("Remove Action")
// Actions
$actionEl.append($actionRemoveButton);
let $actionRemoveButtonWrap = $("<div>", { class: "button-container col-sm-12 col-sx-12" });
let $actionRemoveIcon = $("<i>", {
class: "fa-solid fa-minus"
});
let $actionRemoveButton = $("<button>", {
class: "btn btn-secondary remove-action btn-orange",
actionIndex: actionIndex,
wfIndex: wfIndex
})
.append($actionRemoveIcon) // Add icon
.append("Remove Action"); // Add text
$actionRemoveButtonWrap.append($actionRemoveButton);
$actionEl.append($actionRemoveButtonWrap);
$actionsContainer.append($actionEl);
lastActionIndex = actionIndex
});
// add actions group button
// add action button
let $actionAddIcon = $("<i>", {
class: "fa-solid fa-plus"
});
let $actionAddButton = $("<button>", {
class : "btn btn-secondary add-action",
lastActionIndex : lastActionIndex,
wfIndex: wfIndex
}).text("Add Action")
}).append($actionAddIcon).append("Add Action")
$actionsContainer.append($actionAddButton)
let $wfRemoveButtonWrap = $("<div>", { class: "button-container col-sm-12 col-sx-12" });
let $wfRemoveIcon = $("<i>", {
class: "fa-solid fa-trash"
});
let $wfRemoveButton = $("<button>", {
class: "btn btn-secondary remove-wf",
wfIndex: wfIndex
})
.append($wfRemoveIcon) // Add icon
.append("Remove Workflow"); // Add text
$wfCollapsiblePanel.append($actionsContainer);
$wfCollapsiblePanel.append($wfRemoveButtonWrap.append($wfRemoveButton))
$wfContainer.append($wfCollapsiblePanel)
return $wfContainer;
@@ -327,12 +376,15 @@ function renderConditions(wfIndex, parentIndexPath, conditionGroupsIndex, condit
$conditionItem.append($editableInput); // Append editable input for condition value
let $conditionRemoveButtonWrap = $("<div>", { class: "button-container col-sm-12 col-sx-12" });
let $conditionRemoveButtonIcon = $("<i>", {
class: "fa-solid fa-minus"
});
let $conditionRemoveButton = $("<button>", {
class : "btn btn-secondary remove-condition",
lastConditionIndex : lastConditionIndex,
wfIndex: wfIndex,
parentIndexPath: parentIndexPath
}).text("Remove Condition")
}).append($conditionRemoveButtonIcon).append("Remove Condition")
$conditionRemoveButtonWrap .append($conditionRemoveButton);
$conditionItem.append($conditionRemoveButtonWrap);
@@ -350,22 +402,28 @@ function renderConditions(wfIndex, parentIndexPath, conditionGroupsIndex, condit
if (conditionGroupsIndex != 0) {
// Add Condition button
let $conditionAddWrap = $("<div>", { class: "button-container col-sm-6 col-sx-12" });
let $conditionAddIcon = $("<i>", {
class: "fa-solid fa-plus"
});
let $conditionAddButton = $("<button>", {
class: "btn btn-secondary add-condition col-sx-12",
lastConditionIndex: lastConditionIndex,
wfIndex: wfIndex,
parentIndexPath: parentIndexPath
}).text("Add Condition");
}).append($conditionAddIcon).append("Add Condition");
$conditionAddWrap.append($conditionAddButton);
// Remove Condition Group button
let $conditionGroupRemoveWrap = $("<div>", { class: "button-container col-sm-6 col-sx-12" });
let $conditionGroupRemoveIcon = $("<i>", {
class: "fa-solid fa-trash"
});
let $conditionGroupRemoveButton = $("<button>", {
class: "btn btn-secondary remove-condition-group col-sx-12",
lastConditionIndex: lastConditionIndex,
wfIndex: wfIndex,
parentIndexPath: parentIndexPath
}).text("Remove Condition Group");
}).append($conditionGroupRemoveIcon).append("Remove Condition Group");
$conditionGroupRemoveWrap.append($conditionGroupRemoveButton);
$buttonWrap.append($conditionAddWrap);
@@ -374,11 +432,14 @@ function renderConditions(wfIndex, parentIndexPath, conditionGroupsIndex, condit
// Add Condition Group button
let $conditionsGroupAddWrap = $("<div>", { class: "button-container col-sm-12 col-sx-12" });
let $conditionsGroupAddIcon = $("<i>", {
class: "fa-solid fa-plus"
});
let $conditionsGroupAddButton = $("<button>", {
class: "btn btn-secondary add-condition-group col-sx-12",
wfIndex: wfIndex,
parentIndexPath: parentIndexPath
}).text("Add Condition Group");
}).append($conditionsGroupAddIcon).append("Add Condition Group");
$conditionsGroupAddWrap.append($conditionsGroupAddButton);
$buttonWrap.append($conditionsGroupAddWrap);
@@ -571,6 +632,48 @@ function parsePath(path) {
// Buttons functionality
// ---------------------------------------------------
// ---------------------------------------------------
// Function to add a new Workflow
function addWorkflow() {
workflows.push({
"name": "New Workflow",
"trigger": {
"object_type": "Devices",
"event_type": "create"
},
"conditions": [
],
"actions": [
]
}
);
// // Ensure the workflows object is updated in memory
// workflows = workflows;
// Update the cache with the modified workflows object
setCache("workflows", JSON.stringify(workflows));
// Re-render the UI
renderWorkflows();
}
// ---------------------------------------------------
// Function to remove a Workflow
function removeWorkflow(wfIndex) {
workflows.splice(wfIndex, 1);
// // Ensure the workflows object is updated in memory
// workflows = workflows;
// Update the cache with the modified workflows object
setCache("workflows", JSON.stringify(workflows));
// Re-render the UI
renderWorkflows();
}
// ---------------------------------------------------
// Function to add a new condition
function addCondition(wfIndex, parentIndexPath) {
@@ -593,10 +696,10 @@ function addCondition(wfIndex, parentIndexPath) {
value: "" // Default empty value
});
// 🔥 Ensure the workflows object is updated in memory
// Ensure the workflows object is updated in memory
workflows[wfIndex] = { ...workflows[wfIndex] };
// 🔥 Update the cache with the modified workflows object
// Update the cache with the modified workflows object
setCache("workflows", JSON.stringify(workflows));
// Re-render the UI
@@ -624,10 +727,10 @@ function addConditionGroup(wfIndex, parentIndexPath) {
conditions: []
});
// 🔥 Ensure the workflows object is updated in memory
// Ensure the workflows object is updated in memory
workflows[wfIndex] = { ...workflows[wfIndex] };
// 🔥 Update the cache with the modified workflows object
// Update the cache with the modified workflows object
setCache("workflows", JSON.stringify(workflows));
// Re-render the UI
@@ -662,10 +765,10 @@ function removeCondition(wfIndex, parentIndexPath, lastConditionIndex) {
// Remove the specified condition
target.conditions.splice(lastConditionIndex, 1);
// 🔥 Ensure the workflows object is updated in memory
// Ensure the workflows object is updated in memory
workflows[wfIndex] = { ...workflows[wfIndex] };
// 🔥 Update the cache with the modified workflows object
// Update the cache with the modified workflows object
setCache("workflows", JSON.stringify(workflows));
// Re-render the UI
@@ -675,27 +778,27 @@ function removeCondition(wfIndex, parentIndexPath, lastConditionIndex) {
function removeAction(wfIndex, actionIndex) {
if (!actionIndex || actionIndex === undefined) return;
// // Navigate to the target nested object
// let target = getNestedObject(workflows, parentIndexPath);
// Navigate to the target nested object
let target = getNestedObject(workflows, wfIndex);
// console.log("Target before removal:", target);
console.log("Target before removal:", target);
// if (!target || !Array.isArray(target.conditions)) {
// console.error("❌ Invalid path or conditions array missing:", parentIndexPath);
// return;
// }
if (!target || !Array.isArray(target.actions)) {
console.error("❌ Invalid path or conditions array missing:", actionIndex);
return;
}
// // Remove the specified condition
// target.conditions.splice(lastConditionIndex, 1);
// Remove the specified condition
target.actions.splice(actionIndex, 1);
// // 🔥 Ensure the workflows object is updated in memory
// workflows[wfIndex] = { ...workflows[wfIndex] };
// Ensure the workflows object is updated in memory
workflows[wfIndex] = { ...workflows[wfIndex] };
// // 🔥 Update the cache with the modified workflows object
// setCache("workflows", JSON.stringify(workflows));
// Update the cache with the modified workflows object
setCache("workflows", JSON.stringify(workflows));
// // Re-render the UI
// renderWorkflows();
// Re-render the UI
renderWorkflows();
}
function removeConditionGroup(wfIndex, parentIndexPath) {
@@ -726,10 +829,10 @@ function removeConditionGroup(wfIndex, parentIndexPath) {
// Remove the specified condition group
delete target.conditions.splice(lastIndex, 1);
// 🔥 Ensure the workflows object is updated in memory
// Ensure the workflows object is updated in memory
workflows[wfIndex] = { ...workflows[wfIndex] };
// 🔥 Update the cache with the modified workflows object
// Update the cache with the modified workflows object
setCache("workflows", JSON.stringify(workflows));
// Re-render the UI
@@ -759,6 +862,15 @@ function getNestedObject(obj, path) {
// ---------------------------------------------------
// Event listeners
$(document).on("click", ".add-workflow-btn", function () {
addWorkflow();
});
$(document).on("click", ".remove-wf", function () {
let wfIndex = $(this).attr("wfindex");
removeWorkflow(wfIndex);
});
$(document).on("click", ".add-condition", function () {
let wfIndex = $(this).attr("wfindex");
let parentIndexPath = $(this).attr("parentIndexPath");

View File

@@ -627,7 +627,8 @@ def process_plugin_events(db, plugin, plugEventsArr):
("Plugin", "Object_PrimaryID", "Object_SecondaryID", "DateTimeCreated",
"DateTimeChanged", "Watched_Value1", "Watched_Value2", "Watched_Value3",
"Watched_Value4", "Status", "Extra", "UserData", "ForeignKey", "SyncHubNodeName",
"HelpVal1", "HelpVal2", "HelpVal3", "HelpVal4", "ObjectGUID")
"HelpVal1", "HelpVal2", "HelpVal3", "HelpVal4",
"ObjectGUID")
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
""", objects_to_insert
)
@@ -639,7 +640,8 @@ def process_plugin_events(db, plugin, plugEventsArr):
UPDATE Plugins_Objects
SET "Plugin" = ?, "Object_PrimaryID" = ?, "Object_SecondaryID" = ?, "DateTimeCreated" = ?,
"DateTimeChanged" = ?, "Watched_Value1" = ?, "Watched_Value2" = ?, "Watched_Value3" = ?,
"Watched_Value4" = ?, "Status" = ?, "Extra" = ?, "UserData" = ?, "ForeignKey" = ?, "SyncHubNodeName" = ?, "HelpVal1" = ?, "HelpVal2" = ?, "HelpVal3" = ?, "HelpVal4" = ?,
"Watched_Value4" = ?, "Status" = ?, "Extra" = ?, "UserData" = ?, "ForeignKey" = ?, "SyncHubNodeName" = ?,
"HelpVal1" = ?, "HelpVal2" = ?, "HelpVal3" = ?, "HelpVal4" = ?,
"ObjectGUID" = ?
WHERE "Index" = ?
""", objects_to_update

View File

@@ -22,57 +22,120 @@ Logger(get_setting_value('LOG_LEVEL'))
from const import applicationPath, logPath, apiPath, confFileName, sql_generateGuid
from helper import timeNowTZ
#-------------------------------------------------------------------------------
# Execution object handling
#-------------------------------------------------------------------------------
class AppEvent_obj:
def __init__(self, db):
self.db = db
# drop table
# Drop existing 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;')
self.drop_all_triggers()
# Create the AppEvents table if missing
self.create_app_events_table()
self.db.sql.execute('DROP TRIGGER IF EXISTS trg_delete_plugin_object;')
self.db.sql.execute('DROP TRIGGER IF EXISTS trg_create_plugin_object;')
self.db.sql.execute('DROP TRIGGER IF EXISTS trg_update_plugin_object;')
# Define object mapping for different table structures, including fields, expressions, and constants
self.object_mapping = {
"Devices": {
"fields": {
"ObjectGUID": "NEW.devGUID",
"ObjectPrimaryID": "NEW.devMac",
"ObjectSecondaryID": "NEW.devLastIP",
"ObjectForeignKey": "NEW.devGUID",
"ObjectStatus": "CASE WHEN NEW.devPresentLastScan = 1 THEN 'online' ELSE 'offline' END",
"ObjectStatusColumn": "'devPresentLastScan'",
"ObjectIsNew": "NEW.devIsNew",
"ObjectIsArchived": "NEW.devIsArchived",
"ObjectPlugin": "'DEVICES'"
}
},
"Plugins_Objects": {
"fields": {
"ObjectGUID": "NEW.ObjectGUID",
"ObjectPrimaryID": "NEW.Plugin",
"ObjectSecondaryID": "NEW.Object_PrimaryID",
"ObjectForeignKey": "NEW.ForeignKey",
"ObjectStatus": "NEW.Status",
"ObjectStatusColumn": "'Status'",
"ObjectIsNew": "CASE WHEN NEW.Status = 'new' THEN 1 ELSE 0 END",
"ObjectIsArchived": "0", # Default value
"ObjectPlugin": "NEW.Plugin"
}
}
}
# Create AppEvent table if missing
self.db.sql.execute("""CREATE TABLE IF NOT EXISTS "AppEvents" (
"Index" INTEGER,
"GUID" TEXT UNIQUE,
"AppEventProcessed" BOOLEAN,
"DateTimeCreated" TEXT,
"ObjectType" TEXT, -- ObjectType (Plugins, Notifications, Events)
"ObjectGUID" TEXT,
"ObjectPlugin" TEXT,
"ObjectPrimaryID" TEXT,
"ObjectSecondaryID" TEXT,
"ObjectForeignKey" 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>
"AppEventType" TEXT, -- "create", "update", "delete" (+TBD)
"Helper1" TEXT,
"Helper2" TEXT,
"Helper3" TEXT,
"Extra" TEXT,
PRIMARY KEY("Index" AUTOINCREMENT)
);
# Re-Create triggers dynamically
for table, config in self.object_mapping.items():
self.create_trigger(table, "insert", config)
self.create_trigger(table, "update", config)
self.create_trigger(table, "delete", config)
self.save()
def drop_all_triggers(self):
"""Drops all relevant triggers to ensure a clean start."""
self.db.sql.execute("""
SELECT 'DROP TRIGGER IF EXISTS ' || name || ';'
FROM sqlite_master
WHERE type = 'trigger';
""")
# -------------
# Device events
# Fetch all drop statements
drop_statements = self.db.sql.fetchall()
sql_devices_mappedColumns = '''
# Execute each drop statement
for statement in drop_statements:
self.db.sql.execute(statement[0])
self.save()
def create_app_events_table(self):
"""Creates the AppEvents table if it doesn't exist."""
self.db.sql.execute("""
CREATE TABLE IF NOT EXISTS "AppEvents" (
"Index" INTEGER PRIMARY KEY AUTOINCREMENT,
"GUID" TEXT UNIQUE,
"AppEventProcessed" BOOLEAN,
"DateTimeCreated" TEXT,
"ObjectType" TEXT,
"ObjectGUID" TEXT,
"ObjectPlugin" TEXT,
"ObjectPrimaryID" TEXT,
"ObjectSecondaryID" TEXT,
"ObjectForeignKey" TEXT,
"ObjectIndex" TEXT,
"ObjectIsNew" BOOLEAN,
"ObjectIsArchived" BOOLEAN,
"ObjectStatusColumn" TEXT,
"ObjectStatus" TEXT,
"AppEventType" TEXT,
"Helper1" TEXT,
"Helper2" TEXT,
"Helper3" TEXT,
"Extra" TEXT
);
""")
def create_trigger(self, table_name, event, config):
"""Generic function to create triggers dynamically."""
trigger_name = f"trg_{event}_{table_name.lower()}"
query = f"""
CREATE TRIGGER IF NOT EXISTS "{trigger_name}"
AFTER {event.upper()} ON "{table_name}"
WHEN NOT EXISTS (
SELECT 1 FROM AppEvents
WHERE AppEventProcessed = 0
AND ObjectType = '{table_name}'
AND ObjectGUID = {config['fields']['ObjectGUID']}
AND ObjectStatus = {config['fields']['ObjectStatus']}
AND AppEventType = '{event.lower()}'
)
BEGIN
INSERT INTO "AppEvents" (
"GUID",
"DateTimeCreated",
"AppEventProcessed",
@@ -85,328 +148,32 @@ class AppEvent_obj:
"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_devices_mappedColumns}
)
VALUES (
{sql_generateGuid},
DATETIME('now'),
FALSE,
'Devices',
NEW.devGUID,
NEW.devMac,
NEW.devLastIP,
CASE WHEN NEW.devPresentLastScan = 1 THEN 'online' ELSE 'offline' END,
'devPresentLastScan',
NEW.devIsNew,
NEW.devIsArchived,
NEW.devMac,
'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_devices_mappedColumns}
)
VALUES (
{sql_generateGuid},
DATETIME('now'),
FALSE,
'Devices',
NEW.devGUID,
NEW.devMac,
NEW.devLastIP,
CASE WHEN NEW.devPresentLastScan = 1 THEN 'online' ELSE 'offline' END,
'devPresentLastScan',
NEW.devIsNew,
NEW.devIsArchived,
NEW.devMac,
'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_devices_mappedColumns}
)
VALUES (
{sql_generateGuid},
DATETIME('now'),
FALSE,
'Devices',
OLD.devGUID,
OLD.devMac,
OLD.devLastIP,
CASE WHEN OLD.devPresentLastScan = 1 THEN 'online' ELSE 'offline' END,
'devPresentLastScan',
OLD.devIsNew,
OLD.devIsArchived,
OLD.devMac,
'delete'
);
END;
''')
# -------------
# Plugins_Objects events
sql_plugins_objects_mappedColumns = '''
"GUID",
"DateTimeCreated",
"AppEventProcessed",
"ObjectType",
"ObjectGUID",
"ObjectPlugin",
"ObjectPrimaryID",
"ObjectSecondaryID",
"ObjectForeignKey",
"ObjectStatusColumn",
"ObjectStatus",
"AppEventType"
'''
# Create trigger for update event on Plugins_Objects
self.db.sql.execute(f'''
CREATE TRIGGER IF NOT EXISTS trg_update_plugin_object
AFTER UPDATE ON Plugins_Objects
BEGIN
INSERT INTO AppEvents (
{sql_plugins_objects_mappedColumns}
)
VALUES (
{sql_generateGuid},
DATETIME('now'),
FALSE,
'Plugins_Objects',
NEW.ObjectGUID,
NEW.Plugin,
NEW.Object_PrimaryID,
NEW.Object_SecondaryID,
NEW.ForeignKey,
'Status',
NEW.Status,
'update'
{sql_generateGuid},
DATETIME('now'),
FALSE,
'{table_name}',
{config['fields']['ObjectGUID']}, -- ObjectGUID
{config['fields']['ObjectPrimaryID']}, -- ObjectPrimaryID
{config['fields']['ObjectSecondaryID']}, -- ObjectSecondaryID
{config['fields']['ObjectStatus']}, -- ObjectStatus
{config['fields']['ObjectStatusColumn']}, -- ObjectStatusColumn
{config['fields']['ObjectIsNew']}, -- ObjectIsNew
{config['fields']['ObjectIsArchived']}, -- ObjectIsArchived
{config['fields']['ObjectForeignKey']}, -- ObjectForeignKey
{config['fields']['ObjectPlugin']}, -- ObjectForeignKey
'{event.lower()}'
);
END;
''')
"""
# Create trigger for CREATE event on Plugins_Objects
self.db.sql.execute(f'''
CREATE TRIGGER IF NOT EXISTS trg_create_plugin_object
AFTER INSERT ON Plugins_Objects
BEGIN
INSERT INTO AppEvents (
{sql_plugins_objects_mappedColumns}
)
VALUES (
{sql_generateGuid},
DATETIME('now'),
FALSE,
'Plugins_Objects',
NEW.ObjectGUID,
NEW.Plugin,
NEW.Object_PrimaryID,
NEW.Object_SecondaryID,
NEW.ForeignKey,
'Status',
NEW.Status,
'create'
);
END;
''')
mylog("verbose", [query])
# Create trigger for DELETE event on Plugins_Objects
self.db.sql.execute(f'''
CREATE TRIGGER IF NOT EXISTS trg_delete_plugin_object
AFTER DELETE ON Plugins_Objects
BEGIN
INSERT INTO AppEvents (
{sql_plugins_objects_mappedColumns}
)
VALUES (
{sql_generateGuid},
DATETIME('now'),
FALSE,
'Plugins_Objects',
OLD.ObjectGUID,
OLD.Plugin,
OLD.Object_PrimaryID,
OLD.Object_SecondaryID,
OLD.ForeignKey,
'Status',
OLD.Status,
'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
if not any(kwargs.values()):
return False
# Continue and save into DB if notifications are available
self.GUID = str(uuid.uuid4())
self.DateTimeCreated = timeNowTZ()
self.ObjectType = "Plugins" # Modify ObjectType as needed
# Optional parameters
self.ObjectGUID = kwargs.get("ObjectGUID", "")
self.ObjectPlugin = kwargs.get("ObjectPlugin", "")
self.ObjectMAC = kwargs.get("ObjectMAC", "")
self.ObjectIP = kwargs.get("ObjectIP", "")
self.ObjectPrimaryID = kwargs.get("ObjectPrimaryID", "")
self.ObjectSecondaryID = kwargs.get("ObjectSecondaryID", "")
self.ObjectForeignKey = kwargs.get("ObjectForeignKey", "")
self.ObjectIndex = kwargs.get("ObjectIndex", "")
self.ObjectRowID = kwargs.get("ObjectRowID", "")
self.ObjectStatusColumn = kwargs.get("ObjectStatusColumn", "")
self.ObjectStatus = kwargs.get("ObjectStatus", "")
self.AppEventStatus = "new" # Modify AppEventStatus as needed
self.Extra = Extra
self.upsert()
return True
def upsert(self):
self.db.sql.execute("""
INSERT OR REPLACE INTO AppEvents (
"GUID",
"DateTimeCreated",
"ObjectType",
"ObjectGUID",
"ObjectPlugin",
"ObjectMAC",
"ObjectIP",
"ObjectPrimaryID",
"ObjectSecondaryID",
"ObjectForeignKey",
"ObjectIndex",
"ObjectRowID",
"ObjectStatusColumn",
"ObjectStatus",
"AppEventStatus",
"Extra"
)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
""", (
self.GUID,
self.DateTimeCreated,
self.ObjectType,
self.ObjectGUID,
self.ObjectPlugin,
self.ObjectMAC,
self.ObjectIP,
self.ObjectPrimaryID,
self.ObjectSecondaryID,
self.ObjectForeignKey,
self.ObjectIndex,
self.ObjectRowID,
self.ObjectStatusColumn,
self.ObjectStatus,
self.AppEventStatus,
self.Extra
))
self.save()
self.db.sql.execute(query)
def save(self):
# Commit changes
self.db.commitDB()
def getPluginObject(**kwargs):
# Check if nothing, end
if not any(kwargs.values()):
return None
# Optional parameters
GUID = kwargs.get("GUID", "")
Plugin = kwargs.get("Plugin", "")
MAC = kwargs.get("MAC", "")
IP = kwargs.get("IP", "")
PrimaryID = kwargs.get("PrimaryID", "")
SecondaryID = kwargs.get("SecondaryID", "")
ForeignKey = kwargs.get("ForeignKey", "")
Index = kwargs.get("Index", "")
RowID = kwargs.get("RowID", "")
# we need the plugin
if Plugin == "":
return None
plugins_objects = apiPath + 'table_plugins_objects.json'
try:
with open(plugins_objects, 'r') as json_file:
data = json.load(json_file)
for item in data.get("data",[]):
if item.get("Index") == Index:
return item
for item in data.get("data",[]):
if item.get("ObjectPrimaryID") == PrimaryID and item.get("ObjectSecondaryID") == SecondaryID:
return item
for item in data.get("data",[]):
if item.get("ObjectPrimaryID") == MAC and item.get("ObjectSecondaryID") == IP:
return item
for item in data.get("data",[]):
if item.get("ObjectPrimaryID") == PrimaryID and item.get("ObjectSecondaryID") == IP:
return item
for item in data.get("data",[]):
if item.get("ObjectPrimaryID") == MAC and item.get("ObjectSecondaryID") == IP:
return item
mylog('debug', [f'[{module_name}] ⚠ ERROR - Object not found - GUID:{GUID} | Plugin:{Plugin} | MAC:{MAC} | IP:{IP} | PrimaryID:{PrimaryID} | SecondaryID:{SecondaryID} | ForeignKey:{ForeignKey} | Index:{Index} | RowID:{RowID} '])
return None
except (FileNotFoundError, json.JSONDecodeError, ValueError) as e:
# Handle the case when the file is not found, JSON decoding fails, or data is not in the expected format
mylog('none', [f'[{module_name}] ⚠ ERROR - JSONDecodeError or FileNotFoundError for file {plugins_objects}'])
return None