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

This commit is contained in:
Jokob @NetAlertX
2026-06-17 06:43:51 +00:00
6 changed files with 114 additions and 11 deletions

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`

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.

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 57 KiB

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;

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)).

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();
});
}
// ---------------------------------------------------