Skip to content

Commit bb29824

Browse files
committed
Merge branch 'next_release' of https://github.com/netalertx/NetAlertX into next_release
2 parents 9c6e6d5 + 65dc689 commit bb29824

6 files changed

Lines changed: 114 additions & 11 deletions

File tree

‎docs/WORKFLOWS.md‎

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ Triggers define the event that activates a workflow. They monitor changes to obj
2323
> Workflows not running? Check the [Workflows debugging](./WORKFLOWS_DEBUGGING.md) guide how to troubleshoot triggers and conditions.
2424
2525
#### Example Trigger:
26+
2627
- **Object Type**: `Devices`
2728
- **Event Type**: `update`
2829

@@ -38,7 +39,9 @@ Conditions determine whether a workflow should proceed based on certain criteria
3839
> To better understand how to use specific Device fields, please read through the [Database overview](./DATABASE.md) guide.
3940
4041
#### Example Condition:
42+
4143
- **Logic**: `AND`
44+
4245
- **Field**: `devVendor`
4346
- **Operator**: `contains` (case in-sensitive)
4447
- **Value**: `Google`
@@ -53,8 +56,16 @@ Actions define the tasks that the workflow will perform once the conditions are
5356

5457
You can include multiple actions that should execute once the conditions are met.
5558

59+
#### Target device for the Actions
60+
61+
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.
62+
63+
![Action target](./img/WORKFLOWS/actions_target.png)
64+
5665
#### Example Action:
66+
5767
- **Action Type**: `update_field`
68+
5869
- **Field**: `devIsNew`
5970
- **Value**: `0`
6071

‎docs/WORKFLOW_EXAMPLES.md‎

Lines changed: 70 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ Sometimes devices are manually archived (e.g., no longer expected on the network
5454

5555
* `devIsArchived` is `1` (archived).
5656
* `devPresentLastScan` is `1` (device was detected in the latest scan).
57+
5758
* **Action**:
5859

5960
* 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
110111
* **Conditions**:
111112

112113
* `devLastIP` contains `192.168.1.` (matches subnet).
114+
113115
* **Action**:
114116

115117
* Sets `devNetworkNode` to the specified MAC address.
@@ -175,11 +177,78 @@ You may want to automatically clear out newly detected Google devices (such as C
175177

176178
* `devVendor` contains `Google`.
177179
* `devIsNew` is `1` (device marked as new).
180+
178181
* **Actions**:
179182

180183
1. Sets `devIsNew` to `0` (mark as not new).
181184
2. Deletes the device.
182185

183186
### ✅ Result
184187

185-
Any newly detected Google devices are cleaned up instantly — first marked as not new, then deleted — helping you avoid clutter in your device records.
188+
Any newly detected Google devices are cleaned up instantly — first marked as not new, then deleted — helping you avoid clutter in your device records.
189+
190+
---
191+
192+
## Example 4: On new device discovery archive the old device with the same ip
193+
194+
This workflow automatically archives devices if a new device is discovered with an already assigned IP.
195+
196+
### 📋 Use Case
197+
198+
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).
199+
200+
### ⚙️ Workflow Configuration
201+
202+
```json
203+
{
204+
"name": "Archive device with same ip",
205+
"trigger": {
206+
"object_type": "Devices",
207+
"event_type": "insert"
208+
},
209+
"conditions": [
210+
{
211+
"logic": "AND",
212+
"conditions": []
213+
}
214+
],
215+
"actions": [
216+
{
217+
"type": "update_field",
218+
"field": "devIsArchived",
219+
"value": "1",
220+
"target": {
221+
"strategy": "query",
222+
"conditions": [
223+
{
224+
"field": "devLastIP",
225+
"operator": "equals",
226+
"value": "{{trigger.devLastIP}}"
227+
}
228+
]
229+
}
230+
}
231+
]
232+
}
233+
```
234+
235+
### 🔍 Explanation
236+
237+
* **Trigger**: Runs on a new device being inserted.
238+
239+
* **Conditions**:
240+
241+
* `N/A`
242+
243+
* **Target Conditions**:
244+
245+
* `devLastIP` of the target is the same as the newly discovered device's `devLastIP` value.
246+
247+
* **Actions**:
248+
249+
1. Sets `devIsArchived` to `1` (mark target device as archived).
250+
251+
252+
### ✅ Result
253+
254+
Any newly detected device that has the same IP as an existing device will automatically trigger the archival of the old device.
57.4 KB
Loading

‎front/css/app.css‎

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2345,6 +2345,17 @@ textarea[readonly],
23452345
padding: 5px;
23462346
}
23472347

