mirror of
https://github.com/jokob-sk/NetAlertX.git
synced 2026-03-31 07:12:23 -07:00
Merge branch 'main' of https://github.com/jokob-sk/NetAlertX
This commit is contained in:
184
docs/API_DEVICE_FIELD_LOCK.md
Normal file
184
docs/API_DEVICE_FIELD_LOCK.md
Normal file
@@ -0,0 +1,184 @@
|
||||
# Device Field Lock/Unlock API
|
||||
|
||||
## Overview
|
||||
|
||||
The Device Field Lock/Unlock feature allows users to lock specific device fields to prevent plugin overwrites. This is part of the authoritative device field update system that ensures data integrity while maintaining flexibility for user customization.
|
||||
|
||||
## Concepts
|
||||
|
||||
### Tracked Fields
|
||||
|
||||
Only certain device fields support locking. These are the fields that can be modified by both plugins and users:
|
||||
|
||||
- `devName` - Device name/hostname
|
||||
- `devVendor` - Device vendor/manufacturer
|
||||
- `devFQDN` - Fully qualified domain name
|
||||
- `devSSID` - Network SSID
|
||||
- `devParentMAC` - Parent device MAC address
|
||||
- `devParentPort` - Parent device port
|
||||
- `devParentRelType` - Parent device relationship type
|
||||
- `devVlan` - VLAN identifier
|
||||
|
||||
### Field Source Tracking
|
||||
|
||||
Every tracked field has an associated `*Source` field that indicates where the current value originated:
|
||||
|
||||
- `NEWDEV` - Created via the UI as a new device
|
||||
- `USER` - Manually edited by a user
|
||||
- `LOCKED` - Field is locked; prevents any plugin overwrites
|
||||
- Plugin name (e.g., `UNIFIAPI`, `PIHOLE`) - Last updated by this plugin
|
||||
|
||||
### Locking Mechanism
|
||||
|
||||
When a field is **locked**, its source is set to `LOCKED`. This prevents plugin overwrites based on the authorization logic:
|
||||
|
||||
1. Plugin wants to update field
|
||||
2. Authoritative handler checks field's `*Source` value
|
||||
3. If `*Source` == `LOCKED`, plugin update is rejected
|
||||
4. User can still manually unlock the field
|
||||
|
||||
When a field is **unlocked**, its source is set to `NEWDEV`, allowing plugins to resume updates.
|
||||
|
||||
## Endpoints
|
||||
|
||||
### Lock or Unlock a Field
|
||||
|
||||
```
|
||||
POST /device/{mac}/field/lock
|
||||
Authorization: Bearer {API_TOKEN}
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"fieldName": "devName",
|
||||
"lock": true
|
||||
}
|
||||
```
|
||||
|
||||
#### Parameters
|
||||
- `mac` (path, required): Device MAC address (e.g., `AA:BB:CC:DD:EE:FF`)
|
||||
- `fieldName` (body, required): Name of the field to lock/unlock. Must be one of the tracked fields listed above.
|
||||
- `lock` (body, required): Boolean. `true` to lock, `false` to unlock.
|
||||
|
||||
#### Responses
|
||||
|
||||
**Success (200)**
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
"message": "Field devName locked",
|
||||
"fieldName": "devName",
|
||||
"locked": true
|
||||
}
|
||||
```
|
||||
|
||||
**Bad Request (400)**
|
||||
```json
|
||||
{
|
||||
"success": false,
|
||||
"error": "fieldName is required"
|
||||
}
|
||||
```
|
||||
|
||||
```json
|
||||
{
|
||||
"success": false,
|
||||
"error": "Field 'devInvalidField' cannot be locked"
|
||||
}
|
||||
```
|
||||
|
||||
**Unauthorized (403)**
|
||||
```json
|
||||
{
|
||||
"success": false,
|
||||
"error": "Unauthorized"
|
||||
}
|
||||
```
|
||||
|
||||
**Not Found (404)**
|
||||
```json
|
||||
{
|
||||
"success": false,
|
||||
"error": "Device not found"
|
||||
}
|
||||
```
|
||||
|
||||
## Examples
|
||||
|
||||
### Lock a Device Name
|
||||
Prevent the device name from being overwritten by plugins:
|
||||
|
||||
```bash
|
||||
curl -X POST https://your-netalertx.local/api/device/AA:BB:CC:DD:EE:FF/field/lock \
|
||||
-H "Authorization: Bearer your-api-token" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"fieldName": "devName",
|
||||
"lock": true
|
||||
}'
|
||||
```
|
||||
|
||||
### Unlock a Field
|
||||
Allow plugins to resume updating a field:
|
||||
|
||||
```bash
|
||||
curl -X POST https://your-netalertx.local/api/device/AA:BB:CC:DD:EE:FF/field/lock \
|
||||
-H "Authorization: Bearer your-api-token" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"fieldName": "devName",
|
||||
"lock": false
|
||||
}'
|
||||
```
|
||||
|
||||
## UI Integration
|
||||
|
||||
The Device Edit form displays lock/unlock buttons for all tracked fields:
|
||||
|
||||
1. **Lock Button** (🔒): Click to prevent plugin overwrites
|
||||
2. **Unlock Button** (🔓): Click to allow plugin overwrites again
|
||||
3. **Source Indicator**: Shows current field source (USER, LOCKED, NEWDEV, or plugin name)
|
||||
|
||||
## UI Workflow
|
||||
|
||||
### Locking a Field via UI
|
||||
|
||||
1. Navigate to Device Details
|
||||
2. Find the field you want to protect
|
||||
3. Click the lock button (🔒) next to the field
|
||||
4. Button changes to unlock (🔓) and source indicator turns red (LOCKED)
|
||||
5. Field is now protected from plugin overwrites
|
||||
|
||||
### Unlocking a Field via UI
|
||||
|
||||
1. Find the locked field (button shows 🔓)
|
||||
2. Click the unlock button
|
||||
3. Button changes back to lock (🔒) and source resets to NEWDEV
|
||||
4. Plugins can now update this field again
|
||||
|
||||
## Authorization
|
||||
|
||||
All lock/unlock operations require:
|
||||
- Valid API token in `Authorization: Bearer {token}` header
|
||||
- User must be authenticated to the NetAlertX instance
|
||||
|
||||
## Implementation Details
|
||||
|
||||
### Backend Logic
|
||||
The lock/unlock feature is implemented in:
|
||||
- **API Endpoint**: `/server/api_server/api_server_start.py` - `api_device_field_lock()`
|
||||
- **Data Model**: `/server/models/device_instance.py` - Authorization checks in `setDeviceData()`
|
||||
- **Database**: Devices table with `*Source` columns tracking field origins
|
||||
|
||||
### Authorization Handler
|
||||
|
||||
The authoritative field update logic prevents plugin overwrites:
|
||||
|
||||
1. Plugin provides new value for field via plugin config `SET_ALWAYS`/`SET_EMPTY`
|
||||
2. Authoritative handler (in DeviceInstance) checks `{field}Source` value
|
||||
3. If source is `LOCKED` or `USER`, plugin update is rejected
|
||||
4. If source is `NEWDEV` or plugin name, plugin update is accepted
|
||||
|
||||
## See Also
|
||||
- [API Device Endpoints Documentation](./API_DEVICE.md)
|
||||
- [Authoritative Field Updates System](./PLUGINS_DEV.md#authoritative-fields)
|
||||
- [Plugin Configuration Reference](./PLUGINS_DEV_CONFIG.md)
|
||||
@@ -4,7 +4,7 @@ Please follow tips 1 - 4 to get a more detailed error.
|
||||
|
||||
## 1. More Logging
|
||||
|
||||
When debugging an issue always set the highest log level:
|
||||
When debugging an issue always set the highest log level in **Settings -> Core**:
|
||||
|
||||
`LOG_LEVEL='trace'`
|
||||
|
||||
|
||||
@@ -47,4 +47,25 @@ The **MAC** field and the **Last IP** field will then become editable.
|
||||
|
||||
To speed up device population you can also copy data from an existing device. This can be done from the **Tools** tab on the Device details.
|
||||
|
||||
## Field Locking (Preventing Plugin Overwrites)
|
||||
|
||||
NetAlertX allows you to "lock" specific device fields to prevent plugins from automatically overwriting your custom values. This is useful when you've manually corrected information that might be discovered differently by discovery plugins.
|
||||
|
||||
### Quick Start
|
||||
|
||||
1. Open a device for editing
|
||||
2. Click the **lock button** (🔒) next to any tracked field
|
||||
3. The field is now protected—plugins cannot change it until you unlock it
|
||||
|
||||
### Tracked Fields
|
||||
|
||||
The following 10 fields support locking:
|
||||
- devMac, devName, devLastIP, devVendor, devFQDN, devSSID, devParentMAC, devParentPort, devParentRelType, devVlan
|
||||
|
||||
### See Also
|
||||
|
||||
- **For Users:** [Quick Reference - Device Field Lock/Unlock](QUICK_REFERENCE_FIELD_LOCK.md) - How to use field locking
|
||||
- **For Developers:** [API Device Field Lock Documentation](API_DEVICE_FIELD_LOCK.md) - Technical API reference
|
||||
- **For Plugin Developers:** [Plugin Field Configuration (SET_ALWAYS/SET_EMPTY)](PLUGINS_DEV_CONFIG.md) - Configure which fields plugins can update
|
||||
|
||||
|
||||
|
||||
@@ -27,6 +27,9 @@ services:
|
||||
- NET_ADMIN # Required for ARP scanning
|
||||
- NET_RAW # Required for raw socket operations
|
||||
- NET_BIND_SERVICE # Required to bind to privileged ports (nbtscan)
|
||||
- CHOWN # Required for root-entrypoint to chown /data + /tmp before dropping privileges
|
||||
- SETUID # Required for root-entrypoint to switch to non-root user
|
||||
- SETGID # Required for root-entrypoint to switch to non-root group
|
||||
|
||||
volumes:
|
||||
- type: volume # Persistent Docker-managed named volume for config + database
|
||||
|
||||
@@ -177,6 +177,55 @@ After persistence:
|
||||
|
||||
---
|
||||
|
||||
## Field Update Authorization (SET_ALWAYS / SET_EMPTY)
|
||||
|
||||
For tracked fields (devMac, devName, devLastIP, devVendor, devFQDN, devSSID, devParentMAC, devParentPort, devParentRelType, devVlan), plugins can configure how they interact with the authoritative field update system.
|
||||
|
||||
### SET_ALWAYS
|
||||
|
||||
**Mandatory when field is tracked.**
|
||||
|
||||
Controls whether a plugin field is enabled:
|
||||
|
||||
- `["devName", "devLastIP"]` - Plugin can always overwrite this field when authorized (subject to source-based permissions)
|
||||
|
||||
**Authorization logic:** Even with a field listed in `SET_ALWAYS`, the plugin respects source-based permissions:
|
||||
|
||||
- Cannot overwrite `USER` source (user manually edited)
|
||||
- Cannot overwrite `LOCKED` source (user locked field)
|
||||
- Can overwrite `NEWDEV` or plugin-owned sources (if plugin has SET_ALWAYS enabled)
|
||||
- Will update plugin-owned sources if value the same
|
||||
|
||||
**Example in config.json:**
|
||||
|
||||
```json
|
||||
{
|
||||
"SET_ALWAYS": ["devName", "devLastIP"]
|
||||
}
|
||||
```
|
||||
|
||||
### SET_EMPTY
|
||||
|
||||
**Optional field override.**
|
||||
|
||||
Restricts when a plugin can update a field:
|
||||
|
||||
- `"SET_EMPTY": ["devName", "devLastIP"]` - Overwrite these fields only if current value is empty OR source is `NEWDEV`
|
||||
|
||||
**Use case:** Some plugins discover optional enrichment data (like vendor/hostname) that shouldn't override user-set or existing values. Use `SET_EMPTY` to be less aggressive.
|
||||
|
||||
|
||||
### Authorization Decision Flow
|
||||
|
||||
1. **Source check:** Is field LOCKED or USER? → REJECT (protected)
|
||||
2. **Field in SET_ALWAYS check:** Is SET_ALWAYS enabled for this plugin+field? → YES: ALLOW (can overwrite empty values, NEWDEV, plugin sources, etc.) | NO: Continue to step 3
|
||||
3. **Field in SET_EMPTY check:** Is SET_EMPTY enabled AND field non-empty+non-NEWDEV? → REJECT
|
||||
4. **Default behavior:** Allow overwrite if field empty or NEWDEV source
|
||||
|
||||
**Note:** Check each plugin's `config.json` manifest for its specific SET_ALWAYS/SET_EMPTY configuration.
|
||||
|
||||
---
|
||||
|
||||
## Summary
|
||||
|
||||
The lifecycle of a plugin configuration is:
|
||||
|
||||
147
docs/QUICK_REFERENCE_FIELD_LOCK.md
Normal file
147
docs/QUICK_REFERENCE_FIELD_LOCK.md
Normal file
@@ -0,0 +1,147 @@
|
||||
# Quick Reference Guide - Device Field Lock/Unlock System
|
||||
|
||||
## One-Minute Overview
|
||||
|
||||
The device field lock/unlock system allows you to protect specific device fields from being automatically overwritten by scanning plugins. When you lock a field, NetAlertX remembers your choice and prevents plugins from changing that value until you unlock it.
|
||||
|
||||
**Use case:** You've manually corrected a device name or port number and want to keep it that way, even when plugins discover different values.
|
||||
|
||||
## Tracked Fields
|
||||
|
||||
These are the ONLY fields that can be locked:
|
||||
|
||||
- devName - Device hostname/alias
|
||||
- devVendor - Device manufacturer
|
||||
- devFQDN - Fully qualified domain name
|
||||
- devSSID - WiFi network name
|
||||
- devParentMAC - Parent/gateway MAC
|
||||
- devParentPort - Parent device port
|
||||
- devParentRelType - Relationship type (e.g., "gateway")
|
||||
- devVlan - VLAN identifier
|
||||
|
||||
## Source Values Explained
|
||||
|
||||
Each locked field has a "source" indicator that shows you why the value is protected:
|
||||
|
||||
| Indicator | Meaning | Can It Change? |
|
||||
|-----------|---------|---|
|
||||
| 🔒 **LOCKED** | You locked this field | No, until you unlock it |
|
||||
| ✏️ **USER** | You edited this field | No, plugins can't overwrite |
|
||||
| 📡 **NEWDEV** | Default/unset value | Yes, plugins can update |
|
||||
| 📡 **Plugin name** | Last updated by a plugin (e.g., UNIFIAPI) | Yes, plugins can update if field in SET_ALWAYS |
|
||||
|
||||
## How to Use
|
||||
|
||||
### Lock a Field (Prevent Plugin Changes)
|
||||
|
||||
1. Navigate to **Device Details** for the device
|
||||
2. Find the field you want to protect (e.g., device name)
|
||||
3. Click the **lock button** (🔒) next to the field
|
||||
4. The button changes to **unlock** (🔓)
|
||||
5. That field is now protected
|
||||
|
||||
### Unlock a Field (Allow Plugin Updates)
|
||||
|
||||
1. Go to **Device Details**
|
||||
2. Find the locked field (shows 🔓)
|
||||
3. Click the **unlock button** (🔓)
|
||||
4. The button changes back to **lock** (🔒)
|
||||
5. Plugins can now update that field again
|
||||
|
||||
## Common Scenarios
|
||||
|
||||
### Scenario 1: You've Named Your Device and Want to Keep the Name
|
||||
|
||||
1. You manually edit device name to "Living Room Smart TV"
|
||||
2. A scanning plugin later discovers it as "Unknown Device" or "DEVICE-ABC123"
|
||||
3. **Solution:** Lock the device name field
|
||||
4. Your custom name is preserved even after future scans
|
||||
|
||||
### Scenario 2: You Lock a Field, But It Still Changes
|
||||
|
||||
**This means the field source is USER or LOCKED (protected).** Check:
|
||||
- Is it showing the lock icon? (If yes, it's protected)
|
||||
- Wait a moment—sometimes changes take a few seconds to display
|
||||
- Try refreshing the page
|
||||
|
||||
### Scenario 3: You Want to Let Plugins Update Again
|
||||
|
||||
1. Find the device with locked fields
|
||||
2. Click the unlock button (🔓) next to each field
|
||||
3. Refresh the page
|
||||
4. Next time a plugin runs, it can update that field
|
||||
|
||||
## What Happens When You Lock a Field
|
||||
|
||||
- ✅ Your custom value is kept
|
||||
- ✅ Future plugin scans won't overwrite it
|
||||
- ✅ You can still manually edit it anytime after unlocking
|
||||
- ✅ Lock persists across plugin runs
|
||||
- ✅ Other users can see it's locked
|
||||
|
||||
## What Happens When You Unlock a Field
|
||||
|
||||
- ✅ Plugins can update it again on next scan
|
||||
- ✅ If a plugin has a new value, it will be applied
|
||||
- ✅ You can lock it again anytime
|
||||
- ✅ Your manual edits are still saved in the database
|
||||
|
||||
## Error Messages & Solutions
|
||||
|
||||
| Message | What It Means | What to Do |
|
||||
|---------|--------------|-----------|
|
||||
| "Field cannot be locked" | You tried to lock a field that doesn't support locking | Only lock the fields listed above |
|
||||
| "Device not found" | The device MAC address doesn't exist | Verify the device hasn't been deleted |
|
||||
| Lock button doesn't work | Network or permission issue | Refresh the page and try again |
|
||||
| Unexpected field changed | Field might have been unlocked | Check if field shows unlock icon (🔓) |
|
||||
|
||||
## Quick Tips
|
||||
|
||||
- **Lock names you manually corrected** to keep them stable
|
||||
- **Leave discovery fields (vendor, FQDN) unlocked** for automatic updates
|
||||
- **Use locks sparingly**—they prevent automatic data enrichment
|
||||
- **Check the source indicator** (colored badge) to understand field origin
|
||||
- **Lock buttons only appear for devices that are saved** (not for new devices being created)
|
||||
|
||||
## When to Lock vs. When NOT to Lock
|
||||
|
||||
### ✅ **Good reasons to lock:**
|
||||
- You've customized the device name and it's correct
|
||||
- You've set a static IP and it shouldn't change
|
||||
- You've configured VLAN information
|
||||
- You know the parent device and don't want it auto-corrected
|
||||
|
||||
### ❌ **Bad reasons to lock:**
|
||||
- The value seems wrong—edit it first, then lock
|
||||
- You want to prevent data from another source—use field lock, not to hide problems
|
||||
- You're trying to force a value the system disagrees with
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
**Lock button not appearing:**
|
||||
- Confirm the field is one of the tracked fields (see list above)
|
||||
- Confirm the device is already saved (new devices don't show lock buttons)
|
||||
- Refresh the page
|
||||
|
||||
**Lock button is there but click doesn't work:**
|
||||
- Check your internet connection
|
||||
- Check you have permission to edit devices
|
||||
- Look at browser console (F12 > Console tab) for error messages
|
||||
- Try again in a few seconds
|
||||
|
||||
**Field still changes after locking:**
|
||||
- Double-check the lock icon shows
|
||||
- Reload the page—the change might be a display issue
|
||||
- Check if you accidentally unlocked it
|
||||
- Open an issue if it persists
|
||||
|
||||
## For More Information
|
||||
|
||||
- **Technical details:** See [API_DEVICE_FIELD_LOCK.md](API_DEVICE_FIELD_LOCK.md)
|
||||
- **Plugin configuration:** See [PLUGINS_DEV_CONFIG.md](PLUGINS_DEV_CONFIG.md)
|
||||
- **Admin guide:** See [DEVICE_MANAGEMENT.md](DEVICE_MANAGEMENT.md)
|
||||
|
||||
---
|
||||
|
||||
**Quick Start:** Find a device field you want to protect → Click the lock icon → That's it! The field won't change until you unlock it.
|
||||
|
||||
Reference in New Issue
Block a user