review fixes

This commit is contained in:
Jokob @NetAlertX
2026-01-21 00:17:54 +00:00
parent 22695a633c
commit 3ee21ac830
9 changed files with 169 additions and 170 deletions

View File

@@ -472,24 +472,24 @@ def api_device_field_lock(mac, payload=None):
# Validate that the field can be locked
source_field = field_name + "Source"
allowed_tracked_fields = {
"devMac", "devName", "devLastIP", "devVendor", "devFQDN",
"devMac", "devName", "devLastIP", "devVendor", "devFQDN",
"devSSID", "devParentMAC", "devParentPort", "devParentRelType", "devVlan"
}
if field_name not in allowed_tracked_fields:
return jsonify({"success": False, "error": f"Field '{field_name}' cannot be locked"}), 400
device_handler = DeviceInstance()
try:
# When locking: set source to LOCKED
# When unlocking: check current value and let plugins take over
new_source = "LOCKED" if should_lock else "NEWDEV"
result = device_handler.updateDeviceColumn(mac, source_field, new_source)
if result.get("success"):
action = "locked" if should_lock else "unlocked"
return jsonify({
"success": True,
"success": True,
"message": f"Field {field_name} {action}",
"fieldName": field_name,
"locked": should_lock
@@ -497,7 +497,7 @@ def api_device_field_lock(mac, payload=None):
else:
return jsonify(result), 400
except Exception as e:
mylog("error", f"Error locking field {field_name} for {mac}: {str(e)}")
mylog("none", f"Error locking field {field_name} for {mac}: {str(e)}")
return jsonify({"success": False, "error": str(e)}), 500

View File

@@ -275,7 +275,7 @@ class UpdateDeviceColumnRequest(BaseModel):
class LockDeviceFieldRequest(BaseModel):
"""Request to lock/unlock a device field."""
fieldName: str = Field(..., description="Field name to lock/unlock (devMac, devName, devLastIP, etc.)")
fieldName: Optional[str] = Field(None, description="Field name to lock/unlock (devMac, devName, devLastIP, etc.)")
lock: bool = Field(True, description="True to lock the field, False to unlock")

View File

@@ -595,6 +595,30 @@ class DeviceInstance:
cur.execute(sql, values)
conn.commit()
if data.get("createNew", False):
# Initialize source-tracking fields on device creation.
# We always mark devMacSource as NEWDEV, and mark other tracked fields
# as NEWDEV only if the create payload provides a non-empty value.
initial_sources = {FIELD_SOURCE_MAP["devMac"]: "NEWDEV"}
for field_name, source_field in FIELD_SOURCE_MAP.items():
if field_name == "devMac":
continue
field_value = data.get(field_name)
if field_value is None:
continue
if isinstance(field_value, str) and not field_value.strip():
continue
initial_sources[source_field] = "NEWDEV"
if initial_sources:
# Apply source updates in a single statement for the newly inserted row.
set_clause = ", ".join([f"{col}=?" for col in initial_sources.keys()])
source_values = list(initial_sources.values())
source_values.append(normalized_mac)
source_sql = f"UPDATE Devices SET {set_clause} WHERE devMac = ?"
cur.execute(source_sql, source_values)
conn.commit()
# Enforce source tracking on user updates
# User-updated fields should have their *Source set to "USER"
user_updated_fields = {k: v for k, v in data.items() if k in FIELD_SOURCE_MAP}
@@ -683,26 +707,30 @@ class DeviceInstance:
if field_name not in FIELD_SOURCE_MAP:
return {"success": False, "error": f"Field {field_name} does not support locking"}
mac_normalized = normalize_mac(mac)
conn = get_temp_db_connection()
try:
conn = get_temp_db_connection()
lock_field(mac, field_name, conn)
conn.close()
lock_field(mac_normalized, field_name, conn)
return {"success": True, "message": f"Field {field_name} locked"}
except Exception as e:
return {"success": False, "error": str(e)}
finally:
conn.close()
def unlockDeviceField(self, mac, field_name):
"""Unlock a device field so plugins can overwrite it again."""
if field_name not in FIELD_SOURCE_MAP:
return {"success": False, "error": f"Field {field_name} does not support unlocking"}
mac_normalized = normalize_mac(mac)
conn = get_temp_db_connection()
try:
conn = get_temp_db_connection()
unlock_field(mac, field_name, conn)
conn.close()
unlock_field(mac_normalized, field_name, conn)
return {"success": True, "message": f"Field {field_name} unlocked"}
except Exception as e:
return {"success": False, "error": str(e)}
finally:
conn.close()
def copyDevice(self, mac_from, mac_to):
"""Copy a device entry from one MAC to another."""

View File

@@ -9,6 +9,7 @@ from models.device_instance import DeviceInstance
from scan.name_resolution import NameResolver
from scan.device_heuristics import guess_icon, guess_type
from db.db_helper import sanitize_SQL_input, list_to_where, safe_int
from helper import format_ip_long
# Make sure log level is initialized correctly
Logger(get_setting_value("LOG_LEVEL"))
@@ -544,6 +545,12 @@ def create_new_devices(db):
# Derive primary IP family values
cur_IP = str(cur_IP).strip() if cur_IP else ""
cur_IP_normalized = check_IP_format(cur_IP) if ":" not in cur_IP else cur_IP
# Validate IPv6 addresses using format_ip_long for consistency
if ":" in cur_IP_normalized:
validated_ipv6 = format_ip_long(cur_IP_normalized)
cur_IP_normalized = validated_ipv6 if validated_ipv6 else ""
primary_ipv4 = cur_IP_normalized if cur_IP_normalized and ":" not in cur_IP_normalized else ""
primary_ipv6 = cur_IP_normalized if cur_IP_normalized and ":" in cur_IP_normalized else ""