mirror of
https://github.com/jokob-sk/NetAlertX.git
synced 2025-12-07 09:36:05 -08:00
GraphQl 0.123 - Dynamic columns + re-adding old Device table columns
This commit is contained in:
@@ -160,6 +160,7 @@
|
|||||||
var tableColumnOrder = [];
|
var tableColumnOrder = [];
|
||||||
var tableColumnVisible = [];
|
var tableColumnVisible = [];
|
||||||
headersDefaultOrder = [];
|
headersDefaultOrder = [];
|
||||||
|
missingNumbers = [];
|
||||||
|
|
||||||
// Read parameters & Initialize components
|
// Read parameters & Initialize components
|
||||||
callAfterAppInitialized(main)
|
callAfterAppInitialized(main)
|
||||||
@@ -193,7 +194,7 @@ function main () {
|
|||||||
const fullArray = Array.from({ length: tableColumnOrder.length }, (_, i) => i);
|
const fullArray = Array.from({ length: tableColumnOrder.length }, (_, i) => i);
|
||||||
|
|
||||||
// Filter out the elements already present in inputArray
|
// Filter out the elements already present in inputArray
|
||||||
const missingNumbers = fullArray.filter(num => !tableColumnVisible.includes(num));
|
missingNumbers = fullArray.filter(num => !tableColumnVisible.includes(num));
|
||||||
|
|
||||||
// Concatenate the inputArray with the missingNumbers
|
// Concatenate the inputArray with the missingNumbers
|
||||||
tableColumnOrder = [...tableColumnVisible, ...missingNumbers];
|
tableColumnOrder = [...tableColumnVisible, ...missingNumbers];
|
||||||
@@ -336,47 +337,43 @@ function filterDataByStatus(data, status) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
|
||||||
function getDeviceStatus(item)
|
|
||||||
{
|
|
||||||
|
|
||||||
if(item.devIsNew === 1)
|
|
||||||
{
|
|
||||||
return 'New';
|
|
||||||
}
|
|
||||||
else if(item.devPresentLastScan === 1)
|
|
||||||
{
|
|
||||||
return 'On-line';
|
|
||||||
}
|
|
||||||
else if(item.devPresentLastScan === 0 && item.devAlertDown !== 0)
|
|
||||||
{
|
|
||||||
return 'Down';
|
|
||||||
}
|
|
||||||
else if(item.devIsArchived === 1)
|
|
||||||
{
|
|
||||||
return 'Archived';
|
|
||||||
}
|
|
||||||
else if(item.devPresentLastScan === 0)
|
|
||||||
{
|
|
||||||
return 'Off-line';
|
|
||||||
}
|
|
||||||
|
|
||||||
return "Unknown status"
|
|
||||||
}
|
|
||||||
|
|
||||||
// Map column index to column name for GraphQL query
|
// Map column index to column name for GraphQL query
|
||||||
function mapColumnIndexToFieldName(index) {
|
function mapColumnIndexToFieldName(index, tableColumnVisible) {
|
||||||
const columnNames = [
|
const columnNames = [
|
||||||
"rowid", "devMac", "devName", "devOwner", "devType", "devVendor",
|
"devName",
|
||||||
"devFavorite", "devGroup", "devComments", "devFirstConnection",
|
"devOwner",
|
||||||
"devLastConnection", "devLastIP", "devStaticIP", "devScan", "devLogEvents",
|
"devType",
|
||||||
"devAlertEvents", "devAlertDown", "devSkipRepeated", "devLastNotification",
|
"devIcon",
|
||||||
"devPresentLastScan", "devIsNew", "devLocation", "devIsArchived",
|
"devFavorite",
|
||||||
"devParentMAC", "devParentPort", "devIcon", "devGUID", "devSite", "devSSID",
|
"devGroup",
|
||||||
"devSyncHubNode", "devSourcePlugin"
|
"devFirstConnection",
|
||||||
|
"devLastConnection",
|
||||||
|
"devLastIP",
|
||||||
|
"devIsRandomMac", // resolved on the fly
|
||||||
|
"devStatus", // resolved on the fly
|
||||||
|
"devMac",
|
||||||
|
"devIpLong", //formatIPlong(device.devLastIP) || "", // IP orderable
|
||||||
|
"rowid",
|
||||||
|
"devParentMAC",
|
||||||
|
"devParentChildrenCount", // resolved on the fly
|
||||||
|
"devLocation",
|
||||||
|
"devVendor",
|
||||||
|
"devParentPort",
|
||||||
|
"devGUID",
|
||||||
|
"devSyncHubNode",
|
||||||
|
"devSite",
|
||||||
|
"devSSID",
|
||||||
|
"devSourcePlugin"
|
||||||
];
|
];
|
||||||
|
|
||||||
return columnNames[index] || null;
|
console.log(index);
|
||||||
|
console.log(tableColumnVisible);
|
||||||
|
console.log(tableColumnOrder); // this
|
||||||
|
console.log(missingNumbers);
|
||||||
|
console.log(columnNames[tableColumnOrder[index]]);
|
||||||
|
|
||||||
|
return columnNames[tableColumnOrder[index]] || null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -465,6 +462,7 @@ function initializeDatatable (status) {
|
|||||||
devLastNotification
|
devLastNotification
|
||||||
devPresentLastScan
|
devPresentLastScan
|
||||||
devIsNew
|
devIsNew
|
||||||
|
devIsRandomMac
|
||||||
devLocation
|
devLocation
|
||||||
devIsArchived
|
devIsArchived
|
||||||
devParentMAC
|
devParentMAC
|
||||||
@@ -475,6 +473,9 @@ function initializeDatatable (status) {
|
|||||||
devSSID
|
devSSID
|
||||||
devSyncHubNode
|
devSyncHubNode
|
||||||
devSourcePlugin
|
devSourcePlugin
|
||||||
|
devStatus
|
||||||
|
devParentChildrenCount
|
||||||
|
devIpLong
|
||||||
}
|
}
|
||||||
count
|
count
|
||||||
}
|
}
|
||||||
@@ -493,7 +494,7 @@ function initializeDatatable (status) {
|
|||||||
"page": Math.floor(d.start / d.length) + 1, // Page number (1-based)
|
"page": Math.floor(d.start / d.length) + 1, // Page number (1-based)
|
||||||
"limit": parseInt(d.length, 10), // Page size (ensure it's an integer)
|
"limit": parseInt(d.length, 10), // Page size (ensure it's an integer)
|
||||||
"sort": d.order && d.order[0] ? [{
|
"sort": d.order && d.order[0] ? [{
|
||||||
"field": mapColumnIndexToFieldName(d.order[0].column), // Sort field from DataTable column
|
"field": mapColumnIndexToFieldName(d.order[0].column, tableColumnVisible), // Sort field from DataTable column
|
||||||
"order": d.order[0].dir.toUpperCase() // Sort direction (ASC/DESC)
|
"order": d.order[0].dir.toUpperCase() // Sort direction (ASC/DESC)
|
||||||
}] : [], // Default to an empty array if no sorting is defined
|
}] : [], // Default to an empty array if no sorting is defined
|
||||||
"search": d.search.value // Search query
|
"search": d.search.value // Search query
|
||||||
@@ -518,13 +519,13 @@ function initializeDatatable (status) {
|
|||||||
device.devFirstConnection || "",
|
device.devFirstConnection || "",
|
||||||
device.devLastConnection || "",
|
device.devLastConnection || "",
|
||||||
device.devLastIP || "",
|
device.devLastIP || "",
|
||||||
(isRandomMAC(device.devMac)) || "", // Custom logic for randomized MAC
|
device.devIsRandomMac || "", // Custom logic for randomized MAC
|
||||||
getDeviceStatus(device) || "",
|
device.devStatus || "",
|
||||||
device.devMac || "", // hidden
|
device.devMac || "", // hidden
|
||||||
formatIPlong(device.devLastIP) || "", // IP orderable
|
device.devIpLong || "", // IP orderable
|
||||||
device.rowid || "",
|
device.rowid || "",
|
||||||
device.devParentMAC || "",
|
device.devParentMAC || "",
|
||||||
getNumberOfChildren(device.devMac, json.devices.devices) || 0,
|
device.devParentChildrenCount || 0,
|
||||||
device.devLocation || "",
|
device.devLocation || "",
|
||||||
device.devVendor || "",
|
device.devVendor || "",
|
||||||
device.devParentPort || 0,
|
device.devParentPort || 0,
|
||||||
@@ -751,26 +752,6 @@ function initializeDatatable (status) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
|
||||||
function getNumberOfChildren(mac, devices)
|
|
||||||
{
|
|
||||||
childrenCount = 0;
|
|
||||||
|
|
||||||
$.each(devices, function(index, dev) {
|
|
||||||
|
|
||||||
if(dev.devParentMAC != null && dev.devParentMAC.trim() == mac.trim())
|
|
||||||
{
|
|
||||||
childrenCount++;
|
|
||||||
}
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
return childrenCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
function handleLoadingDialog(needsReload = false)
|
function handleLoadingDialog(needsReload = false)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -12,7 +12,6 @@ require dirname(__FILE__).'/../server/init.php';
|
|||||||
// Helper function to get GraphQL URL (you can replace this with environment variables)
|
// Helper function to get GraphQL URL (you can replace this with environment variables)
|
||||||
function getGraphQLUrl() {
|
function getGraphQLUrl() {
|
||||||
$port = getSettingValue("GRAPHQL_PORT"); // Port for the GraphQL server
|
$port = getSettingValue("GRAPHQL_PORT"); // Port for the GraphQL server
|
||||||
// return "$url:$port/graphql"; // Full URL to the GraphQL endpoint
|
|
||||||
return "0.0.0.0:$port/graphql"; // Full URL to the GraphQL endpoint
|
return "0.0.0.0:$port/graphql"; // Full URL to the GraphQL endpoint
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -27,7 +27,20 @@ vendorsPathNewest = '/usr/share/arp-scan/ieee-oui_all_filtered.txt'
|
|||||||
#===============================================================================
|
#===============================================================================
|
||||||
# SQL queries
|
# SQL queries
|
||||||
#===============================================================================
|
#===============================================================================
|
||||||
sql_devices_all = """select rowid, * from Devices"""
|
sql_devices_all = """
|
||||||
|
SELECT
|
||||||
|
rowid,
|
||||||
|
*,
|
||||||
|
CASE
|
||||||
|
WHEN devIsNew = 1 THEN 'New'
|
||||||
|
WHEN devPresentLastScan = 1 THEN 'On-line'
|
||||||
|
WHEN devPresentLastScan = 0 AND devAlertDown != 0 THEN 'Down'
|
||||||
|
WHEN devIsArchived = 1 THEN 'Archived'
|
||||||
|
WHEN devPresentLastScan = 0 THEN 'Off-line'
|
||||||
|
ELSE 'Unknown status'
|
||||||
|
END AS devStatus
|
||||||
|
FROM Devices
|
||||||
|
"""
|
||||||
sql_appevents = """select * from AppEvents"""
|
sql_appevents = """select * from AppEvents"""
|
||||||
sql_devices_stats = """SELECT Online_Devices as online, Down_Devices as down, All_Devices as 'all', Archived_Devices as archived,
|
sql_devices_stats = """SELECT Online_Devices as online, Down_Devices as down, All_Devices as 'all', Archived_Devices as archived,
|
||||||
(select count(*) from Devices a where devIsNew = 1 ) as new,
|
(select count(*) from Devices a where devIsNew = 1 ) as new,
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ class DB():
|
|||||||
mylog('debug','openDB: database already open')
|
mylog('debug','openDB: database already open')
|
||||||
return
|
return
|
||||||
|
|
||||||
mylog('none', '[Database] Opening DB' )
|
mylog('verbose', '[Database] Opening DB' )
|
||||||
# Open DB and Cursor
|
# Open DB and Cursor
|
||||||
try:
|
try:
|
||||||
self.sql_connection = sqlite3.connect (fullDbPath, isolation_level=None)
|
self.sql_connection = sqlite3.connect (fullDbPath, isolation_level=None)
|
||||||
@@ -37,7 +37,7 @@ class DB():
|
|||||||
self.sql_connection.row_factory = sqlite3.Row
|
self.sql_connection.row_factory = sqlite3.Row
|
||||||
self.sql = self.sql_connection.cursor()
|
self.sql = self.sql_connection.cursor()
|
||||||
except sqlite3.Error as e:
|
except sqlite3.Error as e:
|
||||||
mylog('none',[ '[Database] - Open DB Error: ', e])
|
mylog('verbose',[ '[Database] - Open DB Error: ', e])
|
||||||
|
|
||||||
|
|
||||||
#-------------------------------------------------------------------------------
|
#-------------------------------------------------------------------------------
|
||||||
@@ -96,7 +96,7 @@ class DB():
|
|||||||
""")
|
""")
|
||||||
|
|
||||||
# -------------------------------------------------------------------
|
# -------------------------------------------------------------------
|
||||||
# DevicesNew - cleanup after 6/6/2025
|
# DevicesNew - cleanup after 6/6/2025 - need to update also DB in the source code!
|
||||||
|
|
||||||
# check if migration already done based on devMac
|
# check if migration already done based on devMac
|
||||||
devMac_missing = self.sql.execute ("""
|
devMac_missing = self.sql.execute ("""
|
||||||
@@ -104,6 +104,104 @@ class DB():
|
|||||||
""").fetchone()[0] == 0
|
""").fetchone()[0] == 0
|
||||||
|
|
||||||
if devMac_missing:
|
if devMac_missing:
|
||||||
|
|
||||||
|
# -------------------------------------------------------------------------
|
||||||
|
# Alter Devices table
|
||||||
|
# -------------------------------------------------------------------------
|
||||||
|
# dev_Network_Node_MAC_ADDR column
|
||||||
|
dev_Network_Node_MAC_ADDR_missing = self.sql.execute ("""
|
||||||
|
SELECT COUNT(*) AS CNTREC FROM pragma_table_info('Devices') WHERE name='dev_Network_Node_MAC_ADDR'
|
||||||
|
""").fetchone()[0] == 0
|
||||||
|
|
||||||
|
if dev_Network_Node_MAC_ADDR_missing :
|
||||||
|
mylog('verbose', ["[upgradeDB] Adding dev_Network_Node_MAC_ADDR to the Devices table"])
|
||||||
|
self.sql.execute("""
|
||||||
|
ALTER TABLE "Devices" ADD "dev_Network_Node_MAC_ADDR" TEXT
|
||||||
|
""")
|
||||||
|
|
||||||
|
# dev_Network_Node_port column
|
||||||
|
dev_Network_Node_port_missing = self.sql.execute ("""
|
||||||
|
SELECT COUNT(*) AS CNTREC FROM pragma_table_info('Devices') WHERE name='dev_Network_Node_port'
|
||||||
|
""").fetchone()[0] == 0
|
||||||
|
|
||||||
|
if dev_Network_Node_port_missing :
|
||||||
|
mylog('verbose', ["[upgradeDB] Adding dev_Network_Node_port to the Devices table"])
|
||||||
|
self.sql.execute("""
|
||||||
|
ALTER TABLE "Devices" ADD "dev_Network_Node_port" INTEGER
|
||||||
|
""")
|
||||||
|
|
||||||
|
# dev_Icon column
|
||||||
|
dev_Icon_missing = self.sql.execute ("""
|
||||||
|
SELECT COUNT(*) AS CNTREC FROM pragma_table_info('Devices') WHERE name='dev_Icon'
|
||||||
|
""").fetchone()[0] == 0
|
||||||
|
|
||||||
|
if dev_Icon_missing :
|
||||||
|
mylog('verbose', ["[upgradeDB] Adding dev_Icon to the Devices table"])
|
||||||
|
self.sql.execute("""
|
||||||
|
ALTER TABLE "Devices" ADD "dev_Icon" TEXT
|
||||||
|
""")
|
||||||
|
|
||||||
|
# dev_GUID column
|
||||||
|
dev_GUID_missing = self.sql.execute ("""
|
||||||
|
SELECT COUNT(*) AS CNTREC FROM pragma_table_info('Devices') WHERE name='dev_GUID'
|
||||||
|
""").fetchone()[0] == 0
|
||||||
|
|
||||||
|
if dev_GUID_missing :
|
||||||
|
mylog('verbose', ["[upgradeDB] Adding dev_GUID to the Devices table"])
|
||||||
|
self.sql.execute("""
|
||||||
|
ALTER TABLE "Devices" ADD "dev_GUID" TEXT
|
||||||
|
""")
|
||||||
|
|
||||||
|
# dev_NetworkSite column
|
||||||
|
dev_NetworkSite_missing = self.sql.execute ("""
|
||||||
|
SELECT COUNT(*) AS CNTREC FROM pragma_table_info('Devices') WHERE name='dev_NetworkSite'
|
||||||
|
""").fetchone()[0] == 0
|
||||||
|
|
||||||
|
if dev_NetworkSite_missing :
|
||||||
|
mylog('verbose', ["[upgradeDB] Adding dev_NetworkSite to the Devices table"])
|
||||||
|
self.sql.execute("""
|
||||||
|
ALTER TABLE "Devices" ADD "dev_NetworkSite" TEXT
|
||||||
|
""")
|
||||||
|
|
||||||
|
# dev_SSID column
|
||||||
|
dev_SSID_missing = self.sql.execute ("""
|
||||||
|
SELECT COUNT(*) AS CNTREC FROM pragma_table_info('Devices') WHERE name='dev_SSID'
|
||||||
|
""").fetchone()[0] == 0
|
||||||
|
|
||||||
|
if dev_SSID_missing :
|
||||||
|
mylog('verbose', ["[upgradeDB] Adding dev_SSID to the Devices table"])
|
||||||
|
self.sql.execute("""
|
||||||
|
ALTER TABLE "Devices" ADD "dev_SSID" TEXT
|
||||||
|
""")
|
||||||
|
|
||||||
|
# SQL query to update missing dev_GUID
|
||||||
|
self.sql.execute(f'''
|
||||||
|
UPDATE Devices
|
||||||
|
SET dev_GUID = {sql_generateGuid}
|
||||||
|
WHERE dev_GUID IS NULL
|
||||||
|
''')
|
||||||
|
|
||||||
|
# dev_SyncHubNodeName column
|
||||||
|
dev_SyncHubNodeName_missing = self.sql.execute ("""
|
||||||
|
SELECT COUNT(*) AS CNTREC FROM pragma_table_info('Devices') WHERE name='dev_SyncHubNodeName'
|
||||||
|
""").fetchone()[0] == 0
|
||||||
|
|
||||||
|
if dev_SyncHubNodeName_missing :
|
||||||
|
mylog('verbose', ["[upgradeDB] Adding dev_SyncHubNodeName to the Devices table"])
|
||||||
|
self.sql.execute("""
|
||||||
|
ALTER TABLE "Devices" ADD "dev_SyncHubNodeName" TEXT
|
||||||
|
""")
|
||||||
|
|
||||||
|
# dev_SourcePlugin column
|
||||||
|
dev_SourcePlugin_missing = self.sql.execute ("""
|
||||||
|
SELECT COUNT(*) AS CNTREC FROM pragma_table_info('Devices') WHERE name='dev_SourcePlugin'
|
||||||
|
""").fetchone()[0] == 0
|
||||||
|
|
||||||
|
if dev_SourcePlugin_missing :
|
||||||
|
mylog('verbose', ["[upgradeDB] Adding dev_SourcePlugin to the Devices table"])
|
||||||
|
self.sql.execute("""
|
||||||
|
ALTER TABLE "Devices" ADD "dev_SourcePlugin" TEXT
|
||||||
|
""")
|
||||||
|
|
||||||
# SQL to create Devices table with indexes
|
# SQL to create Devices table with indexes
|
||||||
sql_create_devices_new_tmp = """
|
sql_create_devices_new_tmp = """
|
||||||
@@ -743,7 +841,7 @@ class DB():
|
|||||||
columnNames = list(map(lambda x: x[0], self.sql.description))
|
columnNames = list(map(lambda x: x[0], self.sql.description))
|
||||||
rows = self.sql.fetchall()
|
rows = self.sql.fetchall()
|
||||||
except sqlite3.Error as e:
|
except sqlite3.Error as e:
|
||||||
mylog('none',[ '[Database] - SQL ERROR: ', e])
|
mylog('verbose',[ '[Database] - SQL ERROR: ', e])
|
||||||
return json_obj({}, []) # return empty object
|
return json_obj({}, []) # return empty object
|
||||||
|
|
||||||
result = {"data":[]}
|
result = {"data":[]}
|
||||||
@@ -768,9 +866,9 @@ class DB():
|
|||||||
rows = self.sql.fetchall()
|
rows = self.sql.fetchall()
|
||||||
return rows
|
return rows
|
||||||
except AssertionError:
|
except AssertionError:
|
||||||
mylog('none',[ '[Database] - ERROR: inconsistent query and/or arguments.', query, " params: ", args])
|
mylog('verbose',[ '[Database] - ERROR: inconsistent query and/or arguments.', query, " params: ", args])
|
||||||
except sqlite3.Error as e:
|
except sqlite3.Error as e:
|
||||||
mylog('none',[ '[Database] - SQL ERROR: ', e])
|
mylog('verbose',[ '[Database] - SQL ERROR: ', e])
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def read_one(self, query, *args):
|
def read_one(self, query, *args):
|
||||||
@@ -785,7 +883,7 @@ class DB():
|
|||||||
return rows[0]
|
return rows[0]
|
||||||
|
|
||||||
if len(rows) > 1:
|
if len(rows) > 1:
|
||||||
mylog('none',[ '[Database] - Warning!: query returns multiple rows, only first row is passed on!', query, " params: ", args])
|
mylog('verbose',[ '[Database] - Warning!: query returns multiple rows, only first row is passed on!', query, " params: ", args])
|
||||||
return rows[0]
|
return rows[0]
|
||||||
# empty result set
|
# empty result set
|
||||||
return None
|
return None
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ sys.path.extend([f"{INSTALL_PATH}/server"])
|
|||||||
|
|
||||||
from logger import mylog
|
from logger import mylog
|
||||||
from const import apiPath
|
from const import apiPath
|
||||||
|
from helper import is_random_mac, get_number_of_children, format_ip_long
|
||||||
|
|
||||||
# Define a base URL with the user's home directory
|
# Define a base URL with the user's home directory
|
||||||
folder = apiPath
|
folder = apiPath
|
||||||
@@ -57,6 +58,11 @@ class Device(ObjectType):
|
|||||||
devSSID = String()
|
devSSID = String()
|
||||||
devSyncHubNode = String()
|
devSyncHubNode = String()
|
||||||
devSourcePlugin = String()
|
devSourcePlugin = String()
|
||||||
|
devStatus = String()
|
||||||
|
devIsRandomMac = Int()
|
||||||
|
devParentChildrenCount = Int()
|
||||||
|
devIpLong = Int()
|
||||||
|
|
||||||
|
|
||||||
class DeviceResult(ObjectType):
|
class DeviceResult(ObjectType):
|
||||||
devices = List(Device)
|
devices = List(Device)
|
||||||
@@ -67,6 +73,7 @@ class Query(ObjectType):
|
|||||||
devices = Field(DeviceResult, options=PageQueryOptionsInput())
|
devices = Field(DeviceResult, options=PageQueryOptionsInput())
|
||||||
|
|
||||||
def resolve_devices(self, info, options=None):
|
def resolve_devices(self, info, options=None):
|
||||||
|
mylog('none', f'[graphql_schema] resolve_devices: {self}')
|
||||||
try:
|
try:
|
||||||
with open(folder + 'table_devices.json', 'r') as f:
|
with open(folder + 'table_devices.json', 'r') as f:
|
||||||
devices_data = json.load(f)["data"]
|
devices_data = json.load(f)["data"]
|
||||||
@@ -74,16 +81,19 @@ class Query(ObjectType):
|
|||||||
mylog('none', f'[graphql_schema] Error loading devices data: {e}')
|
mylog('none', f'[graphql_schema] Error loading devices data: {e}')
|
||||||
return DeviceResult(devices=[], count=0)
|
return DeviceResult(devices=[], count=0)
|
||||||
|
|
||||||
|
|
||||||
|
# Add dynamic fields to each device
|
||||||
|
for device in devices_data:
|
||||||
|
device["devIsRandomMac"] = 1 if is_random_mac(device["devMac"]) else 0
|
||||||
|
device["devParentChildrenCount"] = get_number_of_children(device["devMac"], devices_data)
|
||||||
|
device["devIpLong"] = format_ip_long(device.get("devLastIP", ""))
|
||||||
|
|
||||||
total_count = len(devices_data)
|
total_count = len(devices_data)
|
||||||
|
|
||||||
# Apply pagination and sorting if options are provided
|
mylog('none', f'[graphql_schema] devices_data: {devices_data}')
|
||||||
if options:
|
|
||||||
# Implement pagination and sorting here
|
|
||||||
if options.page and options.limit:
|
|
||||||
start = (options.page - 1) * options.limit
|
|
||||||
end = start + options.limit
|
|
||||||
devices_data = devices_data[start:end]
|
|
||||||
|
|
||||||
|
# Apply sorting if options are provided
|
||||||
|
if options:
|
||||||
if options.sort:
|
if options.sort:
|
||||||
for sort_option in options.sort:
|
for sort_option in options.sort:
|
||||||
devices_data = sorted(
|
devices_data = sorted(
|
||||||
@@ -91,7 +101,7 @@ class Query(ObjectType):
|
|||||||
key=lambda x: x.get(sort_option.field),
|
key=lambda x: x.get(sort_option.field),
|
||||||
reverse=(sort_option.order.lower() == "desc")
|
reverse=(sort_option.order.lower() == "desc")
|
||||||
)
|
)
|
||||||
|
|
||||||
# Filter data if a search term is provided
|
# Filter data if a search term is provided
|
||||||
if options.search:
|
if options.search:
|
||||||
devices_data = [
|
devices_data = [
|
||||||
@@ -99,7 +109,17 @@ class Query(ObjectType):
|
|||||||
if options.search.lower() in device.get("devName", "").lower()
|
if options.search.lower() in device.get("devName", "").lower()
|
||||||
]
|
]
|
||||||
|
|
||||||
return DeviceResult(devices=devices_data, count=total_count)
|
# Then apply pagination
|
||||||
|
if options.page and options.limit:
|
||||||
|
start = (options.page - 1) * options.limit
|
||||||
|
end = start + options.limit
|
||||||
|
devices_data = devices_data[start:end]
|
||||||
|
|
||||||
|
# Convert dict objects to Device instances to enable field resolution
|
||||||
|
devices = [Device(**device) for device in devices_data]
|
||||||
|
|
||||||
|
return DeviceResult(devices=devices, count=total_count)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# Schema Definition
|
# Schema Definition
|
||||||
|
|||||||
@@ -12,7 +12,8 @@ INSTALL_PATH="/app"
|
|||||||
sys.path.extend([f"{INSTALL_PATH}/server"])
|
sys.path.extend([f"{INSTALL_PATH}/server"])
|
||||||
|
|
||||||
from logger import mylog
|
from logger import mylog
|
||||||
from helper import get_setting_value
|
from helper import get_setting_value, timeNowTZ
|
||||||
|
from notification import write_notification
|
||||||
|
|
||||||
app = Flask(__name__)
|
app = Flask(__name__)
|
||||||
|
|
||||||
@@ -24,22 +25,23 @@ def graphql_endpoint():
|
|||||||
# Check for API token in headers
|
# Check for API token in headers
|
||||||
token = request.headers.get("Authorization")
|
token = request.headers.get("Authorization")
|
||||||
if token != f"Bearer {API_TOKEN}":
|
if token != f"Bearer {API_TOKEN}":
|
||||||
mylog('none', [f'[graphql_server] Unauthorized access attempt'])
|
mylog('verbose', [f'[graphql_server] Unauthorized access attempt'])
|
||||||
|
|
||||||
return jsonify({"error": "Unauthorized"}), 401
|
return jsonify({"error": "Unauthorized"}), 401
|
||||||
|
|
||||||
data = request.get_json()
|
data = request.get_json()
|
||||||
mylog('none', [f'[graphql_server] data: {data}'])
|
mylog('verbose', [f'[graphql_server] data: {data}'])
|
||||||
|
|
||||||
|
|
||||||
# Use the schema to execute the GraphQL query
|
# Use the schema to execute the GraphQL query
|
||||||
result = devicesSchema.execute(data.get("query"), variables=data.get("variables"))
|
result = devicesSchema.execute(data.get("query"), variables=data.get("variables"))
|
||||||
mylog('none', [f'[graphql_server] result: {result}'])
|
|
||||||
|
|
||||||
# Return the data from the query in JSON format
|
# Return the data from the query in JSON format
|
||||||
return jsonify(result.data)
|
return jsonify(result.data)
|
||||||
|
|
||||||
def start_server():
|
def start_server():
|
||||||
"""Function to start the GraphQL server in a background thread."""
|
"""Function to start the GraphQL server in a background thread."""
|
||||||
mylog('none', [f'[graphql_server] Starting on port "{GRAPHQL_PORT}"'])
|
mylog('verbose', [f'[graphql_server] Starting on port: {GRAPHQL_PORT}'])
|
||||||
|
|
||||||
# Start the Flask app in a separate thread
|
# Start the Flask app in a separate thread
|
||||||
thread = threading.Thread(target=lambda: app.run(host="0.0.0.0", port=GRAPHQL_PORT, debug=True, use_reloader=False))
|
thread = threading.Thread(target=lambda: app.run(host="0.0.0.0", port=GRAPHQL_PORT, debug=True, use_reloader=False))
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ import base64
|
|||||||
import hashlib
|
import hashlib
|
||||||
import random
|
import random
|
||||||
import string
|
import string
|
||||||
|
import ipaddress
|
||||||
|
|
||||||
|
|
||||||
import conf
|
import conf
|
||||||
@@ -911,6 +912,42 @@ def generate_random_string(length):
|
|||||||
characters = string.ascii_letters + string.digits
|
characters = string.ascii_letters + string.digits
|
||||||
return ''.join(random.choice(characters) for _ in range(length))
|
return ''.join(random.choice(characters) for _ in range(length))
|
||||||
|
|
||||||
|
|
||||||
|
# Helper function to determine if a MAC address is random
|
||||||
|
def is_random_mac(mac):
|
||||||
|
# Check if second character matches "2", "6", "A", "E" (case insensitive)
|
||||||
|
is_random = mac[1].upper() in ["2", "6", "A", "E"]
|
||||||
|
|
||||||
|
# Check against user-defined non-random MAC prefixes
|
||||||
|
if is_random:
|
||||||
|
not_random_prefixes = get_setting_value("UI_NOT_RANDOM_MAC")
|
||||||
|
for prefix in not_random_prefixes:
|
||||||
|
if mac.startswith(prefix):
|
||||||
|
is_random = False
|
||||||
|
break
|
||||||
|
return is_random
|
||||||
|
|
||||||
|
# Helper function to calculate number of children
|
||||||
|
def get_number_of_children(mac, devices):
|
||||||
|
# Count children by checking devParentMAC for each device
|
||||||
|
return sum(1 for dev in devices if dev.get("devParentMAC", "").strip() == mac.strip())
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# Function to convert IP to a long integer
|
||||||
|
def format_ip_long(ip_address):
|
||||||
|
try:
|
||||||
|
# Check if it's an IPv6 address
|
||||||
|
if ':' in ip_address:
|
||||||
|
ip = ipaddress.IPv6Address(ip_address)
|
||||||
|
else:
|
||||||
|
# Assume it's an IPv4 address
|
||||||
|
ip = ipaddress.IPv4Address(ip_address)
|
||||||
|
return int(ip)
|
||||||
|
except ValueError:
|
||||||
|
# Return a default error value if IP is invalid
|
||||||
|
return -1
|
||||||
|
|
||||||
#-------------------------------------------------------------------------------
|
#-------------------------------------------------------------------------------
|
||||||
# JSON methods
|
# JSON methods
|
||||||
#-------------------------------------------------------------------------------
|
#-------------------------------------------------------------------------------
|
||||||
|
|||||||
Reference in New Issue
Block a user