From 8a8df3c7b887202b464a6a74872ac1469a92d5a1 Mon Sep 17 00:00:00 2001 From: jokob-sk Date: Mon, 3 Jun 2024 22:24:06 +1000 Subject: [PATCH] =?UTF-8?q?=F0=9F=94=83=20Node=20sync=20v0.2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- front/js/common.js | 23 +- front/js/settings_utils.js | 1 + front/js/ui_components.js | 20 + front/plugins/node_sync/README.md | 13 - front/plugins/node_sync/config.json | 259 ------------ front/plugins/node_sync/ignore_plugin | 0 front/plugins/node_sync/script.py | 100 ----- front/plugins/node_sync/server.php | 0 front/plugins/sync/README.md | 11 + front/plugins/sync/config.json | 545 ++++++++++++++++++++++++++ front/plugins/sync/hub.php | 47 +++ front/plugins/sync/sync.py | 104 +++++ 12 files changed, 749 insertions(+), 374 deletions(-) delete mode 100755 front/plugins/node_sync/README.md delete mode 100755 front/plugins/node_sync/config.json delete mode 100755 front/plugins/node_sync/ignore_plugin delete mode 100755 front/plugins/node_sync/script.py delete mode 100755 front/plugins/node_sync/server.php create mode 100755 front/plugins/sync/README.md create mode 100755 front/plugins/sync/config.json create mode 100755 front/plugins/sync/hub.php create mode 100755 front/plugins/sync/sync.py diff --git a/front/js/common.js b/front/js/common.js index 85b0aeb7..e2e71e36 100755 --- a/front/js/common.js +++ b/front/js/common.js @@ -144,7 +144,16 @@ function cacheSettings() if(options_params != []) { // handles only strings of length == 1 - resolvedOptions = `["${resolveParams(options_params, resolvedOptions[0])}"]` + + resolved = resolveParams(options_params, resolvedOptions[0]) + + if(resolved.includes('"')) // check if list of strings + { + resolvedOptions = `[${resolved}]` + } else // one value only + { + resolvedOptions = `["${resolved}"]` + } } } } @@ -1027,8 +1036,18 @@ function resolveParams(params, template) { // If the parameter type is 'setting', retrieve setting value if (param.type == "setting") { var value = getSetting(param.value); + + // Remove brackets and single quotes, replace them with double quotes + value = value.replace('[','').replace(']','').replace(/'/g, '"'); + + // Split the string into an array, remove empty elements + const arr = value.split(',').filter(Boolean); + + // Join the array elements with commas + const result = arr.join(', '); + // Replace placeholder with setting value - template = template.replace("{" + param.name + "}", value); + template = template.replace("{" + param.name + "}", result); } else { // If the parameter type is not 'setting', use the provided value template = template.replace("{" + param.name + "}", param.value); diff --git a/front/js/settings_utils.js b/front/js/settings_utils.js index ffd9641b..d431194a 100755 --- a/front/js/settings_utils.js +++ b/front/js/settings_utils.js @@ -539,6 +539,7 @@ function getParam(targetId, key, skipCache = false) { // optionsArray = getSettingOptions(set['Code_Name'] ) valuesArray = createArray(set['Value']); + // create unique ID var targetLocation = set['Code_Name'] + "_initSettingDropdown"; diff --git a/front/js/ui_components.js b/front/js/ui_components.js index f78b4aeb..c362cfa1 100755 --- a/front/js/ui_components.js +++ b/front/js/ui_components.js @@ -95,9 +95,29 @@ function initSettingDropdown(settingKey, // Identifier for the setting { var optionsHtml = "" + + + if(settingKey == 'SYNC_plugins' || settingKey == 'VNDRPDT_WATCH') + { + console.log('getSettingOptions(settingKey)'); + console.log(getSettingOptions(settingKey)); + + } + optionsArray = createArray(getSettingOptions(settingKey)) + + if(settingKey == 'SYNC_plugins' || settingKey == 'VNDRPDT_WATCH') + { + console.log('settingKey'); + console.log(settingKey); + console.log('valuesArray'); + console.log(valuesArray); + console.log('optionsArray'); + console.log(optionsArray); + } + // check if the result is a SQL query if(isSQLQuery(optionsArray[0])) { diff --git a/front/plugins/node_sync/README.md b/front/plugins/node_sync/README.md deleted file mode 100755 index b6e106be..00000000 --- a/front/plugins/node_sync/README.md +++ /dev/null @@ -1,13 +0,0 @@ -## Overview - -A simple setting-based plugin for setting the password. - -### Usage - -- Head to **Settings** > **Set Password** to adjust the default values. - -### Notes - -- The default password is 123456. -- When enabled a login dialog is displayed. If facing issues, you can always disable the login by setting SETPWD_enable_password=False in your app.conf file. -- SHA256 hash is used \ No newline at end of file diff --git a/front/plugins/node_sync/config.json b/front/plugins/node_sync/config.json deleted file mode 100755 index ac5736be..00000000 --- a/front/plugins/node_sync/config.json +++ /dev/null @@ -1,259 +0,0 @@ -{ - "code_name": "node_sync", - "template_type": "database-entry", - "unique_prefix": "NODESYNC", - "plugin_type": "system", - "enabled": true, - "data_source": "template", - "show_ui": false, - "localized": ["display_name", "description", "icon"], - "display_name": [{ - "language_code": "en_us", - "string": "Node synchronization" - }], - "description": [{ - "language_code": "en_us", - "string": "Plugin to synchronize multiple NetAlertX instances." - }], - "icon": [ - { - "language_code": "en_us", - "string": "" - } - ], - "params" : [ - { - "name" : "password", - "type" : "setting", - "value" : "SETPWD_password" - } - ], - "settings":[ - { - "function": "enable", - "type": "boolean", - "default_value": false, - "options": [], - "localized": ["name", "description"], - "name": [ - { - "language_code": "en_us", - "string": "Enable login" - } - ], - "description": [ - { - "language_code": "en_us", - "string": "When enabled a login dialog is displayed. If facing issues, you can always disable the login by setting SETPWD_enable_password=False in your app.conf file." - } - ] - }, - { - "function": "plugins", - "type": "text.multiselect", - "maxLength": 50, - "default_value": [ - ], - "options": ["{value}"], - "options_params" : [ - { - "name" : "value", - "type" : "setting", - "value" : "LOADED_PLUGINS" - } - ], - "localized": ["name", "description"], - "name": [ - { - "language_code": "en_us", - "string": "Plugins" - } - ], - "description": [ - { - "language_code": "en_us", - "string": "Plugins to synchronize. Only plugins that produce some kind of output in last_result.log can be synchronized." - } - ] - }, - { - "function": "target_url", - "type": "text", - "maxLength": 50, - "default_value": "", - "options": [], - "localized": ["name", "description"], - "name": [ - { - "language_code": "en_us", - "string": "Target URL" - } - ], - "description": [ - { - "language_code": "en_us", - "string": "Target URL to send the data to." - } - ] - }, - { - "function": "password", - "type": "password.SHA256", - "maxLength": 50, - "default_value": "", - "options": [], - "localized": ["name", "description"], - "name": [ - { - "language_code": "en_us", - "string": "Password" - }, - { - "language_code": "es_es", - "string": "Contraseña" - } - ], - "description": [ - { - "language_code": "en_us", - "string": "The password " - } - ] - },{ - "function": "RUN", - "events": ["run"], - "type": "text.select", - "default_value":"schedule", - "options": ["disabled", "once", "schedule", "always_after_scan", "on_new_device"], - "localized": ["name", "description"], - "name" :[{ - "language_code":"en_us", - "string" : "When to run" - }, - { - "language_code":"es_es", - "string" : "Cuándo ejecutar" - }, - { - "language_code":"de_de", - "string" : "Wann laufen" - }], - "description": [{ - "language_code":"en_us", - "string" : "When the backup should be created. A daily or weekly SCHEDULE is a good option." - }, - { - "language_code":"es_es", - "string" : "Cuándo se debe crear la copia de seguridad. Un SCHEDULE diario o semanal es una buena opción." - }, - { - "language_code":"de_de", - "string" : "Wann das Backup erstellt werden soll. Ein täglicher oder wöchentlicher SCHEDULE ist eine gute Option." - }] -}, - { - "function": "CMD", - "type": "readonly", - "default_value": "python3 /app/front/plugins/csv_backup/script.py overwrite={overwrite} location={location}", - "options": [], - "localized": ["name", "description"], - "name": [ - { - "language_code": "en_us", - "string": "Command" - }, - { - "language_code": "es_es", - "string": "Comando" - }, - { - "language_code": "de_de", - "string": "Befehl" - } - ], - "description": [ - { - "language_code": "en_us", - "string": "Command to run. This can not be changed" - }, - { - "language_code": "es_es", - "string": "Comando a ejecutar. Esto no se puede cambiar" - }, - { - "language_code": "de_de", - "string": "Befehl zum Ausführen. Dies kann nicht geändert werden" - } - ] - }, - { - "function": "RUN_SCHD", - "type": "text", - "default_value":"0 2 * * 3", - "options": [], - "localized": ["name", "description"], - "name" : [{ - "language_code":"en_us", - "string" : "Schedule" - }, - { - "language_code":"es_es", - "string" : "Schedule" - }, - { - "language_code":"de_de", - "string" : "Schedule" - }], - "description": [{ - "language_code":"en_us", - "string" : "Only enabled if you select schedule in the CSVBCKP_RUN setting. Make sure you enter the schedule in the correct cron-like format (e.g. validate at crontab.guru). For example entering 0 4 * * * will run the scan after 4 am in the TIMEZONE you set above. Will be run NEXT time the time passes." - }, - { - "language_code":"es_es", - "string" : "Solo está habilitado si selecciona schedule en la configuración CSVBCKP_RUN. Asegúrese de ingresar la programación en el formato similar a cron correcto (por ejemplo, valide en crontab.guru). Por ejemplo, ingresar 0 4 * * * ejecutará el escaneo después de las 4 a.m. en el TIMEZONE que configuró arriba. Se ejecutará la PRÓXIMA vez que pase el tiempo." - }, - { - "language_code":"de_de", - "string" : "Nur aktiviert, wenn Sie schedule in der CSVBCKP_RUN-Einstellung auswählen. Stellen Sie sicher, dass Sie den Zeitplan im richtigen Cron-ähnlichen Format eingeben (z. B. validieren unter crontab.guru). Wenn Sie beispielsweise 0 4 * * * eingeben, wird der Scan nach 4 Uhr morgens in der TIMEZONE den Sie oben festgelegt haben. Wird das NÄCHSTE Mal ausgeführt, wenn die Zeit vergeht." - }] - }, - { - "function": "RUN_TIMEOUT", - "type": "integer", - "default_value": 30, - "options": [], - "localized": ["name", "description"], - "name": [ - { - "language_code": "en_us", - "string": "Run timeout" - }, - { - "language_code": "es_es", - "string": "Tiempo límite de ejecución" - }, - { - "language_code": "de_de", - "string": "Zeitüberschreitung" - } - ], - "description": [ - { - "language_code": "en_us", - "string": "Maximum time in seconds to wait for the script to finish. If this time is exceeded the script is aborted." - }, - { - "language_code": "es_es", - "string": "Tiempo máximo en segundos para esperar a que finalice el script. Si se supera este tiempo, el script se cancela." - }, - { - "language_code": "de_de", - "string": "Maximale Zeit in Sekunden, die auf den Abschluss des Skripts gewartet werden soll. Bei Überschreitung dieser Zeit wird das Skript abgebrochen." - } - ] - } - - - ] - - } diff --git a/front/plugins/node_sync/ignore_plugin b/front/plugins/node_sync/ignore_plugin deleted file mode 100755 index e69de29b..00000000 diff --git a/front/plugins/node_sync/script.py b/front/plugins/node_sync/script.py deleted file mode 100755 index 97ef2081..00000000 --- a/front/plugins/node_sync/script.py +++ /dev/null @@ -1,100 +0,0 @@ -#!/usr/bin/env python - -import os -import pathlib -import argparse -import sys -import hashlib -import csv -import sqlite3 -from io import StringIO -from datetime import datetime - -# Register NetAlertX directories -INSTALL_PATH="/app" -sys.path.extend([f"{INSTALL_PATH}/front/plugins", f"{INSTALL_PATH}/server"]) - -from plugin_helper import Plugin_Object, Plugin_Objects, decodeBase64 -from logger import mylog, append_line_to_file -from helper import timeNowTZ -from const import logPath, applicationPath, fullDbPath - - -CUR_PATH = str(pathlib.Path(__file__).parent.resolve()) -LOG_FILE = os.path.join(CUR_PATH, 'script.log') -RESULT_FILE = os.path.join(CUR_PATH, 'last_result.log') - -pluginName = 'NODESYNC' - -def main(): - - # the script expects a parameter in the format of devices=device1,device2,... - parser = argparse.ArgumentParser(description='Export devices data to CSV') - parser.add_argument('overwrite', action="store", help="Specify 'TRUE' to overwrite an existing file, or 'FALSE' to create a new file") - parser.add_argument('location', action="store", help="The directory where the CSV file will be saved") - values = parser.parse_args() - - overwrite = values.overwrite.split('=')[1] - - if (overwrite.upper() == "TRUE"): - overwrite = True - else: - overwrite = False - - mylog('verbose', [f'[{pluginName}] In script']) - - # Connect to the App database - conn = sqlite3.connect(fullDbPath) - cursor = conn.cursor() - - # Execute your SQL query - cursor.execute("SELECT * FROM Devices") - - # Get column names - columns = [desc[0] for desc in cursor.description] - - if overwrite: - filename = 'devices.csv' - else: - timestamp = datetime.now().strftime('%Y%m%d%H%M%S') - filename = f'devices_{timestamp}.csv' - - fullPath = os.path.join(values.location.split('=')[1], filename) - - mylog('verbose', ['[CSVBCKP] Writing file ', fullPath]) - - # Create a CSV file in the specified location - with open(fullPath, 'w', newline='') as csvfile: - # Initialize the CSV writer - csv_writer = csv.writer(csvfile, delimiter=',', quoting=csv.QUOTE_MINIMAL) - - # Wrap the header values in double quotes and write the header row - csv_writer.writerow([ '"' + col + '"' for col in columns]) - - # Fetch and write data rows - for row in cursor.fetchall(): - # Wrap each value in double quotes and write the row - csv_writer.writerow(['"' + str(value) + '"' for value in row]) - - # Close the database connection - conn.close() - - # Open the CSV file for reading - with open(fullPath, 'r') as file: - data = file.read() - - # Replace all occurrences of """ with " - data = data.replace('"""', '"') - - # Open the CSV file for writing - with open(fullPath, 'w') as file: - file.write(data) - - return 0 - - -#=============================================================================== -# BEGIN -#=============================================================================== -if __name__ == '__main__': - main() \ No newline at end of file diff --git a/front/plugins/node_sync/server.php b/front/plugins/node_sync/server.php deleted file mode 100755 index e69de29b..00000000 diff --git a/front/plugins/sync/README.md b/front/plugins/sync/README.md new file mode 100755 index 00000000..4f03eff6 --- /dev/null +++ b/front/plugins/sync/README.md @@ -0,0 +1,11 @@ +## Overview + +Synchronization plugin to synchronize multiple app instances. The plugin sends encrypted `last_result.log` files for individual plugins. + +### Usage + +- Head to **Settings** > **Sync Hub** to adjust the default values. + +### Notes + +- TBC \ No newline at end of file diff --git a/front/plugins/sync/config.json b/front/plugins/sync/config.json new file mode 100755 index 00000000..2b96df65 --- /dev/null +++ b/front/plugins/sync/config.json @@ -0,0 +1,545 @@ +{ + "code_name": "sync", + "template_type": "database-entry", + "unique_prefix": "SYNC", + "plugin_type": "system", + "enabled": true, + "data_source": "template", + "show_ui": false, + "localized": ["display_name", "description", "icon"], + "display_name": [{ + "language_code": "en_us", + "string": "Sync Hub" + }], + "description": [{ + "language_code": "en_us", + "string": "Plugin to synchronize multiple NetAlertX instances." + }], + "icon": [ + { + "language_code": "en_us", + "string": "" + } + ], + "params" : [], + "database_column_definitions": [ + { + "column": "Index", + "css_classes": "col-sm-2", + "show": false, + "type": "label", + "default_value": "", + "options": [], + "localized": [ + "name" + ], + "name": [ + { + "language_code": "en_us", + "string": "N/A" + }, + { + "language_code": "es_es", + "string": "N/A" + } + ] + }, + { + "column": "Plugin", + "css_classes": "col-sm-2", + "show": false, + "type": "label", + "default_value": "", + "options": [], + "localized": [ + "name" + ], + "name": [ + { + "language_code": "en_us", + "string": "N/A" + }, + { + "language_code": "es_es", + "string": "N/A" + } + ] + }, + { + "column": "Object_PrimaryID", + "css_classes": "col-sm-2", + "show": true, + "type": "label", + "default_value": "", + "options": [], + "localized": [ + "name" + ], + "name": [ + { + "language_code": "en_us", + "string": "Plugin" + } + ] + }, + { + "column": "Object_SecondaryID", + "css_classes": "col-sm-2", + "show": false, + "type": "label", + "default_value": "", + "options": [], + "localized": [ + "name" + ], + "name": [ + { + "language_code": "en_us", + "string": "Time" + } + ] + }, + { + "column": "DateTimeCreated", + "css_classes": "col-sm-2", + "show": true, + "type": "label", + "default_value": "", + "options": [], + "localized": [ + "name" + ], + "name": [ + { + "language_code": "en_us", + "string": "Sent when" + } + ] + }, + { + "column": "DateTimeChanged", + "css_classes": "col-sm-2", + "show": false, + "type": "label", + "default_value": "", + "options": [], + "localized": [ + "name" + ], + "name": [ + { + "language_code": "en_us", + "string": "Changed" + } + ] + }, + { + "column": "Watched_Value1", + "css_classes": "col-sm-2", + "show": true, + "type": "label", + "default_value":"", + "options": [ + ], + "localized": [ + "name" + ], + "name": [ + { + "language_code": "en_us", + "string": "Node name" + } + ] + }, + { + "column": "Watched_Value2", + "css_classes": "col-sm-8", + "show": true, + "type": "label", + "default_value": "", + "options": [], + "localized": [ + "name" + ], + "name": [ + { + "language_code": "en_us", + "string": "Status code" + } + ] + }, + { + "column": "Watched_Value3", + "css_classes": "col-sm-2", + "show": true, + "type": "textarea_readonly", + "default_value": "", + "options": [], + "localized": [ + "name" + ], + "name": [ + { + "language_code": "en_us", + "string": "Response" + } + ] + }, + { + "column": "Watched_Value4", + "css_classes": "col-sm-2", + "show": false, + "type": "label", + "default_value": "", + "options": [], + "localized": [ + "name" + ], + "name": [ + { + "language_code": "en_us", + "string": "N/A" + } + ] + }, + { + "column": "UserData", + "css_classes": "col-sm-2", + "show": false, + "type": "textbox_save", + "default_value": "", + "options": [], + "localized": [ + "name" + ], + "name": [ + { + "language_code": "en_us", + "string": "Comments" + } + ] + }, + { + "column": "Status", + "css_classes": "col-sm-1", + "show": false, + "type": "replace", + "default_value": "", + "options": [ + { + "equals": "watched-not-changed", + "replacement": "
" + }, + { + "equals": "watched-changed", + "replacement": "
" + }, + { + "equals": "new", + "replacement": "
" + }, + { + "equals": "missing-in-last-scan", + "replacement": "
" + } + ], + "localized": [ + "name" + ], + "name": [ + { + "language_code": "en_us", + "string": "Status" + }, + { + "language_code": "es_es", + "string": "Estado" + } + ] + }, + { + "column": "Extra", + "css_classes": "col-sm-3", + "show": false, + "type": "label", + "default_value": "", + "options": [], + "localized": [ + "name" + ], + "name": [ + { + "language_code": "en_us", + "string": "Extra" + }, + { + "language_code": "es_es", + "string": "Extra" + } + ] + } + ], + "settings":[ + { + "function": "instance_type", + "type": "text.select", + "maxLength": 50, + "default_value": ["hub"], + "options": ["hub", "node"], + "localized": ["name", "description"], + "name": [ + { + "language_code": "en_us", + "string": "Instance type" + } + ], + "description": [ + { + "language_code": "en_us", + "string": "If this app instance is to receive the synchronization data, select hub. If this instance is sending the data, select node" + } + ] + }, + { + "function": "RUN", + "events": ["run"], + "type": "text.select", + "display_condition": { + "type" : "setting", + "name" : "SYNC_instance_type", + "value": "hub" + }, + "default_value":"disabled", + "options": ["disabled", "once", "schedule", "always_after_scan", "on_new_device", "on_notification"], + "localized": ["name", "description"], + "name" :[{ + "language_code":"en_us", + "string" : "When to run" + }, + { + "language_code":"es_es", + "string" : "Cuándo ejecutar" + }, + { + "language_code":"de_de", + "string" : "Wann laufen" + }], + "description": [{ + "language_code":"en_us", + "string" : "When the node sync should run. Data might be lost if you run the sync less frequently. Good options are always_after_scan, on_new_device, on_notification" + }] + }, + { + "function": "target_url", + "type": "text", + "display_condition": { + "type" : "setting", + "name" : "SYNC_instance_type", + "value": "hub" + }, + "maxLength": 50, + "default_value": "", + "options": [], + "localized": ["name", "description"], + "name": [ + { + "language_code": "en_us", + "string": "Hub URL" + } + ], + "description": [ + { + "language_code": "en_us", + "string": "Target hub URL to send the data to." + } + ] + }, + { + "function": "node_name", + "type": "text", + "display_condition": { + "type" : "setting", + "name" : "SYNC_instance_type", + "value": "node" + }, + "maxLength": 50, + "default_value": "", + "options": [], + "localized": ["name", "description"], + "name": [ + { + "language_code": "en_us", + "string": "Node name" + } + ], + "description": [ + { + "language_code": "en_us", + "string": "Use a unique node name, without spaces or special characters, such as Node_Vlan01" + } + ] + }, + { + "function": "plugins", + "type": "text.multiselect", + "display_condition": { + "type" : "setting", + "name" : "SYNC_instance_type", + "value": "node" + }, + "maxLength": 50, + "default_value": [ + ], + "options": ["{value}"], + "options_params" : [ + { + "name" : "value", + "type" : "setting", + "value" : "LOADED_PLUGINS" + } + ], + "localized": ["name", "description"], + "name": [ + { + "language_code": "en_us", + "string": "Plugins" + } + ], + "description": [ + { + "language_code": "en_us", + "string": "Plugins to synchronize. Only plugins that produce some kind of output in last_result.log can be synchronized." + } + ] + }, + { + "function": "api_token", + "type": "text", + "maxLength": 50, + "default_value": "", + "options": [], + "localized": ["name", "description"], + "name": [ + { + "language_code": "en_us", + "string": "API token" + } + ], + "description": [ + { + "language_code": "en_us", + "string": "API token to secure communication. The API token needs to be the same on the hub and on the nodes." + } + ] + }, + { + "function": "CMD", + "type": "readonly", + "default_value": "python3 /app/front/plugins/sync/sync.py", + "options": [], + "localized": ["name", "description"], + "name": [ + { + "language_code": "en_us", + "string": "Command" + }, + { + "language_code": "es_es", + "string": "Comando" + }, + { + "language_code": "de_de", + "string": "Befehl" + } + ], + "description": [ + { + "language_code": "en_us", + "string": "Command to run. This can not be changed" + }, + { + "language_code": "es_es", + "string": "Comando a ejecutar. Esto no se puede cambiar" + }, + { + "language_code": "de_de", + "string": "Befehl zum Ausführen. Dies kann nicht geändert werden" + } + ] + }, + { + "function": "RUN_SCHD", + "type": "text", + "display_condition": { + "type" : "setting", + "name" : "SYNC_instance_type", + "value": "hub" + }, + "default_value":"0 2 * * 3", + "options": [], + "localized": ["name", "description"], + "name" : [{ + "language_code":"en_us", + "string" : "Schedule" + }, + { + "language_code":"es_es", + "string" : "Schedule" + }, + { + "language_code":"de_de", + "string" : "Schedule" + }], + "description": [{ + "language_code":"en_us", + "string" : "Only enabled if you select schedule in the SYNC_RUN setting. Make sure you enter the schedule in the correct cron-like format (e.g. validate at crontab.guru). For example entering 0 4 * * * will run the scan after 4 am in the TIMEZONE you set above. Will be run NEXT time the time passes." + }, + { + "language_code":"es_es", + "string" : "Solo está habilitado si selecciona schedule en la configuración SYNC_RUN. Asegúrese de ingresar la programación en el formato similar a cron correcto (por ejemplo, valide en crontab.guru). Por ejemplo, ingresar 0 4 * * * ejecutará el escaneo después de las 4 a.m. en el TIMEZONE que configuró arriba. Se ejecutará la PRÓXIMA vez que pase el tiempo." + }, + { + "language_code":"de_de", + "string" : "Nur aktiviert, wenn Sie schedule in der SYNC_RUN-Einstellung auswählen. Stellen Sie sicher, dass Sie den Zeitplan im richtigen Cron-ähnlichen Format eingeben (z. B. validieren unter crontab.guru). Wenn Sie beispielsweise 0 4 * * * eingeben, wird der Scan nach 4 Uhr morgens in der TIMEZONE den Sie oben festgelegt haben. Wird das NÄCHSTE Mal ausgeführt, wenn die Zeit vergeht." + }] + }, + { + "function": "RUN_TIMEOUT", + "type": "integer", + "default_value": 30, + "options": [], + "localized": ["name", "description"], + "name": [ + { + "language_code": "en_us", + "string": "Run timeout" + }, + { + "language_code": "es_es", + "string": "Tiempo límite de ejecución" + }, + { + "language_code": "de_de", + "string": "Zeitüberschreitung" + } + ], + "description": [ + { + "language_code": "en_us", + "string": "Maximum time in seconds to wait for the script to finish. If this time is exceeded the script is aborted." + }, + { + "language_code": "es_es", + "string": "Tiempo máximo en segundos para esperar a que finalice el script. Si se supera este tiempo, el script se cancela." + }, + { + "language_code": "de_de", + "string": "Maximale Zeit in Sekunden, die auf den Abschluss des Skripts gewartet werden soll. Bei Überschreitung dieser Zeit wird das Skript abgebrochen." + } + ] + } + + + ] + + } diff --git a/front/plugins/sync/hub.php b/front/plugins/sync/hub.php new file mode 100755 index 00000000..7796963f --- /dev/null +++ b/front/plugins/sync/hub.php @@ -0,0 +1,47 @@ + diff --git a/front/plugins/sync/sync.py b/front/plugins/sync/sync.py new file mode 100755 index 00000000..9d005be6 --- /dev/null +++ b/front/plugins/sync/sync.py @@ -0,0 +1,104 @@ +#!/usr/bin/env python + +import os +import pathlib +import sys +import hashlib +import requests +from plugin_helper import Plugin_Object, Plugin_Objects, decodeBase64 +from plugin_utils import get_plugins_configs +from logger import mylog +from helper import get_setting_value + +# Define the installation path and extend the system path for plugin imports +INSTALL_PATH = "/app" +sys.path.extend([f"{INSTALL_PATH}/front/plugins", f"{INSTALL_PATH}/server"]) + +# Define the current path and log file paths +CUR_PATH = str(pathlib.Path(__file__).parent.resolve()) +LOG_FILE = os.path.join(CUR_PATH, 'script.log') +RESULT_FILE = os.path.join(CUR_PATH, 'last_result.log') + +pluginName = 'SYNC' + +# Function to encrypt data using a password +def encrypt_data(data, password): + key = hashlib.sha256(password.encode()).digest() + cipher = hashlib.pbkdf2_hmac('sha256', data.encode(), key, 100000) + return cipher.hex() + +def main(): + mylog('verbose', [f'[{pluginName}] In script']) + + + # Initialize the Plugin obj output file + plugin_objects = Plugin_Objects(RESULT_FILE) + + # Retrieve configuration settings + plugins_to_sync = get_setting_value('SYNC_plugins') + api_token = get_setting_value('SYNC_api_token') # Use an API token instead of a password + hub_url = get_setting_value('SYNC_hub_url') + node_name = get_setting_value('SYNC_node_name') + + # Get all plugin configurations + all_plugins = get_plugins_configs() + + + index = 0 + for plugin in all_plugins: + pref = plugin["unique_prefix"] + + if pref in plugins_to_sync: + index += 1 + mylog('verbose', [f'[{pluginName}] synching "{pref}" ({index}/{len(plugins_to_sync)})']) + + # Construct the file path for the plugin's last_result.log file + plugin_folder = plugin["code_name"] + file_path = f"{INSTALL_PATH}/front/plugins/{plugin_folder}/last_result.log" + + if os.path.exists(file_path): + # Read the content of the log file + with open(file_path, 'r') as f: + newLines = f.read() + # Encrypt the log data using the API token + encrypted_data = encrypt_data(newLines, api_token) + + # Prepare the data payload for the POST request + data = { + 'data': encrypted_data, + 'plugin_folder': plugin_folder, + 'node_name': node_name + } + + # Set the authorization header with the API token + headers = {'Authorization': f'Bearer {api_token}'} + api_endpoint = f"{hub_url}/plugins/sync/hub.php" + response = requests.post(api_endpoint, data=data, headers=headers) + + mylog('verbose', [f'[{pluginName}] response: "{response}"']) + + if response.status_code == 200: + mylog('verbose', [f'[{pluginName}] Data for "{plugin_folder}" sent successfully']) + else: + mylog('error', [f'[{pluginName}] Failed to send data for "{plugin_folder}"']) + + # log result + plugin_objects.add_object( + primaryId = pref, + secondaryId = timeNowTZ(), + watched1 = node_name, + watched2 = response.status_code, + watched3 = response.text, + watched4 = '', + extra = '', + foreignKey = '') + else: + mylog('verbose', [f'[{pluginName}] {plugin_folder}/last_result.log not found']) + + # log result + plugin_objects.write_result_file() + + return 0 + +if __name__ == '__main__': + main()