diff --git a/docs/DOCKER_INSTALLATION.md b/docs/DOCKER_INSTALLATION.md index 2116fb33..16eae292 100644 --- a/docs/DOCKER_INSTALLATION.md +++ b/docs/DOCKER_INSTALLATION.md @@ -4,10 +4,11 @@ [![Discord](https://img.shields.io/discord/1274490466481602755?color=0aa8d2&logoColor=fff&logo=Discord&style=for-the-badge)](https://discord.gg/NczTUTWyRr) [![Home Assistant](https://img.shields.io/badge/Repo-blue?logo=home-assistant&style=for-the-badge&color=0aa8d2&logoColor=fff&label=Add)](https://my.home-assistant.io/redirect/supervisor_add_addon_repository/?repository_url=https%3A%2F%2Fgithub.com%2Falexbelgium%2Fhassio-addons) -# NetAlertX - Network scanner & notification framework +# NetAlertX - Network Visibility & Asset Intelligence Framework -| [📑 Docker guide](https://docs.netalertx.com/DOCKER_INSTALLATION) | [🚀 Releases](https://github.com/jokob-sk/NetAlertX/releases) | [📚 Docs](https://docs.netalertx.com/) | [🔌 Plugins](https://docs.netalertx.com/PLUGINS) | [🤖 Ask AI](https://gurubase.io/g/netalertx) -|----------------------| ----------------------| ----------------------| ----------------------| ----------------------| +--- +### || [Docker guide](https://docs.netalertx.com/DOCKER_INSTALLATION) || [Releases](https://github.com/netalertx/NetAlertX/releases) || [Docs](https://docs.netalertx.com/) || [Plugins](https://docs.netalertx.com/PLUGINS) || [Website](https://netalertx.com) +--- diff --git a/docs/index.md b/docs/index.md index 8f830dc7..03708e93 100755 --- a/docs/index.md +++ b/docs/index.md @@ -6,7 +6,7 @@ hide: # NetAlertX Documentation -Welcome to the official NetAlertX documentation! NetAlertX is a powerful tool designed to simplify the management and monitoring of your network. Below, you will find guides and resources to help you set up, configure, and troubleshoot your NetAlertX instance. +Find guides and resources to help you set up, configure, and troubleshoot your NetAlertX instance. ![Preview](./img/devices_split.png) @@ -15,7 +15,7 @@ Welcome to the official NetAlertX documentation! NetAlertX is a powerful tool de NetAlertX provides contextual help within the application: - **Hover over settings, fields, or labels** to see additional tooltips and guidance. -- **Click ❔ (question-mark) icons** next to various elements to view detailed information. +- **Click ? (question-mark) icons** next to various elements to view detailed information. --- diff --git a/front/workflowsCore.php b/front/workflowsCore.php index 32a25967..1ca228f5 100755 --- a/front/workflowsCore.php +++ b/front/workflowsCore.php @@ -12,7 +12,7 @@
- +
@@ -48,10 +48,12 @@ let fieldOptions = [ "devLastIP", "devStaticIP", "devScan", "devLogEvents", "devAlertEvents", "devAlertDown", "devSkipRepeated", "devLastNotification", "devPresentLastScan", "devIsNew", "devLocation", "devIsArchived", "devParentMAC", "devParentPort", - "devIcon", "devSite", "devSSID", "devSyncHubNode", "devSourcePlugin", "devFQDN", - "devParentRelType", "devReqNicsOnline" + "devIcon", "devSite", "devSSID", "devSyncHubNode", "devSourcePlugin", "devFQDN", + "devParentRelType", "devReqNicsOnline", "devNameSource", "devVendorSource" , + "devSSIDSource", "devParentMACSource" , "devParentPortSource" , "devParentRelTypeSource", + "devVlanSource" ]; - + let triggerTypes = [ "Devices" ]; @@ -79,7 +81,7 @@ let emptyWorkflow = { }, "conditions": [ ], - "actions": [ + "actions": [ ] }; @@ -131,25 +133,25 @@ function renderWorkflows() { // Generate UI for a single workflow function generateWorkflowUI(wf, wfIndex) { - let wfEnabled = (wf?.enabled ?? "No") == "Yes"; + let wfEnabled = (wf?.enabled ?? "No") == "Yes"; - let $wfContainer = $("
", { - class: "workflow-card panel col-sm-12 col-sx-12", - id: `wf-${wfIndex}-container` + let $wfContainer = $("
", { + class: "workflow-card panel col-sm-12 col-sx-12", + id: `wf-${wfIndex}-container` }); // Workflow Name let $wfLinkWrap = $("
", { class: " ", - id: `wf-${wfIndex}-header` + id: `wf-${wfIndex}-header` } ) - let $wfEnabledIcon = $("", { + let $wfEnabledIcon = $("", { class: `alignRight fa ${wfEnabled ? "fa-dot-circle" : "fa-circle" }` }); - + let $wfHeaderLink = $("", { @@ -163,7 +165,7 @@ function generateWorkflowUI(wf, wfIndex) { let $wfHeaderHeading = $("

", { - class: "panel-title" + class: "panel-title" } ).text(wf.name) @@ -176,34 +178,34 @@ function generateWorkflowUI(wf, wfIndex) { let isOpen = panelState === "true"; // Convert stored string to boolean console.log(`panel isOpen: ${isOpen}` ); - - let $wfCollapsiblePanel = $("
", { - class: ` panel-collapse collapse ${isOpen ? 'in' : ''}`, - id: `wf-${wfIndex}-collapsible-panel` + + let $wfCollapsiblePanel = $("
", { + class: ` panel-collapse collapse ${isOpen ? 'in' : ''}`, + id: `wf-${wfIndex}-collapsible-panel` }); let $wfEnabled = createEditableDropdown( - `[${wfIndex}].enabled`, + `[${wfIndex}].enabled`, getString("WF_Enabled"), - wfEnabledOptions, - wfEnabled ? "Yes" :"No", + wfEnabledOptions, + wfEnabled ? "Yes" :"No", `wf-${wfIndex}-enabled` ); $wfCollapsiblePanel.append($wfEnabled) let $wfNameInput = createEditableInput( - `[${wfIndex}].name`, - getString("WF_Name"), - wf.name, - `wf-${wfIndex}-name`, + `[${wfIndex}].name`, + getString("WF_Name"), + wf.name, + `wf-${wfIndex}-name`, "workflow-name-input" ); $wfCollapsiblePanel.append($wfNameInput) - let $triggersIcon = $("", { + let $triggersIcon = $("", { class: "fa-solid fa-bolt" }); @@ -221,34 +223,34 @@ function generateWorkflowUI(wf, wfIndex) { ).append($triggerTitle); let $triggerTypeDropdown = createEditableDropdown( - `[${wfIndex}].trigger.object_type`, + `[${wfIndex}].trigger.object_type`, getString("WF_Trigger_type"), - triggerTypes, - wf.trigger.object_type, + triggerTypes, + wf.trigger.object_type, `wf-${wfIndex}-trigger-object-type` ); let $eventTypeDropdown = createEditableDropdown( - `[${wfIndex}].trigger.event_type`, - getString("WF_Trigger_event_type"), - triggerEvents, - wf.trigger.event_type, + `[${wfIndex}].trigger.event_type`, + getString("WF_Trigger_event_type"), + triggerEvents, + wf.trigger.event_type, `wf-${wfIndex}-trigger-event-type` ); - let $triggerIcon = $("", { + let $triggerIcon = $("", { class: "fa-solid fa-bolt bckg-icon-2-line" }); $triggerSection.append($triggerIcon); $triggerSection.append($triggerTypeDropdown); $triggerSection.append($eventTypeDropdown); - + $wfCollapsiblePanel.append($triggerSection); // Conditions - let $conditionsIcon = $("", { + let $conditionsIcon = $("", { class: "fa-solid fa-arrows-split-up-and-left fa-rotate-270" }); @@ -262,10 +264,10 @@ function generateWorkflowUI(wf, wfIndex) { $conditionsContainer.append(renderConditions(wfIndex, `[${wfIndex}]`, 0, wf.conditions)); - + $wfCollapsiblePanel.append($conditionsContainer); - let $actionsIcon = $("", { + let $actionsIcon = $("", { class: "fa-solid fa-person-running fa-flip-horizontal" }); @@ -295,10 +297,10 @@ function generateWorkflowUI(wf, wfIndex) { // Dropdown for action.type let $actionDropdown= createEditableDropdown( - `[${wfIndex}].actions[${actionIndex}].type`, - getString("WF_Action_type"), - actionTypes, - action.type, + `[${wfIndex}].actions[${actionIndex}].type`, + getString("WF_Action_type"), + actionTypes, + action.type, `wf-${wfIndex}-actionIndex-${actionIndex}-type` ); @@ -314,23 +316,23 @@ function generateWorkflowUI(wf, wfIndex) { // Dropdown for action.field let $fieldDropdown = createEditableDropdown( - `[${wfIndex}].actions[${actionIndex}].field`, - getString("WF_Action_field"), - fieldOptions, - action.field, + `[${wfIndex}].actions[${actionIndex}].field`, + getString("WF_Action_field"), + fieldOptions, + action.field, `wf-${wfIndex}-actionIndex-${actionIndex}-field` ); // Textbox for action.value let $actionValueInput = createEditableInput( - `[${wfIndex}].actions[${actionIndex}].value`, - getString("WF_Action_value"), - action.value, - `wf-${wfIndex}-actionIndex-${actionIndex}-value`, + `[${wfIndex}].actions[${actionIndex}].value`, + getString("WF_Action_value"), + action.value, + `wf-${wfIndex}-actionIndex-${actionIndex}-value`, "action-value-input" ); - + $actionEl.append($fieldDropdown); $actionEl.append($actionValueInput); @@ -340,7 +342,7 @@ function generateWorkflowUI(wf, wfIndex) { let $actionRemoveButtonWrap = $("
", { class: "button-container col-sm-1 col-sx-12" }); - let $actionRemoveIcon = $("", { + let $actionRemoveIcon = $("", { class: "fa-solid fa-trash" }); @@ -353,14 +355,14 @@ function generateWorkflowUI(wf, wfIndex) { $actionRemoveButtonWrap.append($actionRemoveButton); - let $actionIcon = $("", { + let $actionIcon = $("", { class: `fa-solid fa-person-running fa-flip-horizontal bckg-icon-${numberOfLines}-line ` }); $actionEl.prepend($actionIcon) $actionElWrap.append($actionEl) - + $actionElWrap.append($actionRemoveButtonWrap) $actionsContainer.append($actionElWrap); @@ -370,7 +372,7 @@ function generateWorkflowUI(wf, wfIndex) { // add action button let $actionAddButtonWrap = $("
", { class: "button-container col-sm-12 col-sx-12" }); - let $actionAddIcon = $("", { + let $actionAddIcon = $("", { class: "fa-solid fa-plus" }); let $actionAddButton = $("
", { @@ -382,10 +384,10 @@ function generateWorkflowUI(wf, wfIndex) { $actionAddButtonWrap.append($actionAddButton) $actionsContainer.append($actionAddButtonWrap) - + let $wfRemoveButtonWrap = $("
", { class: "button-container col-sm-4 col-sx-12" }); - let $wfRemoveIcon = $("", { + let $wfRemoveIcon = $("", { class: "fa-solid fa-trash" }); @@ -399,7 +401,7 @@ function generateWorkflowUI(wf, wfIndex) { let $wfDuplicateButtonWrap = $("
", { class: "button-container col-sm-4 col-sx-12" }); - let $wfDuplicateIcon = $("", { + let $wfDuplicateIcon = $("", { class: "fa-solid fa-copy" }); @@ -412,7 +414,7 @@ function generateWorkflowUI(wf, wfIndex) { let $wfExportButtonWrap = $("
", { class: "button-container col-sm-4 col-sx-12" }); - let $wfExportIcon = $("", { + let $wfExportIcon = $("", { class: "fa-solid fa-file-export" }); @@ -422,13 +424,13 @@ function generateWorkflowUI(wf, wfIndex) { }) .append($wfExportIcon) // Add icon .append(` ${getString("WF_Export")}`); // Add text - + $wfCollapsiblePanel.append($actionsContainer); $wfCollapsiblePanel.append($wfDuplicateButtonWrap.append($wfDuplicateButton)) $wfCollapsiblePanel.append($wfExportButtonWrap.append($wfExportButton)) $wfCollapsiblePanel.append($wfRemoveButtonWrap.append($wfRemoveButton)) - + $wfContainer.append($wfCollapsiblePanel) @@ -439,24 +441,24 @@ function generateWorkflowUI(wf, wfIndex) { // -------------------------------------- // Render conditions recursively function renderConditions(wfIndex, parentIndexPath, conditionGroupsIndex, conditions) { - let $conditionList = $("
", { + let $conditionList = $("
", { class: "condition-list panel col-sm-12 col-sx-12", - parentIndexPath: parentIndexPath + parentIndexPath: parentIndexPath }); lastConditionIndex = 0 - let $conditionListWrap = $("
", { + let $conditionListWrap = $("
", { class: `condition-list-wrap ${conditionGroupsIndex==0?"col-sm-12":"col-sm-11"} col-sx-12`, conditionGroupsIndex: conditionGroupsIndex }); - let $deleteConditionGroupWrap = $("
", { + let $deleteConditionGroupWrap = $("
", { class: "condition-group-wrap-del col-sm-1 col-sx-12" }); $.each(conditions, function (conditionIndex, condition) { - + let currentPath = `${parentIndexPath}.conditions[${conditionIndex}]`; if (condition.logic) { @@ -467,16 +469,16 @@ function renderConditions(wfIndex, parentIndexPath, conditionGroupsIndex, condit ); let $logicDropdown = createEditableDropdown( - `${currentPath}.logic`, - getString("WF_Conditions_logic_rules"), - ["AND", "OR"], - condition.logic, + `${currentPath}.logic`, + getString("WF_Conditions_logic_rules"), + ["AND", "OR"], + condition.logic, `wf-${wfIndex}-${currentPath.replace(/\./g, "-")}-logic` // id ); $nestedCondition.append($logicDropdown); - - $conditionListNested = renderConditions(wfIndex, currentPath, conditionGroupsIndex+1, condition.conditions) + + $conditionListNested = renderConditions(wfIndex, currentPath, conditionGroupsIndex+1, condition.conditions) $nestedCondition.append($conditionListNested); // Recursive call for nested conditions @@ -484,7 +486,7 @@ function renderConditions(wfIndex, parentIndexPath, conditionGroupsIndex, condit } else { // INDIVIDUAL CONDITIONS - let $conditionIcon = $("", { + let $conditionIcon = $("", { class: "fa-solid fa-arrows-split-up-and-left fa-rotate-270 bckg-icon-3-line " }); @@ -505,27 +507,27 @@ function renderConditions(wfIndex, parentIndexPath, conditionGroupsIndex, condit // Create dropdown for condition field let $fieldDropdown = createEditableDropdown( `${currentPath}.field`, - getString("WF_Condition_field"), - fieldOptions, - condition.field, + getString("WF_Condition_field"), + fieldOptions, + condition.field, `wf-${wfIndex}-${currentPath.replace(/\./g, "-")}-field` ); // Create dropdown for operator let $operatorDropdown = createEditableDropdown( - `${currentPath}.operator`, - getString("WF_Condition_operator"), - operatorTypes, - condition.operator, + `${currentPath}.operator`, + getString("WF_Condition_operator"), + operatorTypes, + condition.operator, `wf-${wfIndex}-${currentPath.replace(/\./g, "-")}-operator` ); // Editable input for condition value let $editableInput = createEditableInput( - `${currentPath}.value`, - getString("WF_Condition_value"), - condition.value, - `wf-${wfIndex}-${currentPath.replace(/\./g, "-")}-value`, + `${currentPath}.value`, + getString("WF_Condition_value"), + condition.value, + `wf-${wfIndex}-${currentPath.replace(/\./g, "-")}-value`, "condition-value-input" ); @@ -535,7 +537,7 @@ function renderConditions(wfIndex, parentIndexPath, conditionGroupsIndex, condit $conditionItemsWrap.append($editableInput); // Append editable input for condition value let $conditionRemoveButtonWrap = $("
", { class: "button-container col-sm-1 col-sx-12" }); - let $conditionRemoveButtonIcon = $("", { + let $conditionRemoveButtonIcon = $("", { class: "fa-solid fa-trash" }); let $conditionRemoveButton = $("
", { @@ -549,7 +551,7 @@ function renderConditions(wfIndex, parentIndexPath, conditionGroupsIndex, condit $conditionItem.append($conditionItemsWrap); $conditionItem.append($conditionRemoveButtonWrap); - $conditionList.append($conditionItem); + $conditionList.append($conditionItem); } lastConditionIndex = conditionIndex @@ -562,7 +564,7 @@ function renderConditions(wfIndex, parentIndexPath, conditionGroupsIndex, condit if (conditionGroupsIndex != 0) { // Add Condition button let $conditionAddWrap = $("
", { class: "button-container col-sm-6 col-sx-12" }); - let $conditionAddIcon = $("", { + let $conditionAddIcon = $("", { class: "fa-solid fa-plus" }); let $conditionAddButton = $("
", { @@ -574,7 +576,7 @@ function renderConditions(wfIndex, parentIndexPath, conditionGroupsIndex, condit // Remove Condition Group button let $conditionGroupRemoveWrap = $("
", { class: "button-container col-sx-12" }); - let $conditionGroupRemoveIcon = $("", { + let $conditionGroupRemoveIcon = $("", { class: "fa-solid fa-trash" }); let $conditionGroupRemoveButton = $("
", { @@ -592,7 +594,7 @@ function renderConditions(wfIndex, parentIndexPath, conditionGroupsIndex, condit // Add Condition Group button let $conditionsGroupAddWrap = $("
", { class: "button-container col-sm-6 col-sx-12" }); - let $conditionsGroupAddIcon = $("", { + let $conditionsGroupAddIcon = $("", { class: "fa-solid fa-plus" }); let $conditionsGroupAddButton = $("
", { @@ -606,9 +608,9 @@ function renderConditions(wfIndex, parentIndexPath, conditionGroupsIndex, condit $conditionList.append($addButtonWrap); $conditionListWrap.append($conditionList) - - - let $res = $("
", { + + + let $res = $("
", { class: "condition-list-res col-sm-12 col-sx-12" }); @@ -627,8 +629,8 @@ function createEditableDropdown(jsonPath, labelText, options, selectedValue, id) class: "form-group col-sm-12 col-sx-12" }); - let $label = $(" ', '', '', '', 'importWorkflowExecute', null, "" ); } function importWorkflowExecute() -{ +{ var json = JSON.parse($('#modal-input-textarea').val()); - + workflows = getWorkflowsJson() - + workflows.push(json); updateWorkflowsJson(workflows) @@ -998,7 +1000,7 @@ function removeAction(workflows, wfIndex, actionIndex) { } console.log(actionIndex); - + // Remove the specified condition target.actions.splice(actionIndex, 1); @@ -1016,15 +1018,15 @@ function removeConditionGroup(workflows, wfIndex, parentIndexPath) { // Split the path by dots const parts = parentIndexPath.split('.'); - + // Extract the last part (index) const lastIndex = parts.pop().replace(/\D/g, ''); // Remove any non-numeric characters - + // Rebuild the path without the last part const newPath = parts.join('.'); - console.log(parentIndexPath); - console.log(newPath); + console.log(parentIndexPath); + console.log(newPath); // Navigate to the target nested object let target = getNestedObject(workflows, newPath); @@ -1074,22 +1076,22 @@ function getNestedObject(obj, path) { function getWorkflowsJson() { return workflows = JSON.parse(getCache('workflows')) || getEmptyWorkflowJson(); -} +} // --------------------------------------------------- // Get workflows JSON function updateWorkflowsJson(workflows) -{ +{ // Store the updated workflows object back into cache setCache('workflows', JSON.stringify(workflows)); -} +} // --------------------------------------------------- // Get empty workflow JSON function getEmptyWorkflowJson() { return emptyWorkflow; -} +} // --------------------------------------------------- // Save workflows JSON @@ -1100,11 +1102,11 @@ function saveWorkflows() // import $.post('php/server/query_replace_config.php', { base64data: appConfBase64, fileName: "workflows.json" }, function(msg) { - console.log(msg); - // showMessage(msg); + console.log(msg); + // showMessage(msg); write_notification(`[WF]: ${msg}`, 'interrupt'); }); -} +} // --------------------------------------------------- // Event listeners @@ -1154,7 +1156,7 @@ $(document).on("click", ".remove-condition", function () { let wfIndex = $(this).attr("wfindex"); let parentIndexPath = $(this).attr("parentIndexPath"); let conditionIndex = parseInt($(this).attr("conditionIndex"), 10); - + removeCondition(getWorkflowsJson(), wfIndex, parentIndexPath, conditionIndex); }); @@ -1162,7 +1164,7 @@ $(document).on("click", ".remove-condition", function () { $(document).on("click", ".remove-action", function () { let wfIndex = $(this).attr("wfindex"); let actionIndex = $(this).attr("actionIndex"); - + removeAction(getWorkflowsJson(), wfIndex, actionIndex); });