Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions .gemini/skills/plugin-development/plugin-skill.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# Plugin development skill

1. Assess requirements
2. Read `docs/PLUGINS_DEV.md`
3. Confirm field mapping
4. Ask clarifying questions
5. code placed in `front/plugins/<new plugin name>`


Plugin prefix:

- has to be uppercase letters only (no underscores)
- must be unique
- keep short but readable if possible


7 changes: 7 additions & 0 deletions front/css/app.css
Original file line number Diff line number Diff line change
Expand Up @@ -1846,6 +1846,13 @@ textarea[readonly],
display: grid;
}

@media (min-width: 768px) {
.modal-dialog {
width: 750px;
margin: 30px auto;
}
}

/* ----------------------------------------------------------------- */
/* NETWORK page */
/* ----------------------------------------------------------------- */
Expand Down
7 changes: 6 additions & 1 deletion front/js/modal.js
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,12 @@ function showModalPopupForm(
}
}

const fieldOptionsOverride = field.type?.elements[0]?.elementOptions || [];
// For select elements use field.options (the selectable values); for all other
// element types fall back to elementOptions (used for input attributes like placeholder).
const elementType = field.type?.elements[0]?.elementType;
const fieldOptionsOverride = (elementType === 'select' && field.options?.length)
? field.options
: (field.type?.elements[0]?.elementOptions || []);
const setValue = initialValue;
const setType = JSON.stringify(field.type);
const setEvents = field.events || []; // default to empty array if missing
Expand Down
1 change: 1 addition & 0 deletions front/js/settings_utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -1175,6 +1175,7 @@ function generateFormHtml(settingsData, set, overrideValue, overrideOptions, ori

// Parse the setType JSON string
// console.log(processQuotes(setType));
console.log(setType);

const setTypeObject = JSON.parse(processQuotes(setType))
const dataType = setTypeObject.dataType;
Expand Down
4 changes: 2 additions & 2 deletions front/php/templates/modals.php
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<!-- ---------------------------------------------------------------------------
# NetAlertX
# Open Source Network Guard / WIFI & LAN intrusion detector
# Open Source Network Guard / WIFI & LAN intrusion detector
#
# notificacion.php - Front module. Common notification & modal window
#-------------------------------------------------------------------------------
Expand Down Expand Up @@ -129,7 +129,7 @@

<div id="modal-form-message" class="modal-body"> Modal message </div>

<div id="modal-form-plc"></div>
<div id="modal-form-plc" style="overflow-y: auto; max-height: 60vh; padding: 0 15px;"></div>

<div class="modal-footer">
<button id="modal-form-cancel" type="button" class="btn btn-outline pull-left" style="min-width: 80px;" data-dismiss="modal"> Cancel </button>
Expand Down
84 changes: 84 additions & 0 deletions front/plugins/rest_import/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
## Overview

Import devices from any REST API that returns JSON

Designed to replace small vendor-specific plugins for systems like OPNsense, RouterOS, asset management tools, and custom inventory APIs. Multiple endpoints can be configured independently in a single plugin instance.

### Quick setup guide

Navigate to **Settings** > **REST Import** and click **Add** to create an import definition.

| Field | Description |
|---|---|
| **Name** | Friendly label shown in logs (e.g. `OPNsense DHCP`) |
| **URL** | Full REST endpoint URL |
| **Method** | `GET` or `POST` |
| **Verify SSL** | Disable for self-signed certificates |
| **Auth Type** | `none`, `basic`, or `bearer` |
| **Username / API Key** | Used with `basic` auth |
| **Password / API Secret** | Used with `basic` auth |
| **Bearer Token** | Used with `bearer` auth |
| **Custom Headers** | Optional. One `Key: Value` per line |
| **POST Body** | Optional JSON body for `POST` requests |
| **Device List Path** | Dot-separated path to the array of records (e.g. `rows`, `data.devices`). Leave blank if the response is already an array |

### Field mapping

Map API response fields to NetAlertX scan fields. Leave a mapping blank to skip that field.

| Popup field | Scan column |
|---|---|
| MAC Address | `scanMac` |
| IP Address | `scanLastIP` |
| Device Name | `scanName` |
| Vendor | `scanVendor` |
| SSID | `scanSSID` |
| Device Type | `scanType` |
| Parent MAC | `scanParentMAC` |
| Parent Port | `scanParentPort` |
| Site | `scanSite` |
| VLAN | `scanVlan` |

### Fake MAC generation

Enable **Generate Fake MAC** when the API does not expose MAC addresses (e.g. remote ICMP scans, IP-only inventory systems). A deterministic fake MAC is derived from the IP address using the `fa:ce:` prefix. Requires a valid IP mapping.

> [!WARNING]
> Fake MACs can cause inconsistencies if IP addresses change between scans. Static IPs are strongly recommended when using this feature.

### Example: OPNsense Dnsmasq API

**Response:**
```json
{
"rows": [
{
"hwaddr": "94:18:65:de:22:01",
"address": "192.168.1.2",
"hostname": "Orbi-Base-Station",
"mac_info": "NETGEAR"
}
]
}
```

**Configuration:**
```
Name: OPNsense DHCP
URL: https://firewall/api/dnsmasq/leases/search
Method: GET
Auth Type: basic
Username: admin
Device List Path: rows
MAC Address: hwaddr
IP Address: address
Device Name: hostname
Vendor: mac_info
```
Comment on lines +66 to +77

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Add a language to the fenced configuration block.

The fenced block at Line 66 has no language identifier, matching the markdownlint MD040 warning.

📝 Suggested patch
-```
+```text
 Name:              OPNsense DHCP
 URL:               https://firewall/api/dnsmasq/leases/search
 Method:            GET
 Auth Type:         basic
 Username:          admin
 Device List Path:  rows
 MAC Address:       hwaddr
 IP Address:        address
 Device Name:       hostname
 Vendor:            mac_info
</details>

<details>
<summary>🧰 Tools</summary>

<details>
<summary>🪛 markdownlint-cli2 (0.22.1)</summary>

[warning] 66-66: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

</details>

</details>

<details>
<summary>🤖 Prompt for AI Agents</summary>

Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @front/plugins/rest_import/README.md around lines 66 - 77, Add a language
identifier to the fenced code block that contains the OPNsense DHCP
configuration example. Change the opening triple backticks () to include a language identifier (text) to comply with markdownlint rule MD040, which
requires all fenced code blocks to have a specified language for proper syntax
highlighting and linting compliance.


</details>

<!-- fingerprinting:phantom:poseidon:hawk -->

<!-- cr-comment:v1:3a910b619fdb2af36c9e5dda -->

_Source: Linters/SAST tools_

<!-- This is an auto-generated comment by CodeRabbit -->


### Notes

- Version: 1.0.0
- Author: `jokob-sk`
- Records with missing or invalid MAC addresses are skipped unless **Generate Fake MAC** is enabled
- Each import definition executes independently; failed imports do not block others
Loading
Loading