diff --git a/front/deviceDetailsEdit.php b/front/deviceDetailsEdit.php index 3c8699ea..0c8a28f7 100755 --- a/front/deviceDetailsEdit.php +++ b/front/deviceDetailsEdit.php @@ -280,6 +280,7 @@ function getDeviceData() { const fieldName = setting.setKey.replace('NEWDEV_', ''); if (trackedFields[fieldName] && fieldName !== "devFQDN" && mac != "new") { const sourceField = fieldName + "Source"; + const currentSource = deviceData[sourceField] || "N/A"; const isLocked = currentSource === "LOCKED"; const lockIcon = isLocked ? "fa-lock" : "fa-lock-open"; @@ -302,12 +303,16 @@ function getDeviceData() { const fieldName2 = setting.setKey.replace('NEWDEV_', ''); if (trackedFields[fieldName2] && mac != "new") { const sourceField = fieldName2 + "Source"; - const currentSource = deviceData[sourceField] || "N/A"; - const sourceTitle = getString("FieldLock_Source_Label") + currentSource; - const sourceColor = currentSource === "USER" ? "text-warning" : (currentSource === "LOCKED" ? "text-danger" : "text-muted"); - inlineControl += ` - ${currentSource} - `; + // only show if data available + if (deviceData[sourceField] != "") + { + const currentSource = deviceData[sourceField] || "N/A"; + const sourceTitle = getString("FieldLock_Source_Label") + currentSource; + const sourceColor = currentSource === "USER" ? "text-warning" : (currentSource === "LOCKED" ? "text-danger" : "text-muted"); + inlineControl += ` + ${currentSource} + `; + } } // handle devChildrenDynamic or NEWDEV_devChildrenNicsDynamic - selected values and options are the same diff --git a/server/api_server/graphql_endpoint.py b/server/api_server/graphql_endpoint.py index 458ba51c..94c5c624 100755 --- a/server/api_server/graphql_endpoint.py +++ b/server/api_server/graphql_endpoint.py @@ -92,11 +92,11 @@ class Device(ObjectType): devReqNicsOnline = Int(description="Required NICs online flag") devMacSource = String(description="Source tracking for devMac (USER, LOCKED, NEWDEV, or plugin prefix)") devNameSource = String(description="Source tracking for devName (USER, LOCKED, NEWDEV, or plugin prefix)") - devFqdnSource = String(description="Source tracking for devFQDN (USER, LOCKED, NEWDEV, or plugin prefix)") - devLastIpSource = String(description="Source tracking for devLastIP (USER, LOCKED, NEWDEV, or plugin prefix)") + devFQDNSource = String(description="Source tracking for devFQDN (USER, LOCKED, NEWDEV, or plugin prefix)") + devLastIPSource = String(description="Source tracking for devLastIP (USER, LOCKED, NEWDEV, or plugin prefix)") devVendorSource = String(description="Source tracking for devVendor (USER, LOCKED, NEWDEV, or plugin prefix)") - devSsidSource = String(description="Source tracking for devSSID (USER, LOCKED, NEWDEV, or plugin prefix)") - devParentMacSource = String(description="Source tracking for devParentMAC (USER, LOCKED, NEWDEV, or plugin prefix)") + devSSIDSource = String(description="Source tracking for devSSID (USER, LOCKED, NEWDEV, or plugin prefix)") + devParentMACSource = String(description="Source tracking for devParentMAC (USER, LOCKED, NEWDEV, or plugin prefix)") devParentPortSource = String(description="Source tracking for devParentPort (USER, LOCKED, NEWDEV, or plugin prefix)") devParentRelTypeSource = String(description="Source tracking for devParentRelType (USER, LOCKED, NEWDEV, or plugin prefix)") devVlanSource = String(description="Source tracking for devVlan") diff --git a/server/api_server/openapi/schemas.py b/server/api_server/openapi/schemas.py index 086f03cf..e8fe6423 100644 --- a/server/api_server/openapi/schemas.py +++ b/server/api_server/openapi/schemas.py @@ -147,11 +147,11 @@ class DeviceInfo(BaseModel): devStatus: Optional[str] = Field(None, description="Online/Offline status") devMacSource: Optional[str] = Field(None, description="Source of devMac (USER, LOCKED, or plugin prefix)") devNameSource: Optional[str] = Field(None, description="Source of devName") - devFqdnSource: Optional[str] = Field(None, description="Source of devFQDN") - devLastIpSource: Optional[str] = Field(None, description="Source of devLastIP") + devFQDNSource: Optional[str] = Field(None, description="Source of devFQDN") + devLastIPSource: Optional[str] = Field(None, description="Source of devLastIP") devVendorSource: Optional[str] = Field(None, description="Source of devVendor") - devSsidSource: Optional[str] = Field(None, description="Source of devSSID") - devParentMacSource: Optional[str] = Field(None, description="Source of devParentMAC") + devSSIDSource: Optional[str] = Field(None, description="Source of devSSID") + devParentMACSource: Optional[str] = Field(None, description="Source of devParentMAC") devParentPortSource: Optional[str] = Field(None, description="Source of devParentPort") devParentRelTypeSource: Optional[str] = Field(None, description="Source of devParentRelType") devVlanSource: Optional[str] = Field(None, description="Source of devVlan") diff --git a/server/const.py b/server/const.py index b074dde3..b8704e47 100755 --- a/server/const.py +++ b/server/const.py @@ -96,11 +96,11 @@ sql_devices_all = """ IFNULL(devReqNicsOnline, '') AS devReqNicsOnline, IFNULL(devMacSource, '') AS devMacSource, IFNULL(devNameSource, '') AS devNameSource, - IFNULL(devFqdnSource, '') AS devFqdnSource, - IFNULL(devLastIpSource, '') AS devLastIpSource, + IFNULL(devFQDNSource, '') AS devFQDNSource, + IFNULL(devLastIPSource, '') AS devLastIPSource, IFNULL(devVendorSource, '') AS devVendorSource, - IFNULL(devSsidSource, '') AS devSsidSource, - IFNULL(devParentMacSource, '') AS devParentMacSource, + IFNULL(devSSIDSource, '') AS devSSIDSource, + IFNULL(devParentMACSource, '') AS devParentMACSource, IFNULL(devParentPortSource, '') AS devParentPortSource, IFNULL(devParentRelTypeSource, '') AS devParentRelTypeSource, IFNULL(devVlanSource, '') AS devVlanSource, diff --git a/server/db/authoritative_handler.py b/server/db/authoritative_handler.py index be48c924..aa661b8e 100644 --- a/server/db/authoritative_handler.py +++ b/server/db/authoritative_handler.py @@ -24,11 +24,11 @@ from db.db_helper import row_to_json # noqa: E402 [flake8 lint suppression] FIELD_SOURCE_MAP = { "devMac": "devMacSource", "devName": "devNameSource", - "devFQDN": "devFqdnSource", - "devLastIP": "devLastIpSource", + "devFQDN": "devFQDNSource", + "devLastIP": "devLastIPSource", "devVendor": "devVendorSource", - "devSSID": "devSsidSource", - "devParentMAC": "devParentMacSource", + "devSSID": "devSSIDSource", + "devParentMAC": "devParentMACSource", "devParentPort": "devParentPortSource", "devParentRelType": "devParentRelTypeSource", "devVlan": "devVlanSource", diff --git a/server/db/db_upgrade.py b/server/db/db_upgrade.py index f7599b5a..3d6132c2 100755 --- a/server/db/db_upgrade.py +++ b/server/db/db_upgrade.py @@ -50,11 +50,11 @@ EXPECTED_DEVICES_COLUMNS = [ "devSourcePlugin", "devMacSource", "devNameSource", - "devFqdnSource", - "devLastIpSource", + "devFQDNSource", + "devLastIPSource", "devVendorSource", - "devSsidSource", - "devParentMacSource", + "devSSIDSource", + "devParentMACSource", "devParentPortSource", "devParentRelTypeSource", "devVlanSource", diff --git a/server/scan/device_handling.py b/server/scan/device_handling.py index 246a73be..ecbe1f4c 100755 --- a/server/scan/device_handling.py +++ b/server/scan/device_handling.py @@ -115,7 +115,7 @@ FIELD_SPECS = { # ========================================================== "devLastIP": { "scan_col": "cur_IP", - "source_col": "devLastIpSource", + "source_col": "devLastIPSource", "empty_values": ["", "null", "(unknown)", "(Unknown)"], "priority": ["ARPSCAN", "NEWDEV", "N/A"], "default_value": "0.0.0.0", @@ -177,7 +177,7 @@ FIELD_SPECS = { # ========================================================== "devParentMAC": { "scan_col": "cur_NetworkNodeMAC", - "source_col": "devParentMacSource", + "source_col": "devParentMACSource", "empty_values": ["", "null"], "priority": ["SNMPDSC", "UNIFIAPI", "UNFIMP", "NEWDEV", "N/A"], }, @@ -801,11 +801,11 @@ def create_new_devices(db): devSourcePlugin, devMacSource, devNameSource, - devFqdnSource, - devLastIpSource, + devFQDNSource, + devLastIPSource, devVendorSource, - devSsidSource, - devParentMacSource, + devSSIDSource, + devParentMACSource, devParentPortSource, devParentRelTypeSource, devVlanSource, @@ -1031,7 +1031,7 @@ def update_devices_names(pm): "devName", "devNameSource", plugin_settings ) fqdn_clause = get_overwrite_sql_clause( - "devFQDN", "devFqdnSource", plugin_settings + "devFQDN", "devFQDNSource", plugin_settings ) sql.executemany( @@ -1048,9 +1048,9 @@ def update_devices_names(pm): WHEN {fqdn_clause} THEN ? ELSE devFQDN END, - devFqdnSource = CASE + devFQDNSource = CASE WHEN {fqdn_clause} THEN ? - ELSE devFqdnSource + ELSE devFQDNSource END WHERE devMac = ?""", plugin_records, @@ -1079,7 +1079,7 @@ def update_devices_names(pm): for plugin_label, plugin_records in records_by_plugin.items(): plugin_settings = get_plugin_authoritative_settings(plugin_label) fqdn_clause = get_overwrite_sql_clause( - "devFQDN", "devFqdnSource", plugin_settings + "devFQDN", "devFQDNSource", plugin_settings ) # Apply FQDN-only updates @@ -1089,9 +1089,9 @@ def update_devices_names(pm): WHEN {fqdn_clause} THEN ? ELSE devFQDN END, - devFqdnSource = CASE + devFQDNSource = CASE WHEN {fqdn_clause} THEN ? - ELSE devFqdnSource + ELSE devFQDNSource END WHERE devMac = ?""", plugin_records, diff --git a/test/authoritative_fields/test_authoritative_handler.py b/test/authoritative_fields/test_authoritative_handler.py index 0517f734..e30f24a8 100644 --- a/test/authoritative_fields/test_authoritative_handler.py +++ b/test/authoritative_fields/test_authoritative_handler.py @@ -129,11 +129,11 @@ class TestFieldSourceMapping: expected_fields = { "devMac": "devMacSource", "devName": "devNameSource", - "devFQDN": "devFqdnSource", - "devLastIP": "devLastIpSource", + "devFQDN": "devFQDNSource", + "devLastIP": "devLastIPSource", "devVendor": "devVendorSource", - "devSSID": "devSsidSource", - "devParentMAC": "devParentMacSource", + "devSSID": "devSSIDSource", + "devParentMAC": "devParentMACSource", "devParentPort": "devParentPortSource", "devParentRelType": "devParentRelTypeSource", "devVlan": "devVlanSource", diff --git a/test/authoritative_fields/test_device_field_lock.py b/test/authoritative_fields/test_device_field_lock.py index 93e2e2b9..c71dda7a 100644 --- a/test/authoritative_fields/test_device_field_lock.py +++ b/test/authoritative_fields/test_device_field_lock.py @@ -414,7 +414,7 @@ class TestFieldLockIntegration: device_data = device_handler.getDeviceData(test_mac) assert device_data.get("devNameSource") == "NEWDEV" assert device_data.get("devVendorSource") == "NEWDEV" - assert device_data.get("devSsidSource") == "NEWDEV" + assert device_data.get("devSSIDSource") == "NEWDEV" # Simulate a UI "save" that resubmits the same values. update_result = device_handler.setDeviceData( @@ -430,7 +430,7 @@ class TestFieldLockIntegration: device_data = device_handler.getDeviceData(test_mac) assert device_data.get("devNameSource") == "NEWDEV" assert device_data.get("devVendorSource") == "NEWDEV" - assert device_data.get("devSsidSource") == "NEWDEV" + assert device_data.get("devSSIDSource") == "NEWDEV" def test_only_changed_fields_marked_user(self, test_mac): """When saving, only fields whose values changed should become USER.""" @@ -461,7 +461,7 @@ class TestFieldLockIntegration: device_data = device_handler.getDeviceData(test_mac) assert device_data.get("devNameSource") == "USER" assert device_data.get("devVendorSource") == "NEWDEV" - assert device_data.get("devSsidSource") == "NEWDEV" + assert device_data.get("devSSIDSource") == "NEWDEV" if __name__ == "__main__": diff --git a/test/authoritative_fields/test_field_lock_scan_integration.py b/test/authoritative_fields/test_field_lock_scan_integration.py index de824ea3..23de16fd 100644 --- a/test/authoritative_fields/test_field_lock_scan_integration.py +++ b/test/authoritative_fields/test_field_lock_scan_integration.py @@ -39,19 +39,19 @@ def scan_db(): devNameSource TEXT DEFAULT 'NEWDEV', devVendor TEXT, devVendorSource TEXT DEFAULT 'NEWDEV', - devLastIpSource TEXT DEFAULT 'NEWDEV', + devLastIPSource TEXT DEFAULT 'NEWDEV', devType TEXT, devIcon TEXT, devParentPort TEXT, devParentPortSource TEXT DEFAULT 'NEWDEV', devParentMAC TEXT, - devParentMacSource TEXT DEFAULT 'NEWDEV', + devParentMACSource TEXT DEFAULT 'NEWDEV', devSite TEXT, devSiteSource TEXT DEFAULT 'NEWDEV', devSSID TEXT, - devSsidSource TEXT DEFAULT 'NEWDEV', + devSSIDSource TEXT DEFAULT 'NEWDEV', devFQDN TEXT, - devFqdnSource TEXT DEFAULT 'NEWDEV', + devFQDNSource TEXT DEFAULT 'NEWDEV', devParentRelType TEXT, devParentRelTypeSource TEXT DEFAULT 'NEWDEV', devVlan TEXT, @@ -165,11 +165,11 @@ def scan_db_for_new_devices(): devSourcePlugin TEXT, devMacSource TEXT, devNameSource TEXT, - devFqdnSource TEXT, - devLastIpSource TEXT, + devFQDNSource TEXT, + devLastIPSource TEXT, devVendorSource TEXT, - devSsidSource TEXT, - devParentMacSource TEXT, + devSSIDSource TEXT, + devParentMACSource TEXT, devParentPortSource TEXT, devParentRelTypeSource TEXT, devVlanSource TEXT, @@ -304,12 +304,12 @@ def test_create_new_devices_sets_sources(scan_db_for_new_devices): devMacSource, devNameSource, devVendorSource, - devLastIpSource, - devSsidSource, - devParentMacSource, + devLastIPSource, + devSSIDSource, + devParentMACSource, devParentPortSource, devParentRelTypeSource, - devFqdnSource, + devFQDNSource, devVlanSource FROM Devices WHERE devMac = ? """, @@ -319,12 +319,12 @@ def test_create_new_devices_sets_sources(scan_db_for_new_devices): assert row["devMacSource"] == "ARPSCAN" assert row["devNameSource"] == "ARPSCAN" assert row["devVendorSource"] == "ARPSCAN" - assert row["devLastIpSource"] == "ARPSCAN" - assert row["devSsidSource"] == "ARPSCAN" - assert row["devParentMacSource"] == "ARPSCAN" + assert row["devLastIPSource"] == "ARPSCAN" + assert row["devSSIDSource"] == "ARPSCAN" + assert row["devParentMACSource"] == "ARPSCAN" assert row["devParentPortSource"] == "ARPSCAN" assert row["devParentRelTypeSource"] == "NEWDEV" - assert row["devFqdnSource"] == "NEWDEV" + assert row["devFQDNSource"] == "NEWDEV" assert row["devVlanSource"] == "NEWDEV" @@ -337,7 +337,7 @@ def test_scan_updates_newdev_device_name(scan_db, mock_device_handlers): """ INSERT INTO Devices ( devMac, devLastConnection, devPresentLastScan, devLastIP, - devName, devNameSource, devVendor, devVendorSource, devLastIpSource, + devName, devNameSource, devVendor, devVendorSource, devLastIPSource, devType, devIcon, devParentPort, devParentMAC, devSite, devSSID ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) """, @@ -412,7 +412,7 @@ def test_scan_does_not_update_user_field_name(scan_db, mock_device_handlers): """ INSERT INTO Devices ( devMac, devLastConnection, devPresentLastScan, devLastIP, - devName, devNameSource, devVendor, devVendorSource, devLastIpSource, + devName, devNameSource, devVendor, devVendorSource, devLastIPSource, devType, devIcon, devParentPort, devParentMAC, devSite, devSSID ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) """, @@ -487,7 +487,7 @@ def test_scan_does_not_update_locked_field(scan_db, mock_device_handlers): """ INSERT INTO Devices ( devMac, devLastConnection, devPresentLastScan, devLastIP, - devName, devNameSource, devVendor, devVendorSource, devLastIpSource, + devName, devNameSource, devVendor, devVendorSource, devLastIPSource, devType, devIcon, devParentPort, devParentMAC, devSite, devSSID ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) """, @@ -562,7 +562,7 @@ def test_scan_updates_empty_vendor_field(scan_db, mock_device_handlers): """ INSERT INTO Devices ( devMac, devLastConnection, devPresentLastScan, devLastIP, - devName, devNameSource, devVendor, devVendorSource, devLastIpSource, + devName, devNameSource, devVendor, devVendorSource, devLastIPSource, devType, devIcon, devParentPort, devParentMAC, devSite, devSSID ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) """, @@ -637,7 +637,7 @@ def test_scan_updates_ip_addresses(scan_db, mock_device_handlers): """ INSERT INTO Devices ( devMac, devLastConnection, devPresentLastScan, devLastIP, - devName, devNameSource, devVendor, devVendorSource, devLastIpSource, + devName, devNameSource, devVendor, devVendorSource, devLastIPSource, devType, devIcon, devParentPort, devParentMAC, devSite, devSSID, devPrimaryIPv4, devPrimaryIPv6 ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) @@ -717,7 +717,7 @@ def test_scan_updates_ipv6_without_changing_ipv4(scan_db, mock_device_handlers): """ INSERT INTO Devices ( devMac, devLastConnection, devPresentLastScan, devLastIP, - devName, devNameSource, devVendor, devVendorSource, devLastIpSource, + devName, devNameSource, devVendor, devVendorSource, devLastIPSource, devType, devIcon, devParentPort, devParentMAC, devSite, devSSID, devPrimaryIPv4, devPrimaryIPv6 ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) @@ -796,7 +796,7 @@ def test_scan_updates_presence_status(scan_db, mock_device_handlers): """ INSERT INTO Devices ( devMac, devLastConnection, devPresentLastScan, devLastIP, - devName, devNameSource, devVendor, devVendorSource, devLastIpSource, + devName, devNameSource, devVendor, devVendorSource, devLastIPSource, devType, devIcon, devParentPort, devParentMAC, devSite, devSSID ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) """, @@ -855,7 +855,7 @@ def test_scan_multiple_devices_mixed_sources(scan_db, mock_device_handlers): """ INSERT INTO Devices ( devMac, devLastConnection, devPresentLastScan, devLastIP, - devName, devNameSource, devVendor, devVendorSource, devLastIpSource, + devName, devNameSource, devVendor, devVendorSource, devLastIPSource, devType, devIcon, devParentPort, devParentMAC, devSite, devSSID ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) """, diff --git a/test/authoritative_fields/test_ip_format_and_locking.py b/test/authoritative_fields/test_ip_format_and_locking.py index 29070462..ad57063d 100644 --- a/test/authoritative_fields/test_ip_format_and_locking.py +++ b/test/authoritative_fields/test_ip_format_and_locking.py @@ -31,7 +31,7 @@ def ip_test_db(): devPresentLastScan INTEGER, devForceStatus TEXT, devLastIP TEXT, - devLastIpSource TEXT DEFAULT 'NEWDEV', + devLastIPSource TEXT DEFAULT 'NEWDEV', devPrimaryIPv4 TEXT, devPrimaryIPv4Source TEXT DEFAULT 'NEWDEV', devPrimaryIPv6 TEXT,