mirror of
https://github.com/jokob-sk/NetAlertX.git
synced 2025-12-07 09:36:05 -08:00
/data and /tmp standarization
This commit is contained in:
@@ -1,25 +1,20 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
import json
|
||||
import subprocess
|
||||
import argparse
|
||||
import os
|
||||
import pathlib
|
||||
import base64
|
||||
import re
|
||||
import sys
|
||||
from datetime import datetime
|
||||
import sqlite3
|
||||
from flask import jsonify, request, Response
|
||||
import csv
|
||||
import io
|
||||
from io import StringIO
|
||||
from logger import mylog
|
||||
|
||||
# Register NetAlertX directories
|
||||
INSTALL_PATH="/app"
|
||||
INSTALL_PATH = os.getenv("NETALERTX_APP", "/app")
|
||||
sys.path.extend([f"{INSTALL_PATH}/front/plugins", f"{INSTALL_PATH}/server"])
|
||||
|
||||
from database import get_temp_db_connection
|
||||
from helper import is_random_mac, format_date, get_setting_value
|
||||
from db.db_helper import get_table_json, get_device_condition_by_status
|
||||
|
||||
|
||||
@@ -27,6 +22,7 @@ from db.db_helper import get_table_json, get_device_condition_by_status
|
||||
# Device Endpoints Functions
|
||||
# --------------------------
|
||||
|
||||
|
||||
def get_all_devices():
|
||||
"""Retrieve all devices from the database."""
|
||||
conn = get_temp_db_connection()
|
||||
@@ -41,6 +37,7 @@ def get_all_devices():
|
||||
conn.close()
|
||||
return jsonify({"success": True, "devices": devices})
|
||||
|
||||
|
||||
def delete_devices(macs):
|
||||
"""
|
||||
Delete devices from the Devices table.
|
||||
@@ -75,6 +72,7 @@ def delete_devices(macs):
|
||||
|
||||
return jsonify({"success": True, "deleted_count": deleted_count})
|
||||
|
||||
|
||||
def delete_all_with_empty_macs():
|
||||
"""Delete devices with empty MAC addresses."""
|
||||
conn = get_temp_db_connection()
|
||||
@@ -85,15 +83,19 @@ def delete_all_with_empty_macs():
|
||||
conn.close()
|
||||
return jsonify({"success": True, "deleted": deleted})
|
||||
|
||||
|
||||
def delete_unknown_devices():
|
||||
"""Delete devices marked as unknown."""
|
||||
conn = get_temp_db_connection()
|
||||
cur = conn.cursor()
|
||||
cur.execute("""DELETE FROM Devices WHERE devName='(unknown)' OR devName='(name not found)'""")
|
||||
cur.execute(
|
||||
"""DELETE FROM Devices WHERE devName='(unknown)' OR devName='(name not found)'"""
|
||||
)
|
||||
conn.commit()
|
||||
conn.close()
|
||||
return jsonify({"success": True, "deleted": cur.rowcount})
|
||||
|
||||
|
||||
def export_devices(export_format):
|
||||
"""
|
||||
Export devices from the Devices table in teh desired format.
|
||||
@@ -112,15 +114,12 @@ def export_devices(export_format):
|
||||
list(devices_json["data"][0].keys()) if devices_json["data"] else []
|
||||
)
|
||||
|
||||
|
||||
if export_format == "json":
|
||||
# Convert to standard dict for Flask JSON
|
||||
return jsonify({
|
||||
"data": [row for row in devices_json["data"]],
|
||||
"columns": list(columns)
|
||||
})
|
||||
return jsonify(
|
||||
{"data": [row for row in devices_json["data"]], "columns": list(columns)}
|
||||
)
|
||||
elif export_format == "csv":
|
||||
|
||||
si = StringIO()
|
||||
writer = csv.DictWriter(si, fieldnames=columns, quoting=csv.QUOTE_ALL)
|
||||
writer.writeheader()
|
||||
@@ -135,6 +134,7 @@ def export_devices(export_format):
|
||||
else:
|
||||
return jsonify({"error": f"Unsupported format '{export_format}'"}), 400
|
||||
|
||||
|
||||
def import_csv(file_storage=None):
|
||||
data = ""
|
||||
skipped = []
|
||||
@@ -143,7 +143,9 @@ def import_csv(file_storage=None):
|
||||
# 1. Try JSON `content` (base64-encoded CSV)
|
||||
if request.is_json and request.json.get("content"):
|
||||
try:
|
||||
data = base64.b64decode(request.json["content"], validate=True).decode("utf-8")
|
||||
data = base64.b64decode(request.json["content"], validate=True).decode(
|
||||
"utf-8"
|
||||
)
|
||||
except Exception as e:
|
||||
return jsonify({"error": f"Base64 decode failed: {e}"}), 400
|
||||
|
||||
@@ -153,7 +155,8 @@ def import_csv(file_storage=None):
|
||||
|
||||
# 3. Fallback: try local file (same as PHP `$file = '../../../config/devices.csv';`)
|
||||
else:
|
||||
local_file = "/app/config/devices.csv"
|
||||
config_root = os.environ.get("NETALERTX_CONFIG", "/data/config")
|
||||
local_file = os.path.join(config_root, "devices.csv")
|
||||
try:
|
||||
with open(local_file, "r", encoding="utf-8") as f:
|
||||
data = f.read()
|
||||
@@ -164,11 +167,7 @@ def import_csv(file_storage=None):
|
||||
return jsonify({"error": "No CSV data found"}), 400
|
||||
|
||||
# --- Clean up newlines inside quoted fields ---
|
||||
data = re.sub(
|
||||
r'"([^"]*)"',
|
||||
lambda m: m.group(0).replace("\n", " "),
|
||||
data
|
||||
)
|
||||
data = re.sub(r'"([^"]*)"', lambda m: m.group(0).replace("\n", " "), data)
|
||||
|
||||
# --- Parse CSV ---
|
||||
lines = data.splitlines()
|
||||
@@ -202,11 +201,8 @@ def import_csv(file_storage=None):
|
||||
conn.commit()
|
||||
conn.close()
|
||||
|
||||
return jsonify({
|
||||
"success": True,
|
||||
"inserted": row_count,
|
||||
"skipped_lines": skipped
|
||||
})
|
||||
return jsonify({"success": True, "inserted": row_count, "skipped_lines": skipped})
|
||||
|
||||
|
||||
def devices_totals():
|
||||
conn = get_temp_db_connection()
|
||||
@@ -215,15 +211,17 @@ def devices_totals():
|
||||
# Build a combined query with sub-selects for each status
|
||||
query = f"""
|
||||
SELECT
|
||||
(SELECT COUNT(*) FROM Devices {get_device_condition_by_status('my')}) AS devices,
|
||||
(SELECT COUNT(*) FROM Devices {get_device_condition_by_status('connected')}) AS connected,
|
||||
(SELECT COUNT(*) FROM Devices {get_device_condition_by_status('favorites')}) AS favorites,
|
||||
(SELECT COUNT(*) FROM Devices {get_device_condition_by_status('new')}) AS new,
|
||||
(SELECT COUNT(*) FROM Devices {get_device_condition_by_status('down')}) AS down,
|
||||
(SELECT COUNT(*) FROM Devices {get_device_condition_by_status('archived')}) AS archived
|
||||
(SELECT COUNT(*) FROM Devices {get_device_condition_by_status("my")}) AS devices,
|
||||
(SELECT COUNT(*) FROM Devices {get_device_condition_by_status("connected")}) AS connected,
|
||||
(SELECT COUNT(*) FROM Devices {get_device_condition_by_status("favorites")}) AS favorites,
|
||||
(SELECT COUNT(*) FROM Devices {get_device_condition_by_status("new")}) AS new,
|
||||
(SELECT COUNT(*) FROM Devices {get_device_condition_by_status("down")}) AS down,
|
||||
(SELECT COUNT(*) FROM Devices {get_device_condition_by_status("archived")}) AS archived
|
||||
"""
|
||||
sql.execute(query)
|
||||
row = sql.fetchone() # returns a tuple like (devices, connected, favorites, new, down, archived)
|
||||
row = (
|
||||
sql.fetchone()
|
||||
) # returns a tuple like (devices, connected, favorites, new, down, archived)
|
||||
|
||||
conn.close()
|
||||
|
||||
@@ -252,12 +250,13 @@ def devices_by_status(status=None):
|
||||
if r.get("devFavorite") == 1:
|
||||
dev_name = f'<span class="text-yellow">★</span> {dev_name}'
|
||||
|
||||
table_data.append({
|
||||
"id": r.get("devMac", ""),
|
||||
"title": dev_name,
|
||||
"favorite": r.get("devFavorite", 0)
|
||||
})
|
||||
table_data.append(
|
||||
{
|
||||
"id": r.get("devMac", ""),
|
||||
"title": dev_name,
|
||||
"favorite": r.get("devFavorite", 0),
|
||||
}
|
||||
)
|
||||
|
||||
conn.close()
|
||||
return jsonify(table_data)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user