Merge branch 'next_release' of https://github.com/netalertx/NetAlertX into next_release

This commit is contained in:
Jokob @NetAlertX committed 2026-06-17 06:43:51 +00:00
commit bb29824ac1
6 files changed
+114 -11

No files matched your search

+11
View File
@@ -23,6 +23,7 @@ Triggers define the event that activates a workflow. They monitor changes to obj
> Workflows not running? Check the [Workflows debugging](./WORKFLOWS_DEBUGGING.md) guide how to troubleshoot triggers and conditions.
#### Example Trigger:
- **Object Type**: `Devices`
- **Event Type**: `update`
@@ -38,7 +39,9 @@ Conditions determine whether a workflow should proceed based on certain criteria
> To better understand how to use specific Device fields, please read through the [Database overview](./DATABASE.md) guide.
#### Example Condition:
- **Logic**: `AND`
- **Field**: `devVendor`
- **Operator**: `contains` (case in-sensitive)
- **Value**: `Google`
@@ -53,8 +56,16 @@ Actions define the tasks that the workflow will perform once the conditions are
You can include multiple actions that should execute once the conditions are met.
#### Target device for the Actions
You can change the target of the actions of the workflows. You can either target the device that triggered by selecting the **Apply action to** to `triggering_device`, or target multiple devices by selecting `query` in the **Apply action to** dropdown.
![Action target](./img/WORKFLOWS/actions_target.png)
#### Example Action:
- **Action Type**: `update_field`
- **Field**: `devIsNew`
- **Value**: `0`
+70 -1
View File
@@ -54,6 +54,7 @@ Sometimes devices are manually archived (e.g., no longer expected on the network
* `devIsArchived` is `1` (archived).
* `devPresentLastScan` is `1` (device was detected in the latest scan).
* **Action**:
* Updates the device to set `devIsArchived` to `0` (unarchived).
@@ -110,6 +111,7 @@ When new devices join your network, assigning them to the correct network node i
* **Conditions**:
* `devLastIP` contains `192.168.1.` (matches subnet).
* **Action**:
* Sets `devNetworkNode` to the specified MAC address.
@@ -175,6 +177,7 @@ You may want to automatically clear out newly detected Google devices (such as C
* `devVendor` contains `Google`.
* `devIsNew` is `1` (device marked as new).
* **Actions**:
1. Sets `devIsNew` to `0` (mark as not new).
@@ -182,4 +185,70 @@ You may want to automatically clear out newly detected Google devices (such as C
### ✅ Result
Any newly detected Google devices are cleaned up instantly — first marked as not new, then deleted — helping you avoid clutter in your device records.
Any newly detected Google devices are cleaned up instantly — first marked as not new, then deleted — helping you avoid clutter in your device records.
---
## Example 4: On new device discovery archive the old device with the same ip
This workflow automatically archives devices if a new device is discovered with an already assigned IP.
### 📋 Use Case
This workflow is useful if you are assigning static IPs to your devices. This workflow can also help with archiving device entries with [random MAC addresses](./RANDOM_MAC.md).
### ⚙️ Workflow Configuration
```json
{
"name": "Archive device with same ip",
"trigger": {
"object_type": "Devices",
"event_type": "insert"
},
"conditions": [
{
"logic": "AND",
"conditions": []
}
],
"actions": [
{
"type": "update_field",
"field": "devIsArchived",
"value": "1",
"target": {
"strategy": "query",
"conditions": [
{
"field": "devLastIP",
"operator": "equals",
"value": "{{trigger.devLastIP}}"
}
]
}
}
]
}
```
### 🔍 Explanation
* **Trigger**: Runs on a new device being inserted.
* **Conditions**:
* `N/A`
* **Target Conditions**:
* `devLastIP` of the target is the same as the newly discovered device's `devLastIP` value.
* **Actions**:
1. Sets `devIsArchived` to `1` (mark target device as archived).
### ✅ Result
Any newly detected device that has the same IP as an existing device will automatically trigger the archival of the old device.
Binary file not shown.

After

Width:  |  Height:  |  Size: 57 KiB

+17
View File
@@ -2345,6 +2345,17 @@ textarea[readonly],
padding: 5px;
}
.workflows .add-target-condition
{
margin: 10px;
text-align: center;
}
.workflows .inline-hint
{
margin: 5px;
}
.workflows
{
max-width: 800px;
@@ -2437,6 +2448,12 @@ textarea[readonly],
color: var(--color-green) !important;
}
.workflows .add-condition, .workflows .add-condition-group, .workflows .add-target-condition
{
padding-top: 0.5em;
padding-bottom: 0.5em;
}
.workflows .action-target-conditions
{
opacity: 0.8;
+2 -2
View File
@@ -40,14 +40,14 @@ def main():
if entry['result'] == 0:
leases = entry['arguments']['leases']
for lease in leases:
mac = lease['hw-address']
mac = lease['hw-address']
state = lease['state']
if is_mac(mac):
plugin_objects.add_object(
primaryId = mac,
secondaryId = lease['ip-address'],
# Active or not, similar to watched1 of DHCPLSS plugin
watched1 = state == 0,
watched1 = state == 0,
watched2 = lease['hostname'],
watched3 = None,
# Default (or assigned) (0), declined (1), expired-reclaimed (2), released (3), and registered (4)).
+14 -8
View File
@@ -325,8 +325,8 @@ function generateWorkflowUI(wf, wfIndex) {
.append($("<i>", { class: "fa-solid fa-crosshairs" }))
.append(` ${getString("WF_Action_target_conditions")}:`);
let $tokenHint = $("<div>", { class: "text-muted small col-sm-12 col-xs-12" })
.text(getString("WF_Action_token_hint"));
let $tokenHint = $("<div>", { class: "text-muted inline-hint small col-sm-12 col-xs-12" })
.html(getString("WF_Action_token_hint"));
$targetConditionsWrap.append($targetConditionsTitle);
$targetConditionsWrap.append($tokenHint);
@@ -1230,12 +1230,18 @@ function saveWorkflows()
appConfBase64 = btoa(JSON.stringify(getWorkflowsJson()))
// import
$.post('php/server/query_replace_config.php', { base64data: appConfBase64, fileName: "workflows.json" }, function(msg) {
console.log(msg);
// showMessage(msg);
hideSpinner();
write_notification(`[WF]: ${msg}`, 'interrupt');
});
$.post('php/server/query_replace_config.php', { base64data: appConfBase64, fileName: "workflows.json" })
.done(function(msg) {
console.log(msg);
write_notification(`[WF]: ${msg}`, 'interrupt');
})
.fail(function(jqXHR, textStatus, errorThrown) {
console.warn("Failed to save workflows.json:", textStatus, errorThrown);
write_notification(`[WF]: Save failed (${textStatus})`, 'interrupt');
})
.always(function() {
hideSpinner();
});
}
// ---------------------------------------------------