2348+
.workflows .add-target-condition
2349+
{
2350+
margin: 10px;
2351+
text-align: center;
2352+
}
2353+
2354+
.workflows .inline-hint
2355+
{
2356+
margin: 5px;
2357+
}
2358+
23482359
.workflows
23492360
{
23502361
max-width: 800px;
@@ -2437,6 +2448,12 @@ textarea[readonly],
24372448
color: var(--color-green) !important;
24382449
}
24392450

2451+
.workflows .add-condition, .workflows .add-condition-group, .workflows .add-target-condition
2452+
{
2453+
padding-top: 0.5em;
2454+
padding-bottom: 0.5em;
2455+
}
2456+
24402457
.workflows .action-target-conditions
24412458
{
24422459
opacity: 0.8;

‎front/plugins/kea_api/script.py‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,14 +40,14 @@ def main():
4040
if entry['result'] == 0:
4141
leases = entry['arguments']['leases']
4242
for lease in leases:
43-
mac = lease['hw-address']
43+
mac = lease['hw-address']
4444
state = lease['state']
4545
if is_mac(mac):
4646
plugin_objects.add_object(
4747
primaryId = mac,
4848
secondaryId = lease['ip-address'],
4949
# Active or not, similar to watched1 of DHCPLSS plugin
50-
watched1 = state == 0,
50+
watched1 = state == 0,
5151
watched2 = lease['hostname'],
5252
watched3 = None,
5353
# Default (or assigned) (0), declined (1), expired-reclaimed (2), released (3), and registered (4)).

‎front/workflowsCore.php‎

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -325,8 +325,8 @@ class: `action-target-conditions panel col-sm-12 col-sx-12 ${currentStrategy ===
325325
.append($("<i>", { class: "fa-solid fa-crosshairs" }))
326326
.append(` ${getString("WF_Action_target_conditions")}:`);
327327

328-
let $tokenHint = $("<div>", { class: "text-muted small col-sm-12 col-xs-12" })
329-
.text(getString("WF_Action_token_hint"));
328+
let $tokenHint = $("<div>", { class: "text-muted inline-hint small col-sm-12 col-xs-12" })
329+
.html(getString("WF_Action_token_hint"));
330330

331331
$targetConditionsWrap.append($targetConditionsTitle);
332332
$targetConditionsWrap.append($tokenHint);
@@ -1230,12 +1230,18 @@ function saveWorkflows()
12301230
appConfBase64 = btoa(JSON.stringify(getWorkflowsJson()))
12311231

12321232
// import
1233-
$.post('php/server/query_replace_config.php', { base64data: appConfBase64, fileName: "workflows.json" }, function(msg) {
1234-
console.log(msg);
1235-
// showMessage(msg);
1236-
hideSpinner();
1237-
write_notification(`[WF]: ${msg}`, 'interrupt');
1238-
});
1233+
$.post('php/server/query_replace_config.php', { base64data: appConfBase64, fileName: "workflows.json" })
1234+
.done(function(msg) {
1235+
console.log(msg);
1236+
write_notification(`[WF]: ${msg}`, 'interrupt');
1237+
})
1238+
.fail(function(jqXHR, textStatus, errorThrown) {
1239+
console.warn("Failed to save workflows.json:", textStatus, errorThrown);
1240+
write_notification(`[WF]: Save failed (${textStatus})`, 'interrupt');
1241+
})
1242+
.always(function() {
1243+
hideSpinner();
1244+
});
12391245
}
12401246

12411247
// ---------------------------------------------------

0 commit comments

Comments
 (0)