GraphQL Settings

This commit is contained in:
jokob-sk
2024-12-07 19:25:07 +11:00
parent 79c4574e21
commit d7858c6042
4 changed files with 154 additions and 65 deletions

View File

@@ -5,7 +5,7 @@ The Main Info section is where most of the device identifyiable information is s
> [!NOTE] > [!NOTE]
> >
> You can multi-edit devices by selecting them in the main Devices view, from the Mainetence section, or via the CSV Export fucntionality under Maintenance. More info can be found in the [Devices Bulk-editing docs](https://github.com/jokob-sk/NetAlertX/blob/main/docs/DEVICES_BULK_EDITING.md). > You can multi-edit devices by selecting them in the main Devices view, from the Mainetence section, or via the CSV Export functionality under Maintenance. More info can be found in the [Devices Bulk-editing docs](https://github.com/jokob-sk/NetAlertX/blob/main/docs/DEVICES_BULK_EDITING.md).
![Main Info](/docs/img/DEVICE_MANAGEMENT/DeviceManagement_MainInfo.png) ![Main Info](/docs/img/DEVICE_MANAGEMENT/DeviceManagement_MainInfo.png)
@@ -32,12 +32,18 @@ The Main Info section is where most of the device identifyiable information is s
## Dummy devices ## Dummy devices
You can create dummy devices from the Devices listing screen. The **MAC** field and the **Last IP** field will then become editable. You can create dummy devices from the Devices listing screen.
![Create Dummy Device](/docs/img/DEVICE_MANAGEMENT/Devices_CreateDummyDevice.png) ![Create Dummy Device](/docs/img/DEVICE_MANAGEMENT/Devices_CreateDummyDevice.png)
The **MAC** field and the **Last IP** field will then become editable.
![Save Dummy Device](/docs/img/DEVICE_MANAGEMENT/DeviceEdit_SaveDummyDevice.png) ![Save Dummy Device](/docs/img/DEVICE_MANAGEMENT/DeviceEdit_SaveDummyDevice.png)
You can couple this with the `ICMP` plugin which can be used to monitor the status of these devices, if they are actual devices reachable with the ping command.
> [!NOTE]
>
> You can couple this with the `ICMP` plugin which can be used to monitor the status of these devices, if they are actual devices reachable with the `ping` command. If not, you can use a loopback IP address so they appear online, such as `0.0.0.0` or `127.0.0.1`.
## Copying data from an existing device. ## Copying data from an existing device.

View File

@@ -2,7 +2,7 @@
Make sure you have a root device with the MAC `Internet` (No other MAC addresses are currently supported as the root node) set to a network device type (e.g.: **Type**:`Router`). Make sure you have a root device with the MAC `Internet` (No other MAC addresses are currently supported as the root node) set to a network device type (e.g.: **Type**:`Router`).
> 💡 Tip: You can add dummy devices via the [Undiscoverables plugin](https://github.com/jokob-sk/NetAlertX/blob/main/front/plugins/undiscoverables/README.md) > 💡 Tip: You can add dummy devices via the [Create dummy device](https://github.com/jokob-sk/NetAlertX/blob/main/docs/DEVICE_MANAGEMENT.md#dummy-devices) button in the Devices listing page.
> 💡 Tip: Export your configuration of the Network and Devices once in a while via the Export CSV feature under **Maintenance** -> **Backup/Restore** -> **CSV Export**. > 💡 Tip: Export your configuration of the Network and Devices once in a while via the Export CSV feature under **Maintenance** -> **Backup/Restore** -> **CSV Export**.

View File

@@ -177,69 +177,105 @@ $settingsJSON_DB = json_encode($settings, JSON_HEX_TAG | JSON_HEX_AMP | JSON_HEX
console.log("in getData"); console.log("in getData");
$.get('api/table_settings.json?nocache=' + Date.now(), function(res) { // get settings from the secured graphql endpoint
$.ajax({
settingsData = res["data"]; url: "/php/server/query_graphql.php", // Replace with your GraphQL endpoint
method: "POST",
// Wrong number of settings processing contentType: "application/json",
if(settingsNumberDB != settingsData.length) data: JSON.stringify({
{ query: `
showModalOk('WARNING', "<?= lang("settings_old")?>"); query {
setTimeout(() => { settings {
clearCache() settings {
}, 3000); setKey
} else setName
{ setDescription
$.get('api/plugins.json?nocache=' + Date.now(), function(res) { setOptions
setGroup
pluginsData = res["data"]; setType
setValue
// Sort settingsData alphabetically based on the "setGroup" property setEvents
settingsData.sort((a, b) => { setOverriddenByEnv
if (a["setGroup"] < b["setGroup"]) { }
return -1; count
} }
if (a["setGroup"] > b["setGroup"]) {
return 1;
}
return 0;
});
exception_occurred = false;
// check if cache needs to be refreshed
// the getSetting method returns an empty string even if a setting is not found
// however, __metadata needs to be always a JSON object
// let's use that to verify settings were initialized correctly
settingsData.forEach((set) => {
setKey = set['setKey']
try {
const isMetadata = setKey.includes('__metadata');
// if this isn't a metadata entry, get corresponding metadata object from the dummy setting
const setObj = isMetadata ? {} : JSON.parse(getSetting(`${setKey}__metadata`));
} catch (error) {
console.error(`Error getting setting for ${setKey}:`, error);
showModalOk('WARNING', "Outdated cache - refreshing (refresh browser cache if needed)");
setTimeout(() => {
clearCache()
}, 3000);
exception_occurred = true;
} }
}); `
}),
// only proceed if everything was loaded correctly success: function (response) {
if(!exception_occurred) console.log("Response:", response);
{
initSettingsPage(settingsData, pluginsData); // Handle the successful response
if (response && response.settings) {
const settingsData = response.settings.settings;
console.log("Settings:", settingsData);
// Wrong number of settings processing
if(settingsNumberDB != settingsData.length)
{
showModalOk('WARNING', "<?= lang("settings_old")?>");
setTimeout(() => {
clearCache()
}, 3000);
} else
{
$.get('api/plugins.json?nocache=' + Date.now(), function(res) {
pluginsData = res["data"];
// Sort settingsData alphabetically based on the "setGroup" property
settingsData.sort((a, b) => {
if (a["setGroup"] < b["setGroup"]) {
return -1;
}
if (a["setGroup"] > b["setGroup"]) {
return 1;
}
return 0;
});
exception_occurred = false;
// check if cache needs to be refreshed
// the getSetting method returns an empty string even if a setting is not found
// however, __metadata needs to be always a JSON object
// let's use that to verify settings were initialized correctly
settingsData.forEach((set) => {
setKey = set['setKey']
try {
const isMetadata = setKey.includes('__metadata');
// if this isn't a metadata entry, get corresponding metadata object from the dummy setting
const setObj = isMetadata ? {} : JSON.parse(getSetting(`${setKey}__metadata`));
} catch (error) {
console.error(`Error getting setting for ${setKey}:`, error);
showModalOk('WARNING', "Outdated cache - refreshing (refresh browser cache if needed)");
setTimeout(() => {
clearCache()
}, 3000);
exception_occurred = true;
}
});
// only proceed if everything was loaded correctly
if(!exception_occurred)
{
initSettingsPage(settingsData, pluginsData);
}
})
}
} }
}) },
} error: function (xhr, status, error) {
}) console.error("Error:", error);
// Handle any errors
}
});
} }
// ------------------------------------------------------------------- // -------------------------------------------------------------------

