diff --git a/.github/ISSUE_TEMPLATE/i-have-an-issue.yml b/.github/ISSUE_TEMPLATE/i-have-an-issue.yml index 66312cce..770d23be 100755 --- a/.github/ISSUE_TEMPLATE/i-have-an-issue.yml +++ b/.github/ISSUE_TEMPLATE/i-have-an-issue.yml @@ -95,7 +95,7 @@ body: ***Generally speaking, all bug reports should have logs provided.*** Tip: You can attach images or log files by clicking this area to highlight it and then dragging files in. Additionally, any additional info? Screenshots? References? Anything that will give us more context about the issue you are encountering! - You can use `tail -100 /app/log/app.log` in the container if you have trouble getting to the log files or send them to netalertx@gmail.com with the issue number. + You can use `tail -100 /app/log/app.log` in the container if you have trouble getting to the log files or send them to support@netalertx.com with the issue number. validations: required: false - type: textarea diff --git a/.github/ISSUE_TEMPLATE/security-report.yml b/.github/ISSUE_TEMPLATE/security-report.yml index ae0cf915..70b7a6a6 100755 --- a/.github/ISSUE_TEMPLATE/security-report.yml +++ b/.github/ISSUE_TEMPLATE/security-report.yml @@ -10,7 +10,7 @@ body: attributes: value: | **Important:** For security reasons, please do **not** post sensitive security issues publicly in the issue tracker. - Instead, send details to our security contact email: [jokob@duck.com](mailto:jokob@duck.com). + Instead, send details to our security contact email: [support@netalertx.com](mailto:support@netalertx.com). We appreciate your responsible disclosure. - type: textarea @@ -27,6 +27,6 @@ body: attributes: label: Have you sent this report via email to the security contact? options: - - label: Yes, I have sent the details to jokob@duck.com + - label: Yes, I have sent the details to support@netalertx.com required: true - label: Not yet, I will send it after opening this issue diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md index ab9765e6..72f9bb6c 100755 --- a/CODE_OF_CONDUCT.md +++ b/CODE_OF_CONDUCT.md @@ -60,7 +60,7 @@ representative at an online or offline event. ## Enforcement Instances of abusive, harassing, or otherwise unacceptable behavior may be -reported to the community leaders responsible for enforcement at . +reported to the community leaders responsible for enforcement at . All complaints will be reviewed and investigated promptly and fairly. All community leaders are obligated to respect the privacy and security of the diff --git a/README.md b/README.md index fd2b6eec..e155f2bf 100755 --- a/README.md +++ b/README.md @@ -198,7 +198,7 @@ Thank you to everyone who appreciates this tool and donates. - Bitcoin: `1N8tupjeCK12qRVU2XrV17WvKK7LCawyZM` - Ethereum: `0x6e2749Cb42F4411bc98501406BdcD82244e3f9C7` - 📧 Email me at [jokob@duck.com](mailto:jokob@duck.com?subject=NetAlertX) if you want to get in touch or if I should add other sponsorship platforms. + 📧 Email me at [support@netalertx.com](mailto:support@netalertx.com?subject=NetAlertX) if you want to get in touch or if I should add other sponsorship platforms. diff --git a/back/update_vendors.sh b/back/update_vendors.sh index 0e2fc953..be0d9a3e 100755 --- a/back/update_vendors.sh +++ b/back/update_vendors.sh @@ -6,7 +6,7 @@ # # update_vendors.sh - Back module. IEEE Vendors db update # ------------------------------------------------------------------------------ -# Puche 2021 / 2022+ jokob jokob@duck.com GNU GPLv3 +# Puche 2021 / 2022+ jokob support@netalertx.com GNU GPLv3 # ------------------------------------------------------------------------------ # ---------------------------------------------------------------------- diff --git a/docs/DEBUG_PLUGINS.md b/docs/DEBUG_PLUGINS.md index f84e752d..cb95dea4 100755 --- a/docs/DEBUG_PLUGINS.md +++ b/docs/DEBUG_PLUGINS.md @@ -103,6 +103,6 @@ Sometimes specific log sections are needed to debug issues. The Devices and Curr 2. Wait for the issue to occur. 3. Search for `================ DEVICES table content ================` in your logs. 4. Search for `================ CurrentScan table content ================` in your logs. -5. Open a new issue and post (redacted) output into the issue description (or send to the netalertx@gmail.com email if sensitive data present). +5. Open a new issue and post (redacted) output into the issue description (or send to the support@netalertx.com email if sensitive data present). 6. Please set `LOG_LEVEL` to `debug` or lower. diff --git a/docs/DEBUG_TIPS.md b/docs/DEBUG_TIPS.md index cf7f27bc..31e1201a 100755 --- a/docs/DEBUG_TIPS.md +++ b/docs/DEBUG_TIPS.md @@ -67,7 +67,7 @@ Sometimes specific log sections are needed to debug issues. The Devices and Curr 2. Wait for the issue to occur. 3. Search for `================ DEVICES table content ================` in your logs. 4. Search for `================ CurrentScan table content ================` in your logs. -5. Open a new issue and post (redacted) output into the issue description (or send to the netalertx@gmail.com email if sensitive data present). +5. Open a new issue and post (redacted) output into the issue description (or send to the support@netalertx.com email if sensitive data present). 6. Please set `LOG_LEVEL` to `debug` or lower. ## Common issues diff --git a/docs/DOCKER_INSTALLATION.md b/docs/DOCKER_INSTALLATION.md index 70183b10..81975f91 100644 --- a/docs/DOCKER_INSTALLATION.md +++ b/docs/DOCKER_INSTALLATION.md @@ -127,4 +127,4 @@ You can read or watch several [community configuration guides](https://docs.neta - Bitcoin: `1N8tupjeCK12qRVU2XrV17WvKK7LCawyZM` - Ethereum: `0x6e2749Cb42F4411bc98501406BdcD82244e3f9C7` -> 📧 Email me at [netalertx@gmail.com](mailto:netalertx@gmail.com?subject=NetAlertX Donations) if you want to get in touch or if I should add other sponsorship platforms. +> 📧 Email me at [support@netalertx.com](mailto:support@netalertx.com?subject=NetAlertX Donations) if you want to get in touch or if I should add other sponsorship platforms. diff --git a/docs/NOTIFICATIONS.md b/docs/NOTIFICATIONS.md index 03a67adf..3c26f6b1 100755 --- a/docs/NOTIFICATIONS.md +++ b/docs/NOTIFICATIONS.md @@ -24,7 +24,7 @@ The following device properties influence notifications. You can: 2. **Alert Down** - Alerts when a device goes down. This setting overrides a disabled **Alert Events** setting, so you will get a notification of a device going down even if you don't have **Alert Events** ticked. Disabling this will disable down and down reconnected notifications on the device. 3. **Can Sleep** - Marks the device as sleep-capable (e.g. a battery-powered sensor that deep-sleeps between readings). When enabled, offline periods within the **Alert down after (sleep)** (`NTFPRCS_sleep_time`) global window are shown as **Sleeping** (aqua badge 🌙) instead of **Down**, and no down alert is fired during that window. Once the window expires the device falls back to normal down-alert logic. ⚠ Requires **Alert Down** to be enabled — sleeping suppresses the alert during the window only. 4. **Skip repeated notifications**, if for example you know there is a temporary issue and want to pause the same notification for this device for a given time. -5. **Require NICs Online** - Indicates whether this device should be considered online only if all associated NICs (child devices with the `nic` relationship type) are online. When disabled, a single online NIC is sufficient to mark the parent device as online, regardless of the parent's own detected status. The nic relationship type is configured on the child (NIC) device. +5. **Require NICs Online** - Determines whether this device is considered online only when **all associated NICs** are online. To configure this, navigate to the child devices, assign the `nic` relationship, and set this device as the **Parent node**. If enabled, every associated NIC must be online for the device to be considered online. If disabled, the device is considered online when **any NIC** is online. Database column name: `devReqNicsOnline`. > [!NOTE] > Please read through the [NTFPRCS plugin](https://github.com/netalertx/NetAlertX/blob/main/front/plugins/notification_processing/README.md) documentation to understand how device and global settings influence the notification processing. diff --git a/docs/SECURITY.md b/docs/SECURITY.md index ad3aad0a..a03fe31a 100755 --- a/docs/SECURITY.md +++ b/docs/SECURITY.md @@ -91,9 +91,9 @@ By default, NetAlertX does **not** require login. Before exposing the UI in any ## 📣 Responsible Disclosure -If you discover a vulnerability or security concern, please report it **privately** to: +If you discover a vulnerability or security concern, please report it **privately** via GitHub security advisories or to: -📧 [jokob@duck.com](mailto:jokob@duck.com?subject=NetAlertX%20Security%20Disclosure) +📧 [support@netalertx.com](mailto:support@netalertx.com?subject=NetAlertX%20Security%20Disclosure) We take security seriously and will work to patch confirmed issues promptly. Your help in responsible disclosure is appreciated! diff --git a/front/css/app.css b/front/css/app.css index 67349b79..72e7a548 100755 --- a/front/css/app.css +++ b/front/css/app.css @@ -4,7 +4,7 @@ # # app.css - Front module. CSS styles #------------------------------------------------------------------------------- -# Puche 2021 / 2022+ jokob jokob@duck.com GNU GPLv3 +# Puche 2021 / 2022+ jokob support@netalertx.com GNU GPLv3 ----------------------------------------------------------------------------- */ /* ----------------------------------------------------------------------------- diff --git a/front/js/app-init.js b/front/js/app-init.js index 7ec62d7c..d50738bf 100644 --- a/front/js/app-init.js +++ b/front/js/app-init.js @@ -8,7 +8,7 @@ * mergeUniqueArrays(), getSetting(), getString(), getCache(), * setCache(), and all cache* functions from cache.js. *------------------------------------------------------------------------------- - # jokob@duck.com GNU GPLv3 + # support@netalertx.com GNU GPLv3 ----------------------------------------------------------------------------- */ // ----------------------------------------------------------------------------- diff --git a/front/js/cache.js b/front/js/cache.js index 8fb675e6..937023e7 100644 --- a/front/js/cache.js +++ b/front/js/cache.js @@ -7,7 +7,7 @@ * All cross-file calls (handleSuccess, showSpinner, etc.) are * call-time dependencies resolved after page load. *------------------------------------------------------------------------------- - # jokob@duck.com GNU GPLv3 + # support@netalertx.com GNU GPLv3 ----------------------------------------------------------------------------- */ // Cache version stamp — injected by header.php from the app's .VERSION file. diff --git a/front/js/common.js b/front/js/common.js index bcad76e6..eb351397 100755 --- a/front/js/common.js +++ b/front/js/common.js @@ -4,7 +4,7 @@ * * common.js - Front module. Common Javascript functions *------------------------------------------------------------------------------- -# Puche 2021 / 2022+ jokob jokob@duck.com GNU GPLv3 +# Puche 2021 / 2022+ jokob support@netalertx.com GNU GPLv3 ----------------------------------------------------------------------------- */ // ----------------------------------------------------------------------------- @@ -1009,7 +1009,7 @@ function showSpinner(stringKey = "Loading", target = null) { console.log(resolvedTarget); - console.log(`spinnerTarget=${resolvedTarget.attr("id")} class=${resolvedTarget.attr("class")} size=${resolvedTarget.outerWidth()}x${resolvedTarget.outerHeight()} parent=${resolvedTarget.parent().outerWidth()}x${resolvedTarget.parent().outerHeight()}`) + // console.log(`spinnerTarget=${resolvedTarget.attr("id")} class=${resolvedTarget.attr("class")} size=${resolvedTarget.outerWidth()}x${resolvedTarget.outerHeight()} parent=${resolvedTarget.parent().outerWidth()}x${resolvedTarget.parent().outerHeight()}`) $("#loadingSpinnerText").text(text); diff --git a/front/js/settings_utils.js b/front/js/settings_utils.js index b1ce57a0..752ebb7f 100755 --- a/front/js/settings_utils.js +++ b/front/js/settings_utils.js @@ -1059,6 +1059,16 @@ function collectSetting(prefix, setCodeName, setType, settingsArray) { // Map of handlers const handlers = { + textarea: () => { + let value = $(`#${setCodeName}`).val(); + + // Only escape multiline plain text values + if (dataType === "string") { + value = JSON.stringify(value).slice(1, -1); + } + + return applyTransformers(value, transformers); + }, datatableString: () => { const value = collectTableData(`#${setCodeName}_table`); return btoa(JSON.stringify(value)); @@ -1091,9 +1101,26 @@ function collectSetting(prefix, setCodeName, setType, settingsArray) { }, none: () => "", json: () => { - let value = $(`#${setCodeName}`).val(); - value = applyTransformers(value, transformers); - return JSON.stringify(value, null, 2); + let value = $(`#${setCodeName}`).val(); + + value = applyTransformers(value, transformers); + + try { + value = JSON.parse(value); + } catch (e) { + console.error(`[collectSetting] Invalid JSON for ${setCodeName}`, e); + return value; + } + + value = JSON.stringify(value, null, 2) + .replace(/\btrue\b/g, "True") + .replace(/\bfalse\b/g, "False") + .replace(/\bnull\b/g, "None"); + + console.log("---------------") + console.log(value) + + return value; }, fallback: () => { console.error(`[collectSetting] Couldn't determine how to handle (${setCodeName}|${dataType}|${opts.inputType})`); @@ -1106,17 +1133,20 @@ function collectSetting(prefix, setCodeName, setType, settingsArray) { let handlerKey; if (dataType === "string" && elementType === "datatable") { handlerKey = "datatableString"; + } else if (dataType === "json") { + handlerKey = "json"; + } + else if (elementType === "textarea") { + handlerKey = "textarea"; } else if (dataType === "string" || (dataType === "integer" && (opts.inputType === "number" || opts.inputType === "text"))) { - handlerKey = "simpleValue"; + handlerKey = "simpleValue"; } else if (opts.inputType === "checkbox") { handlerKey = "checkbox"; } else if (dataType === "array") { handlerKey = "array"; } else if (dataType === "none") { handlerKey = "none"; - } else if (dataType === "json") { - handlerKey = "json"; } else { handlerKey = "fallback"; } @@ -1162,16 +1192,19 @@ function generateFormHtml(settingsData, set, overrideValue, overrideOptions, ori const setKey = set['setKey']; const setType = set['setType']; - // if (setKey == 'UNIFIAPI_site_name') { + // if (setKey == 'NTFPRCS_TEXT_TEMPLATE_down_devices') { - // console.log("==== DEBUG OUTPUT BELOW 1 ===="); - // console.log("populateFromOverrides: " + populateFromOverrides); - // console.log(setType); - // console.log(setKey); - // console.log("overrideValue:" + overrideValue); - // console.log("inVal:" + inVal); - // console.log("set['setValue']:" + set['setValue']); - // } + // console.log("==== DEBUG OUTPUT BELOW 1 ===="); + // console.log("populateFromOverrides: " + populateFromOverrides); + // console.log(setType); + // console.log(setKey); + // console.log("overrideValue:" + overrideValue); + // console.log("inVal:" + inVal); + // console.log("set['setValue']:" + set['setValue']); + // console.log("overrideValue stringify:", JSON.stringify(overrideValue)); + // console.log("inVal stringify:", JSON.stringify(inVal)); + // console.log("set['setValue'] stringify:", JSON.stringify(set['setValue'])); + // } // Parse the setType JSON string // console.log(processQuotes(setType)); @@ -1212,7 +1245,7 @@ function generateFormHtml(settingsData, set, overrideValue, overrideOptions, ori // Override value let val = valRes; - // if (setKey == 'UNIFIAPI_site_name') { + // if (setKey == 'NTFPRCS_TEXT_TEMPLATE_down_devices') { // console.log("==== DEBUG OUTPUT BELOW 2 ===="); // console.log(setType); diff --git a/front/js/ui_components.js b/front/js/ui_components.js index 8d3bdc1c..1614d4d6 100755 --- a/front/js/ui_components.js +++ b/front/js/ui_components.js @@ -4,7 +4,7 @@ * * ui_components.js - Front module. Common UI components *------------------------------------------------------------------------------- -# jokob jokob@duck.com GNU GPLv3 +# jokob support@netalertx.com GNU GPLv3 ----------------------------------------------------------------------------- */ diff --git a/front/php/server/db.php b/front/php/server/db.php index b25f39fb..2076c6fa 100755 --- a/front/php/server/db.php +++ b/front/php/server/db.php @@ -5,7 +5,7 @@ // // db.php - Front module. Server side. DB common file //------------------------------------------------------------------------------ -# 2022 jokob jokob@duck.com GNU GPLv3 +# 2022 jokob support@netalertx.com GNU GPLv3 //------------------------------------------------------------------------------ //------------------------------------------------------------------------------ diff --git a/front/php/server/util.php b/front/php/server/util.php index 75c8d86c..4c9449c6 100755 --- a/front/php/server/util.php +++ b/front/php/server/util.php @@ -5,7 +5,7 @@ // // util.php - Front module. Server side. Settings and utility functions //------------------------------------------------------------------------------ -# Puche 2021 / 2022+ jokob jokob@duck.com GNU GPLv3 +# Puche 2021 / 2022+ jokob support@netalertx.com GNU GPLv3 //------------------------------------------------------------------------------ require dirname(__FILE__).'/../templates/globals.php'; diff --git a/front/php/templates/header.php b/front/php/templates/header.php index 577ba986..0337c08f 100755 --- a/front/php/templates/header.php +++ b/front/php/templates/header.php @@ -4,7 +4,7 @@ # # header.php - Front module. Common header to all the web pages #------------------------------------------------------------------------------- -# Puche 2021 / 2022+ jokob jokob@duck.com GNU GPLv3 +# Puche 2021 / 2022+ jokob support@netalertx.com GNU GPLv3 #--------------------------------------------------------------------------- --> diff --git a/front/plugins/_publisher_telegram/tg.py b/front/plugins/_publisher_telegram/tg.py index 203b0a43..97e2a486 100755 --- a/front/plugins/_publisher_telegram/tg.py +++ b/front/plugins/_publisher_telegram/tg.py @@ -3,6 +3,7 @@ import subprocess import os import sys +import json # Register NetAlertX directories INSTALL_PATH = os.getenv('NETALERTX_APP', '/app') @@ -79,45 +80,78 @@ def check_config(): # ------------------------------------------------------------------------------- def send(text): - # limit = 1024 * 1024 # 1MB limit (1024 bytes * 1024 bytes = 1MB) + """ + Send a Telegram notification. + """ limit = get_setting_value('TELEGRAM_SIZE') + run_timeout = int(get_setting_value('TELEGRAM_RUN_TIMEOUT')) + curl_timeout = str(max(1, run_timeout - 1)) + # Ensure the final payload, including the truncation marker, + # never exceeds TELEGRAM_SIZE. + truncation_marker = " (text was truncated)" if len(text) > limit: - payloadData = text[:limit] + " (text was truncated)" + payload_data = (text[:max(0, limit - len(truncation_marker))] + truncation_marker)[:limit] else: - payloadData = text + payload_data = text + + payload = json.dumps({ + "chat_id": get_setting_value('TELEGRAM_HOST'), + "text": payload_data, + "disable_notification": False + }) + + cmd = [ + "curl", + "--location", + + # Prevent curl from hanging indefinitely. + # Both values are intentionally below RUN_TIMEOUT. + "--connect-timeout", curl_timeout, + "--max-time", curl_timeout, + + f"https://api.telegram.org/bot{get_setting_value('TELEGRAM_URL')}/sendMessage", + "--header", + "Content-Type: application/json", + "--data", + payload, + ] + + mylog("debug", ["Executing: Telegram sendMessage", "--data "]) try: - # try runnning a subprocess + proc = subprocess.run( + cmd, + stdout=subprocess.PIPE, + stderr=subprocess.STDOUT, + text=True, + check=False, + ) - req = """curl --location 'https://api.telegram.org/bot%s/sendMessage' \\ - --header 'Content-Type: application/json' \\ - --data '{ - "chat_id": "%s", - "text": "%s", - "disable_notification": false - }'""" % (get_setting_value('TELEGRAM_URL'), get_setting_value('TELEGRAM_HOST'), payloadData) + mylog("debug", [proc.stdout]) - mylog('debug', [req]) + # curl execution failed + if proc.returncode != 0: + raise subprocess.CalledProcessError( + proc.returncode, + cmd, + output=proc.stdout, + ) - p = subprocess.Popen(req, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=True) - stdout, stderr = p.communicate() + # Telegram API returned an error + try: + response = json.loads(proc.stdout) + if isinstance(response, dict) and response.get("ok") is False: + raise RuntimeError(proc.stdout) + except json.JSONDecodeError: + # Ignore non-JSON responses and preserve existing behavior. + pass - # write stdout and stderr into .log files for debugging if needed - # Log the stdout and stderr - mylog('debug', [stdout, stderr]) + return proc.stdout - # log result - result = stdout - - except subprocess.CalledProcessError as e: - # An error occurred, handle it - mylog('none', [e.output]) - - # log result - result = e.output - - return result + except OSError: + # Propagate filesystem/process execution errors. + raise if __name__ == '__main__': diff --git a/front/plugins/_publisher_webhook/webhook.py b/front/plugins/_publisher_webhook/webhook.py index fde9c755..0675150a 100755 --- a/front/plugins/_publisher_webhook/webhook.py +++ b/front/plugins/_publisher_webhook/webhook.py @@ -154,21 +154,24 @@ def send(text_data, html_data, json_data): }] } + # Serialize once so the transmitted payload and HMAC signature always match + payload_json = json.dumps(_json_payload, separators=(',', ':')) + # DEBUG - Write the json payload into a log file for debugging - write_file(logPath + '/webhook_payload.json', json.dumps(_json_payload)) + write_file(logPath + '/webhook_payload.json', payload_json) # Using the Slack-Compatible Webhook endpoint for Discord so that the same payload can be used for both # Consider: curl has the ability to load in data to POST from a file + piping if (endpointUrl.startswith('https://discord.com/api/webhooks/') and not endpointUrl.endswith("/slack")): _WEBHOOK_URL = f"{endpointUrl}/slack" - curlParams = ["curl", "-i", "-H", "Content-Type:application/json", "-d", json.dumps(_json_payload), _WEBHOOK_URL] + curlParams = ["curl", "-i", "-H", "Content-Type:application/json", "-d", payload_json, _WEBHOOK_URL] else: _WEBHOOK_URL = endpointUrl - curlParams = ["curl", "-i", "-X", requestMethod , "-H", "Content-Type:application/json", "-d", json.dumps(_json_payload), _WEBHOOK_URL] + curlParams = ["curl", "-i", "-X", requestMethod, "-H", "Content-Type:application/json", "-d", payload_json, _WEBHOOK_URL] # Add HMAC signature if configured if (secret != ''): - h = hmac.new(secret.encode("UTF-8"), json.dumps(_json_payload, separators=(',', ':')).encode(), hashlib.sha256).hexdigest() + h = hmac.new(secret.encode("UTF-8"), payload_json.encode("UTF-8"), hashlib.sha256).hexdigest() curlParams.insert(4, "-H") curlParams.insert(5, f"X-Webhook-Signature: sha256={h}") diff --git a/front/plugins/db_cleanup/script.py b/front/plugins/db_cleanup/script.py index cae8ec28..dd6b67b5 100755 --- a/front/plugins/db_cleanup/script.py +++ b/front/plugins/db_cleanup/script.py @@ -130,15 +130,11 @@ def cleanup_database( histCount = get_setting_value("DBCLNP_NOTIFI_HIST") mylog("verbose", f"[{pluginName}] Notifications: Trim to {histCount}") delete_query = f"""DELETE FROM Notifications - WHERE "Index" NOT IN ( - SELECT "Index" - FROM ( - SELECT "Index", - ROW_NUMBER() OVER(PARTITION BY "index" ORDER BY dateTimeCreated DESC) AS row_num - FROM Notifications - ) AS ranked_objects - WHERE row_num <= {histCount} - );""" + WHERE "Index" NOT IN ( + SELECT "Index" FROM Notifications + ORDER BY dateTimeCreated DESC + LIMIT {histCount} + );""" cursor.execute(delete_query) mylog("verbose", [f"[{pluginName}] Notifications deleted rows: {cursor.rowcount}"]) diff --git a/front/plugins/newdev_template/config.json b/front/plugins/newdev_template/config.json index 364f937c..40b97a44 100755 --- a/front/plugins/newdev_template/config.json +++ b/front/plugins/newdev_template/config.json @@ -1888,7 +1888,7 @@ "description": [ { "language_code": "en_us", - "string": "Indicates whether this device should be considered online only if all associated NICs (devices with the nic relationship type) are online. If disabled, the device is considered online if any NIC is online. Database column name: devReqNicsOnline." + "string": "Determines whether this device is considered online only when all associated NICs are online. To configure this, navigate to the child devices, assign the nic relationship, and set this device as the Parent node. If enabled, every associated NIC must be online for the device to be considered online. If disabled, the device is considered online when any NIC is online. Database column name: devReqNicsOnline." } ] }, diff --git a/front/plugins/notification_processing/config.json b/front/plugins/notification_processing/config.json index 7a97e969..d3f82bbd 100755 --- a/front/plugins/notification_processing/config.json +++ b/front/plugins/notification_processing/config.json @@ -210,7 +210,7 @@ "type": { "dataType": "string", "elements": [ - { "elementType": "input", "elementOptions": [], "transformers": [] } + { "elementType": "textarea", "elementOptions": [], "transformers": [] } ] }, "default_value": "", @@ -225,7 +225,7 @@ "description": [ { "language_code": "en_us", - "string": "Custom text template for new device notifications. Use {FieldName} placeholders, e.g. {devName} ({eveMac}) - {eveIp}. Leave empty for default formatting. Available fields: {devName}, {eveMac}, {devVendor}, {eveIp}, {eveDateTime}, {eveEventType}, {devComments}." + "string": "Custom text template for new device notifications. Use {FieldName} placeholders, e.g. {devName} ({eveMac}) - {eveIp}. Leave empty for default formatting. Available fields: {devName}, {eveMac}, {devVendor}, {eveIp}, {eveDateTime}, {eveEventType}, {devComments}, {devVlan}, {devSite}, {devSSID}." } ] }, @@ -234,7 +234,7 @@ "type": { "dataType": "string", "elements": [ - { "elementType": "input", "elementOptions": [], "transformers": [] } + { "elementType": "textarea", "elementOptions": [], "transformers": [] } ] }, "default_value": "", @@ -249,7 +249,7 @@ "description": [ { "language_code": "en_us", - "string": "Custom text template for down device notifications. Use {FieldName} placeholders, e.g. {devName} ({eveMac}) - {eveIp}. Leave empty for default formatting. Available fields: {devName}, {eveMac}, {devVendor}, {eveIp}, {eveDateTime}, {eveEventType}, {devComments}." + "string": "Custom text template for down device notifications. Use {FieldName} placeholders, e.g. {devName} ({eveMac}) - {eveIp}. Leave empty for default formatting. Available fields: {devName}, {eveMac}, {devVendor}, {eveIp}, {eveDateTime}, {eveEventType}, {devComments}, {devVlan}, {devSite}, {devSSID}." } ] }, @@ -258,7 +258,7 @@ "type": { "dataType": "string", "elements": [ - { "elementType": "input", "elementOptions": [], "transformers": [] } + { "elementType": "textarea", "elementOptions": [], "transformers": [] } ] }, "default_value": "", @@ -273,7 +273,7 @@ "description": [ { "language_code": "en_us", - "string": "Custom text template for reconnected device notifications. Use {FieldName} placeholders, e.g. {devName} ({eveMac}) reconnected at {eveDateTime}. Leave empty for default formatting. Available fields: {devName}, {eveMac}, {devVendor}, {eveIp}, {eveDateTime}, {eveEventType}, {devComments}." + "string": "Custom text template for reconnected device notifications. Use {FieldName} placeholders, e.g. {devName} ({eveMac}) reconnected at {eveDateTime}. Leave empty for default formatting. Available fields: {devName}, {eveMac}, {devVendor}, {eveIp}, {eveDateTime}, {eveEventType}, {devComments}, {devVlan}, {devSite}, {devSSID}." } ] }, @@ -282,7 +282,7 @@ "type": { "dataType": "string", "elements": [ - { "elementType": "input", "elementOptions": [], "transformers": [] } + { "elementType": "textarea", "elementOptions": [], "transformers": [] } ] }, "default_value": "", @@ -297,7 +297,7 @@ "description": [ { "language_code": "en_us", - "string": "Custom text template for event notifications. Use {FieldName} placeholders, e.g. {devName} ({eveMac}) {eveEventType} at {eveDateTime}. Leave empty for default formatting. Available fields: {devName}, {eveMac}, {devVendor}, {eveIp}, {eveDateTime}, {eveEventType}, {devComments}." + "string": "Custom text template for event notifications. Use {FieldName} placeholders, e.g. {devName} ({eveMac}) {eveEventType} at {eveDateTime}. Leave empty for default formatting. Available fields: {devName}, {eveMac}, {devVendor}, {eveIp}, {eveDateTime}, {eveEventType}, {devComments}, {devVlan}, {devSite}, {devSSID}." } ] }, @@ -306,7 +306,7 @@ "type": { "dataType": "string", "elements": [ - { "elementType": "input", "elementOptions": [], "transformers": [] } + { "elementType": "textarea", "elementOptions": [], "transformers": [] } ] }, "default_value": "", diff --git a/front/plugins/omada_sdn_openapi/script.py b/front/plugins/omada_sdn_openapi/script.py index 9e8bb749..26550961 100755 --- a/front/plugins/omada_sdn_openapi/script.py +++ b/front/plugins/omada_sdn_openapi/script.py @@ -20,6 +20,7 @@ __version__ = 0.1 # Initial version __version__ = 0.2 # Rephrased error messages, improved logging and code logic __version__ = 0.3 # Refactored data collection into a class, improved code clarity with comments __version__ = 0.4 # Fix for https://github.com/netalertx/NetAlertX/issues/1595 - Omada Controller versions >= 6.2.0.0 removed the v1 clients endpoint +__version__ = 0.5 # Fix for https://github.com/netalertx/NetAlertX/issues/1717 - preventing None as IP import os import sys @@ -168,6 +169,10 @@ class OmadaHelper: entry["ip_address"] = data.get("ip") entry["name"] = data.get("name") + # Preventing None as IP + if entry["ip_address"] is None or entry["ip_address"] == "None": + entry["ip_address"] = "null" + # Assign the last datetime the device/client was seen on the network last_seen = OmadaHelper.timestamp_to_datetime(data.get("lastSeen", 0), timezone) entry["last_seen"] = last_seen.get("response_result") if isinstance(last_seen, dict) and last_seen.get("response_type") == "success" else "" diff --git a/front/plugins/rest_import/config.json b/front/plugins/rest_import/config.json index 5ae42a03..a757f853 100644 --- a/front/plugins/rest_import/config.json +++ b/front/plugins/rest_import/config.json @@ -1171,7 +1171,8 @@ "devSite", "devType", "devParentMAC", - "devParentPort" + "devParentPort", + "devVlan" ], "localized": [ "name", diff --git a/front/settings.php b/front/settings.php index d8d971ab..f3f83f89 100755 --- a/front/settings.php +++ b/front/settings.php @@ -439,7 +439,7 @@ $settingsJSON_DB = json_encode($settings, JSON_HEX_TAG | JSON_HEX_AMP | JSON_HEX // constructing final HTML for the setting setHtml = "" - if(set["setGroup"] == prefix) + if(set["setGroup"] == prefix ) { // hide metadata by default by assigning it a special class isMetadata ? metadataClass = 'metadata' : metadataClass = ''; diff --git a/front/userNotifications.php b/front/userNotifications.php index ebd13772..1100631e 100755 --- a/front/userNotifications.php +++ b/front/userNotifications.php @@ -87,6 +87,12 @@ require 'php/templates/header.php'; result = result.split('+')[0]; // Remove timezone offset } + // Keep sortable value for DataTables + if (type === "sort" || type === "type" || type !== "display") { + return result; + } + + // Display localized date only result = localizeTimestamp(result); return result; diff --git a/install/production-filesystem/services/scripts/update_vendors.sh b/install/production-filesystem/services/scripts/update_vendors.sh index 3c891d32..da7d5284 100755 --- a/install/production-filesystem/services/scripts/update_vendors.sh +++ b/install/production-filesystem/services/scripts/update_vendors.sh @@ -7,7 +7,7 @@ set -euo pipefail # # update_vendors.sh - Back module. IEEE Vendors db update # ------------------------------------------------------------------------------ -# Puche 2021 / 2022+ jokob jokob@duck.com GNU GPLv3 +# Puche 2021 / 2022+ jokob support@netalertx.com GNU GPLv3 # ------------------------------------------------------------------------------ # ---------------------------------------------------------------------- diff --git a/server/__main__.py b/server/__main__.py index 1948bd4d..4534f911 100755 --- a/server/__main__.py +++ b/server/__main__.py @@ -6,7 +6,7 @@ # # Back module. Network scanner # ------------------------------------------------------------------------------- -# Puche 2021 / 2022+ jokob jokob@duck.com GNU GPLv3 +# Puche 2021 / 2022+ jokob support@netalertx.com GNU GPLv3 # ------------------------------------------------------------------------------- diff --git a/server/messaging/notification_sections.py b/server/messaging/notification_sections.py index 031d54b2..38d1f369 100644 --- a/server/messaging/notification_sections.py +++ b/server/messaging/notification_sections.py @@ -52,7 +52,10 @@ SQL_TEMPLATES = { devLastIP as eveIp, eveDateTime, eveEventType, - devComments + devComments, + devVlan, + devSite, + devSSID FROM Events_Devices WHERE evePendingAlertEmail = 1 AND eveEventType = 'New Device' {condition} @@ -66,7 +69,10 @@ SQL_TEMPLATES = { eveIp, eveDateTime, eveEventType, - devComments + devComments, + devVlan, + devSite, + devSSID FROM Events_Devices AS down_events WHERE evePendingAlertEmail = 1 AND down_events.eveEventType = 'Device Down' @@ -88,7 +94,10 @@ SQL_TEMPLATES = { reconnected_devices.eveIp, reconnected_devices.eveDateTime, reconnected_devices.eveEventType, - devComments + devComments, + devVlan, + devSite, + devSSID FROM Events_Devices AS reconnected_devices WHERE reconnected_devices.eveEventType = 'Down Reconnected' AND reconnected_devices.evePendingAlertEmail = 1 @@ -109,7 +118,10 @@ SQL_TEMPLATES = { devLastIP as eveIp, eveDateTime, eveEventType, - devComments + devComments, + devVlan, + devSite, + devSSID FROM Events_Devices WHERE evePendingAlertEmail = 1 AND eveEventType IN ({event_types}) {condition} diff --git a/server/models/device_instance.py b/server/models/device_instance.py index 83777d3c..cc772352 100755 --- a/server/models/device_instance.py +++ b/server/models/device_instance.py @@ -446,7 +446,7 @@ class DeviceInstance: # Join all sub-selects with commas query = "SELECT\n " + ",\n ".join(sub_queries) - mylog('none', [f'[getNamedTotals] query {query}']) + mylog('trace', [f'[getNamedTotals] query {query}']) json_obj = get_table_json(sql, query, parameters=None) return json_obj