mirror of
https://github.com/jokob-sk/NetAlertX.git
synced 2025-12-07 09:36:05 -08:00
170 lines
6.5 KiB
Python
Executable File
170 lines
6.5 KiB
Python
Executable File
import json
|
|
from const import fullConfFolder
|
|
from logger import mylog, Logger
|
|
from helper import get_setting_value
|
|
|
|
from workflows.triggers import Trigger
|
|
from workflows.conditions import ConditionGroup
|
|
from workflows.actions import DeleteObjectAction, RunPluginAction, UpdateFieldAction
|
|
|
|
|
|
# Make sure log level is initialized correctly
|
|
Logger(get_setting_value("LOG_LEVEL"))
|
|
|
|
|
|
class WorkflowManager:
|
|
def __init__(self, db):
|
|
self.db = db
|
|
self.workflows = self.load_workflows()
|
|
self.update_api = False
|
|
|
|
def load_workflows(self):
|
|
"""Load workflows from workflows.json."""
|
|
try:
|
|
workflows_json_path = fullConfFolder + "/workflows.json"
|
|
with open(workflows_json_path, "r") as f:
|
|
workflows = json.load(f)
|
|
return workflows
|
|
except (FileNotFoundError, json.JSONDecodeError):
|
|
mylog("none", ["[WF] Failed to load workflows.json"])
|
|
return []
|
|
|
|
def get_new_app_events(self):
|
|
"""Get new unprocessed events from the AppEvents table."""
|
|
result = self.db.sql.execute("""
|
|
SELECT * FROM AppEvents
|
|
WHERE AppEventProcessed = 0
|
|
ORDER BY DateTimeCreated ASC
|
|
""").fetchall()
|
|
|
|
mylog("none", [f"[WF] get_new_app_events - new events count: {len(result)}"])
|
|
|
|
return result
|
|
|
|
def process_event(self, event):
|
|
"""Process the events. Check if events match a workflow trigger"""
|
|
|
|
evGuid = event["GUID"]
|
|
|
|
mylog("verbose", [f"[WF] Processing event with GUID {evGuid}"])
|
|
|
|
# Check if the trigger conditions match
|
|
for workflow in self.workflows:
|
|
# Ensure workflow is enabled before proceeding
|
|
if workflow.get("enabled", "No").lower() == "yes":
|
|
wfName = workflow["name"]
|
|
mylog(
|
|
"debug",
|
|
[f"[WF] Checking if '{evGuid}' triggers the workflow '{wfName}'"],
|
|
)
|
|
|
|
# construct trigger object which also evaluates if the current event triggers it
|
|
trigger = Trigger(workflow["trigger"], event, self.db)
|
|
|
|
if trigger.triggered:
|
|
mylog(
|
|
"verbose",
|
|
[
|
|
f"[WF] Event with GUID '{evGuid}' triggered the workflow '{wfName}'"
|
|
],
|
|
)
|
|
|
|
self.execute_workflow(workflow, trigger)
|
|
|
|
# After processing the event, mark the event as processed (set AppEventProcessed to 1)
|
|
self.db.sql.execute(
|
|
"""
|
|
UPDATE AppEvents
|
|
SET AppEventProcessed = 1
|
|
WHERE "Index" = ?
|
|
""",
|
|
(event["Index"],),
|
|
) # Pass the event's unique identifier
|
|
self.db.commitDB()
|
|
|
|
def execute_workflow(self, workflow, trigger):
|
|
"""Execute the actions in the given workflow if conditions are met."""
|
|
|
|
wfName = workflow["name"]
|
|
|
|
# Ensure conditions exist
|
|
if not isinstance(workflow.get("conditions"), list):
|
|
m = "[WF] workflow['conditions'] must be a list"
|
|
mylog("none", [m])
|
|
raise ValueError(m)
|
|
|
|
# Evaluate each condition group separately
|
|
for condition_group in workflow["conditions"]:
|
|
evaluator = ConditionGroup(condition_group)
|
|
|
|
if evaluator.evaluate(trigger): # If any group evaluates to True
|
|
mylog(
|
|
"none",
|
|
[
|
|
f"[WF] Workflow {wfName} will be executed - conditions were evaluated as TRUE"
|
|
],
|
|
)
|
|
mylog("debug", [f"[WF] Workflow condition_group: {condition_group}"])
|
|
|
|
self.execute_actions(workflow["actions"], trigger)
|
|
return # Stop if a condition group succeeds
|
|
|
|
mylog("none", ["[WF] No condition group matched. Actions not executed."])
|
|
|
|
def execute_actions(self, actions, trigger):
|
|
"""Execute the actions defined in a workflow."""
|
|
|
|
for action in actions:
|
|
if action["type"] == "update_field":
|
|
field = action["field"]
|
|
value = action["value"]
|
|
action_instance = UpdateFieldAction(self.db, field, value, trigger)
|
|
# indicate if the api has to be updated
|
|
self.update_api = True
|
|
|
|
elif action["type"] == "run_plugin":
|
|
plugin_name = action["plugin"]
|
|
params = action["params"]
|
|
action_instance = RunPluginAction(self.db, plugin_name, params, trigger)
|
|
|
|
elif action["type"] == "delete_device":
|
|
action_instance = DeleteObjectAction(self.db, trigger)
|
|
|
|
# elif action["type"] == "send_notification":
|
|
# method = action["method"]
|
|
# message = action["message"]
|
|
# action_instance = SendNotificationAction(method, message, trigger)
|
|
|
|
else:
|
|
m = f"[WF] Unsupported action type: {action['type']}"
|
|
mylog("none", [m])
|
|
raise ValueError(m)
|
|
|
|
action_instance.execute() # Execute the action
|
|
|
|
# if result:
|
|
# # Iterate through actions and execute them
|
|
# for action in workflow["actions"]:
|
|
# if action["type"] == "update_field":
|
|
# # Action type is "update_field", so map to UpdateFieldAction
|
|
# field = action["field"]
|
|
# value = action["value"]
|
|
# action_instance = UpdateFieldAction(field, value)
|
|
# action_instance.execute(trigger.event)
|
|
|
|
# elif action["type"] == "run_plugin":
|
|
# # Action type is "run_plugin", so map to RunPluginAction
|
|
# plugin_name = action["plugin"]
|
|
# params = action["params"]
|
|
# action_instance = RunPluginAction(plugin_name, params)
|
|
# action_instance.execute(trigger.event)
|
|
# elif action["type"] == "send_notification":
|
|
# # Action type is "send_notification", so map to SendNotificationAction
|
|
# method = action["method"]
|
|
# message = action["message"]
|
|
# action_instance = SendNotificationAction(method, message)
|
|
# action_instance.execute(trigger.event)
|
|
# else:
|
|
# # Handle unsupported action types
|
|
# raise ValueError(f"Unsupported action type: {action['type']}")
|