View File

@@ -14,11 +14,13 @@ from helper import is_random_mac, get_number_of_children, format_ip_long, get_se
# Define a base URL with the user's home directory # Define a base URL with the user's home directory
folder = apiPath folder = apiPath
# --- DEVICES ---
# Pagination and Sorting Input Types # Pagination and Sorting Input Types
class SortOptionsInput(InputObjectType): class SortOptionsInput(InputObjectType):
field = String() field = String()
order = String() order = String()
class PageQueryOptionsInput(InputObjectType): class PageQueryOptionsInput(InputObjectType):
page = Int() page = Int()
limit = Int() limit = Int()
@@ -26,6 +28,7 @@ class PageQueryOptionsInput(InputObjectType):
search = String() search = String()
status = String() status = String()
# Device ObjectType # Device ObjectType
class Device(ObjectType): class Device(ObjectType):
rowid = Int() rowid = Int()
@@ -70,8 +73,30 @@ class DeviceResult(ObjectType):
devices = List(Device) devices = List(Device)
count = Int() count = Int()
# --- SETTINGS ---
# Setting ObjectType
class Setting(ObjectType):
setKey = String()
setName = String()
setDescription = String()
setType = String()
setOptions = String()
setGroup = String()
setValue = String()
setEvents = String()
setOverriddenByEnv = Boolean()
class SettingResult(ObjectType):
settings = List(Setting)
count = Int()
# Define Query Type with Pagination Support # Define Query Type with Pagination Support
class Query(ObjectType): class Query(ObjectType):
# --- DEVICES ---
devices = Field(DeviceResult, options=PageQueryOptionsInput()) devices = Field(DeviceResult, options=PageQueryOptionsInput())
def resolve_devices(self, info, options=None): def resolve_devices(self, info, options=None):
@@ -175,6 +200,28 @@ class Query(ObjectType):
return DeviceResult(devices=devices, count=total_count) return DeviceResult(devices=devices, count=total_count)
# --- SETTINGS ---
settings = Field(SettingResult)
def resolve_settings(root, info):
try:
with open(folder + 'table_settings.json', 'r') as f:
settings_data = json.load(f)["data"]
except (FileNotFoundError, json.JSONDecodeError) as e:
mylog('none', f'[graphql_schema] Error loading settings data: {e}')
return SettingResult(settings=[], count=0)
mylog('none', f'[graphql_schema] settings_data: {settings_data}')
# # Convert to Setting objects
settings = [Setting(**setting) for setting in settings_data]
return SettingResult(settings=settings, count=len(settings))
# helps sorting inconsistent dataset mixed integers and strings # helps sorting inconsistent dataset mixed integers and strings
def mixed_type_sort_key(value): def mixed_type_sort_key(value):
if value is None or value == "": if value is None or value == "":