mirror of
https://github.com/jokob-sk/NetAlertX.git
synced 2026-04-15 22:51:37 -07:00
BE/PLG: TZ timestamp work #1251
Signed-off-by: jokob-sk <jokob.sk@gmail.com>
This commit is contained in:
@@ -8,7 +8,6 @@ import sys
|
|||||||
import re
|
import re
|
||||||
import base64
|
import base64
|
||||||
import subprocess
|
import subprocess
|
||||||
from time import strftime
|
|
||||||
|
|
||||||
# Register NetAlertX directories
|
# Register NetAlertX directories
|
||||||
INSTALL_PATH="/app"
|
INSTALL_PATH="/app"
|
||||||
|
|||||||
@@ -44,8 +44,11 @@ def main():
|
|||||||
nmapArgs = ['sudo', 'nmap', '--privileged', '--script', 'broadcast-dhcp-discover']
|
nmapArgs = ['sudo', 'nmap', '--privileged', '--script', 'broadcast-dhcp-discover']
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
# Number of DHCP discovery probes to send
|
||||||
dhcp_probes = 1
|
dhcp_probes = 1
|
||||||
newLines = [datetime.now().strftime("%Y-%m-%d %H:%M:%S")]
|
|
||||||
|
# Initialize a list to store output lines from the scan
|
||||||
|
newLines = []
|
||||||
|
|
||||||
for _ in range(dhcp_probes):
|
for _ in range(dhcp_probes):
|
||||||
output = subprocess.check_output(nmapArgs, universal_newlines=True, stderr=subprocess.STDOUT, timeout=timeoutSec)
|
output = subprocess.check_output(nmapArgs, universal_newlines=True, stderr=subprocess.STDOUT, timeout=timeoutSec)
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ import sys
|
|||||||
import re
|
import re
|
||||||
import base64
|
import base64
|
||||||
import subprocess
|
import subprocess
|
||||||
from time import strftime
|
|
||||||
|
|
||||||
# Register NetAlertX directories
|
# Register NetAlertX directories
|
||||||
INSTALL_PATH="/app"
|
INSTALL_PATH="/app"
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
from time import strftime
|
|
||||||
import pytz
|
import pytz
|
||||||
from pytz import timezone, all_timezones, UnknownTimeZoneError
|
from pytz import timezone, all_timezones, UnknownTimeZoneError
|
||||||
import sys
|
import sys
|
||||||
@@ -205,7 +204,7 @@ class Plugin_Object:
|
|||||||
self.pluginPref = ""
|
self.pluginPref = ""
|
||||||
self.primaryId = primaryId
|
self.primaryId = primaryId
|
||||||
self.secondaryId = secondaryId
|
self.secondaryId = secondaryId
|
||||||
self.created = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
self.created = datetime.now().astimezone().isoformat()
|
||||||
self.changed = ""
|
self.changed = ""
|
||||||
self.watched1 = watched1
|
self.watched1 = watched1
|
||||||
self.watched2 = watched2
|
self.watched2 = watched2
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ INSTALL_PATH="/app"
|
|||||||
sys.path.extend([f"{INSTALL_PATH}/front/plugins", f"{INSTALL_PATH}/server"])
|
sys.path.extend([f"{INSTALL_PATH}/front/plugins", f"{INSTALL_PATH}/server"])
|
||||||
|
|
||||||
from database import get_temp_db_connection
|
from database import get_temp_db_connection
|
||||||
from helper import is_random_mac, format_date, get_setting_value
|
from helper import is_random_mac, format_date, get_setting_value, timeNowTZ
|
||||||
from db.db_helper import row_to_json, get_date_from_period
|
from db.db_helper import row_to_json, get_date_from_period
|
||||||
|
|
||||||
# --------------------------
|
# --------------------------
|
||||||
@@ -30,7 +30,7 @@ def get_device_data(mac):
|
|||||||
|
|
||||||
# Special case for new device
|
# Special case for new device
|
||||||
if mac.lower() == "new":
|
if mac.lower() == "new":
|
||||||
now = datetime.now().strftime("%Y-%m-%d %H:%M")
|
now = timeNowTZ().astimezone().isoformat()
|
||||||
device_data = {
|
device_data = {
|
||||||
"devMac": "",
|
"devMac": "",
|
||||||
"devName": "",
|
"devName": "",
|
||||||
@@ -78,7 +78,6 @@ def get_device_data(mac):
|
|||||||
# Compute period date for sessions/events
|
# Compute period date for sessions/events
|
||||||
period = request.args.get('period', '') # e.g., '7 days', '1 month', etc.
|
period = request.args.get('period', '') # e.g., '7 days', '1 month', etc.
|
||||||
period_date_sql = get_date_from_period(period)
|
period_date_sql = get_date_from_period(period)
|
||||||
current_date = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
|
||||||
|
|
||||||
# Fetch device info + computed fields
|
# Fetch device info + computed fields
|
||||||
sql = f"""
|
sql = f"""
|
||||||
@@ -106,7 +105,7 @@ def get_device_data(mac):
|
|||||||
AND eve_EventType = 'Device Down') AS devDownAlerts,
|
AND eve_EventType = 'Device Down') AS devDownAlerts,
|
||||||
|
|
||||||
(SELECT CAST(MAX(0, SUM(
|
(SELECT CAST(MAX(0, SUM(
|
||||||
julianday(IFNULL(ses_DateTimeDisconnection,'{current_date}')) -
|
julianday(IFNULL(ses_DateTimeDisconnection,'{now}')) -
|
||||||
julianday(CASE WHEN ses_DateTimeConnection < {period_date_sql}
|
julianday(CASE WHEN ses_DateTimeConnection < {period_date_sql}
|
||||||
THEN {period_date_sql} ELSE ses_DateTimeConnection END)
|
THEN {period_date_sql} ELSE ses_DateTimeConnection END)
|
||||||
) * 24) AS INT)
|
) * 24) AS INT)
|
||||||
@@ -186,8 +185,8 @@ def set_device_data(mac, data):
|
|||||||
data.get("devSkipRepeated", 0),
|
data.get("devSkipRepeated", 0),
|
||||||
data.get("devIsNew", 0),
|
data.get("devIsNew", 0),
|
||||||
data.get("devIsArchived", 0),
|
data.get("devIsArchived", 0),
|
||||||
data.get("devLastConnection", datetime.now().strftime("%Y-%m-%d %H:%M:%S")),
|
data.get("devLastConnection", timeNowTZ().astimezone().isoformat()),
|
||||||
data.get("devFirstConnection", datetime.now().strftime("%Y-%m-%d %H:%M:%S")),
|
data.get("devFirstConnection", timeNowTZ().astimezone().isoformat()),
|
||||||
data.get("devLastIP", ""),
|
data.get("devLastIP", ""),
|
||||||
data.get("devGUID", ""),
|
data.get("devGUID", ""),
|
||||||
data.get("devCustomProps", ""),
|
data.get("devCustomProps", ""),
|
||||||
|
|||||||
+1
-1
@@ -59,7 +59,7 @@ class app_state_class:
|
|||||||
previousState = ""
|
previousState = ""
|
||||||
|
|
||||||
# Update self
|
# Update self
|
||||||
self.lastUpdated = str(timeNowTZ())
|
self.lastUpdated = str(timeNowTZ().astimezone().isoformat())
|
||||||
|
|
||||||
if os.path.exists(stateFile):
|
if os.path.exists(stateFile):
|
||||||
try:
|
try:
|
||||||
|
|||||||
@@ -58,25 +58,6 @@ def get_timezone_offset():
|
|||||||
# Date and time methods
|
# Date and time methods
|
||||||
#-------------------------------------------------------------------------------
|
#-------------------------------------------------------------------------------
|
||||||
|
|
||||||
# # -------------------------------------------------------------------------------------------
|
|
||||||
# def format_date(date_str: str) -> str:
|
|
||||||
# """Format a date string as 'YYYY-MM-DD HH:MM'"""
|
|
||||||
# dt = datetime.datetime.fromisoformat(date_str) if isinstance(date_str, str) else date_str
|
|
||||||
# return dt.strftime('%Y-%m-%d %H:%M')
|
|
||||||
|
|
||||||
# # -------------------------------------------------------------------------------------------
|
|
||||||
# def format_date_diff(date1: str, date2: str) -> str:
|
|
||||||
# """Return difference between two dates formatted as 'Xd HH:MM'"""
|
|
||||||
# dt1 = datetime.datetime.fromisoformat(date1) if isinstance(date1, str) else date1
|
|
||||||
# dt2 = datetime.datetime.fromisoformat(date2) if isinstance(date2, str) else date2
|
|
||||||
# delta = dt2 - dt1
|
|
||||||
|
|
||||||
# days = delta.days
|
|
||||||
# hours, remainder = divmod(delta.seconds, 3600)
|
|
||||||
# minutes = remainder // 60
|
|
||||||
|
|
||||||
# return f"{days}d {hours:02}:{minutes:02}"
|
|
||||||
|
|
||||||
# -------------------------------------------------------------------------------------------
|
# -------------------------------------------------------------------------------------------
|
||||||
def format_date_iso(date1: str) -> str:
|
def format_date_iso(date1: str) -> str:
|
||||||
"""Return ISO 8601 string for a date or None if empty"""
|
"""Return ISO 8601 string for a date or None if empty"""
|
||||||
|
|||||||
+9
-5
@@ -93,6 +93,9 @@ class plugin_manager:
|
|||||||
|
|
||||||
# Update plugin states in app_state
|
# Update plugin states in app_state
|
||||||
current_plugin_state = self.get_plugin_states(prefix) # get latest plugin state
|
current_plugin_state = self.get_plugin_states(prefix) # get latest plugin state
|
||||||
|
|
||||||
|
# mylog('debug', f'current_plugin_state: {current_plugin_state}')
|
||||||
|
|
||||||
updateState(pluginsStates={prefix: current_plugin_state.get(prefix, {})})
|
updateState(pluginsStates={prefix: current_plugin_state.get(prefix, {})})
|
||||||
|
|
||||||
# update last run time
|
# update last run time
|
||||||
@@ -218,6 +221,7 @@ class plugin_manager:
|
|||||||
"""
|
"""
|
||||||
sql = self.db.sql
|
sql = self.db.sql
|
||||||
plugin_states = {}
|
plugin_states = {}
|
||||||
|
now_str = timeNowTZ().isoformat()
|
||||||
|
|
||||||
if plugin_name: # Only compute for single plugin
|
if plugin_name: # Only compute for single plugin
|
||||||
sql.execute("""
|
sql.execute("""
|
||||||
@@ -228,7 +232,7 @@ class plugin_manager:
|
|||||||
WHERE Plugin = ?
|
WHERE Plugin = ?
|
||||||
""", (plugin_name,))
|
""", (plugin_name,))
|
||||||
row = sql.fetchone()
|
row = sql.fetchone()
|
||||||
last_changed, total_objects, new_objects, state_updated = row if row else ("", 0, 0)
|
last_changed, total_objects, new_objects = row if row else ("", 0, 0)
|
||||||
new_objects = new_objects or 0 # ensure it's int
|
new_objects = new_objects or 0 # ensure it's int
|
||||||
changed_objects = total_objects - new_objects
|
changed_objects = total_objects - new_objects
|
||||||
|
|
||||||
@@ -237,7 +241,7 @@ class plugin_manager:
|
|||||||
"totalObjects": total_objects or 0,
|
"totalObjects": total_objects or 0,
|
||||||
"newObjects": new_objects or 0,
|
"newObjects": new_objects or 0,
|
||||||
"changedObjects": changed_objects or 0,
|
"changedObjects": changed_objects or 0,
|
||||||
"stateUpdated": timeNowTZ()
|
"stateUpdated": now_str
|
||||||
}
|
}
|
||||||
|
|
||||||
# Save in memory
|
# Save in memory
|
||||||
@@ -252,7 +256,7 @@ class plugin_manager:
|
|||||||
FROM Plugins_Objects
|
FROM Plugins_Objects
|
||||||
GROUP BY Plugin
|
GROUP BY Plugin
|
||||||
""")
|
""")
|
||||||
for plugin, last_changed, total_objects, new_objects, state_updated in sql.fetchall():
|
for plugin, last_changed, total_objects, new_objects in sql.fetchall():
|
||||||
new_objects = new_objects or 0 # ensure it's int
|
new_objects = new_objects or 0 # ensure it's int
|
||||||
changed_objects = total_objects - new_objects
|
changed_objects = total_objects - new_objects
|
||||||
plugin_states[plugin] = {
|
plugin_states[plugin] = {
|
||||||
@@ -260,7 +264,7 @@ class plugin_manager:
|
|||||||
"totalObjects": total_objects or 0,
|
"totalObjects": total_objects or 0,
|
||||||
"newObjects": new_objects or 0,
|
"newObjects": new_objects or 0,
|
||||||
"changedObjects": changed_objects or 0,
|
"changedObjects": changed_objects or 0,
|
||||||
"stateUpdated": timeNowTZ()
|
"stateUpdated": now_str
|
||||||
}
|
}
|
||||||
|
|
||||||
# Save in memory
|
# Save in memory
|
||||||
@@ -755,7 +759,7 @@ def process_plugin_events(db, plugin, plugEventsArr):
|
|||||||
if isMissing:
|
if isMissing:
|
||||||
# if wasn't missing before, mark as changed
|
# if wasn't missing before, mark as changed
|
||||||
if tmpObj.status != "missing-in-last-scan":
|
if tmpObj.status != "missing-in-last-scan":
|
||||||
tmpObj.changed = timeNowTZ().strftime('%Y-%m-%d %H:%M:%S')
|
tmpObj.changed = timeNowTZ().astimezone().isoformat()
|
||||||
tmpObj.status = "missing-in-last-scan"
|
tmpObj.status = "missing-in-last-scan"
|
||||||
# mylog('debug', [f'[Plugins] Missing from last scan (PrimaryID | SecondaryID): {tmpObj.primaryId} | {tmpObj.secondaryId}'])
|
# mylog('debug', [f'[Plugins] Missing from last scan (PrimaryID | SecondaryID): {tmpObj.primaryId} | {tmpObj.secondaryId}'])
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import subprocess
|
|||||||
import conf
|
import conf
|
||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
|
import datetime
|
||||||
from dateutil import parser
|
from dateutil import parser
|
||||||
|
|
||||||
# Register NetAlertX directories
|
# Register NetAlertX directories
|
||||||
@@ -55,7 +56,7 @@ def exclude_ignored_devices(db):
|
|||||||
#-------------------------------------------------------------------------------
|
#-------------------------------------------------------------------------------
|
||||||
def update_devices_data_from_scan (db):
|
def update_devices_data_from_scan (db):
|
||||||
sql = db.sql #TO-DO
|
sql = db.sql #TO-DO
|
||||||
startTime = timeNowTZ().strftime('%Y-%m-%d %H:%M:%S')
|
startTime = timeNowTZ().astimezone().isoformat()
|
||||||
|
|
||||||
# Update Last Connection
|
# Update Last Connection
|
||||||
mylog('debug', '[Update Devices] 1 Last Connection')
|
mylog('debug', '[Update Devices] 1 Last Connection')
|
||||||
@@ -528,23 +529,27 @@ def update_devices_names(pm):
|
|||||||
# --- Short-circuit if no name-resolution plugin has changed ---
|
# --- Short-circuit if no name-resolution plugin has changed ---
|
||||||
name_plugins = ["DIGSCAN", "NSLOOKUP", "NBTSCAN", "AVAHISCAN"]
|
name_plugins = ["DIGSCAN", "NSLOOKUP", "NBTSCAN", "AVAHISCAN"]
|
||||||
|
|
||||||
# Retrieve last time name resolution was checked (string or datetime)
|
# Retrieve last time name resolution was checked
|
||||||
last_checked_str = pm.name_plugins_checked
|
last_checked = pm.name_plugins_checked
|
||||||
last_checked_dt = parser.parse(last_checked_str) if isinstance(last_checked_str, str) else last_checked_str
|
|
||||||
|
|
||||||
# Collect valid state update timestamps for name-related plugins
|
# Collect valid state update timestamps for name-related plugins
|
||||||
state_times = []
|
state_times = []
|
||||||
for p in name_plugins:
|
for p in name_plugins:
|
||||||
state_updated = pm.plugin_states.get(p, {}).get("stateUpdated")
|
state_updated = pm.plugin_states.get(p, {}).get("stateUpdated")
|
||||||
if state_updated and state_updated.strip(): # skip empty or None
|
if state_updated: # skip empty or None
|
||||||
state_times.append(state_updated)
|
state_times.append(state_updated)
|
||||||
|
|
||||||
# Determine the latest valid stateUpdated timestamp
|
# Determine the latest valid stateUpdated timestamp
|
||||||
latest_state_str = max(state_times, default=None)
|
latest_state_str = max(state_times, default=None)
|
||||||
latest_state_dt = parser.parse(latest_state_str) if latest_state_str else None
|
if isinstance(latest_state_str, datetime.datetime):
|
||||||
|
latest_state = latest_state_str
|
||||||
|
elif latest_state_str:
|
||||||
|
latest_state = parser.parse(latest_state_str)
|
||||||
|
else:
|
||||||
|
latest_state = None
|
||||||
|
|
||||||
# Skip if no plugin state changed since last check
|
# Skip if no plugin state changed since last check
|
||||||
if last_checked_dt and latest_state_dt and latest_state_dt <= last_checked_dt:
|
if last_checked and latest_state and latest_state <= last_checked:
|
||||||
mylog('debug', '[Update Device Name] No relevant name plugin changes since last check — skipping update.')
|
mylog('debug', '[Update Device Name] No relevant name plugin changes since last check — skipping update.')
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user