feat: add two-tier permission system with plugin and object-level access control#213
feat: add two-tier permission system with plugin and object-level access control#213
Conversation
…ess control - Add LibreNMSPermissionMixin and NetBoxObjectPermissionMixin to all views - Enforce view/change permissions on LibreNMSSettings model - Add NetBox object permission checks on sync POST handlers - Auto-fallback to synchronous mode for non-superuser background jobs - Update navigation, API, templates, and import UI for permission gating - Add user-facing permissions documentation and mkdocs nav entry - Add test_permissions.py and update test_background_jobs.py
There was a problem hiding this comment.
Pull request overview
Adds a consistent two-tier authorization scheme across the NetBox LibreNMS plugin: a plugin-level permission gate for page access/write actions, plus NetBox model permission checks for object-mutating sync/import operations. It also adjusts background-job UX/behavior to fall back to synchronous execution for non-superusers (due to NetBox core background-task API restrictions).
Changes:
- Introduces reusable permission mixins/constants and applies them across sync/import/status/settings views.
- Adds model-level permission enforcement for sync/import POST handlers and passes user context into import utilities/jobs for permission checks.
- Updates import UI/docs/tests to reflect background-job superuser-only polling and the new permission model.
Reviewed changes
Copilot reviewed 33 out of 33 changed files in this pull request and generated 8 comments.
Show a summary per file
| File | Description |
|---|---|
| netbox_librenms_plugin/views/mixins.py | Adds LibreNMSPermissionMixin + NetBoxObjectPermissionMixin helpers used across views. |
| netbox_librenms_plugin/constants.py | Defines plugin permission constants (PERM_VIEW_PLUGIN, PERM_CHANGE_PLUGIN). |
| netbox_librenms_plugin/views/sync/locations.py | Gates location create/update POSTs behind plugin write permission. |
| netbox_librenms_plugin/views/sync/ip_addresses.py | Adds combined plugin + object permission enforcement for IP sync POSTs. |
| netbox_librenms_plugin/views/sync/interfaces.py | Adds combined plugin + object permission enforcement for interface sync/delete POSTs. |
| netbox_librenms_plugin/views/sync/cables.py | Adds combined plugin + object permission enforcement for cable sync POSTs. |
| netbox_librenms_plugin/views/sync/devices.py | Gates device add/update actions behind plugin write permission. |
| netbox_librenms_plugin/views/sync/device_fields.py | Adds combined plugin + object permission enforcement for device-field update actions. |
| netbox_librenms_plugin/views/base/librenms_sync_view.py | Applies plugin view permission gate to base sync list view. |
| netbox_librenms_plugin/views/base/interfaces_view.py | Applies plugin view permission gate to base interfaces view. |
| netbox_librenms_plugin/views/base/ip_addresses_view.py | Applies plugin view permission gate to base IPs view and verify endpoint. |
| netbox_librenms_plugin/views/base/cables_view.py | Applies plugin view permission gate to base cables view. |
| netbox_librenms_plugin/views/imports/list.py | Applies plugin view permission gate + superuser-only background-job selection + context flag for template. |
| netbox_librenms_plugin/views/imports/actions.py | Gates bulk import confirm/import actions behind plugin write permission; propagates user for permission checks; handles PermissionDenied. |
| netbox_librenms_plugin/import_utils.py | Adds permission-check helpers and checks at start of bulk imports; plumbs user through. |
| netbox_librenms_plugin/jobs.py | Passes user context into import utilities from background jobs. |
| netbox_librenms_plugin/api/views.py | Adds DRF permission class for plugin API endpoints; converts sync_job_status to DRF decorators. |
| netbox_librenms_plugin/navigation.py | Requires plugin view permission for menu visibility; renames menu label. |
| netbox_librenms_plugin/views/settings_views.py | Replaces direct PermissionRequiredMixin with plugin permission mixin + explicit write check on POST. |
| netbox_librenms_plugin/views/status_check.py | Applies plugin view permission gate to status list views. |
| netbox_librenms_plugin/views/mapping_views.py | Applies plugin view permission gate to mapping CRUD/list views. |
| netbox_librenms_plugin/views/object_sync/devices.py | Uses plugin view permission constant for tab visibility; adds plugin permission mixin to verify endpoint. |
| netbox_librenms_plugin/views/object_sync/vms.py | Uses plugin view permission constant for tab visibility. |
| netbox_librenms_plugin/templates/netbox_librenms_plugin/librenms_import.html | Disables background-job UI for non-superusers and hides cancel UI accordingly. |
| netbox_librenms_plugin/static/netbox_librenms_plugin/js/librenms_import.js | Improves filter fetch error handling; uses modal manager hide helper consistently. |
| netbox_librenms_plugin/tests/test_permissions.py | Adds comprehensive coverage for new mixins/helpers/API permission class and import permission enforcement. |
| netbox_librenms_plugin/tests/test_background_jobs.py | Updates coverage for superuser-only background-job behavior. |
| netbox_librenms_plugin/tables/locations.py | Adjusts accessors for site/location sync table data. |
| netbox_librenms_plugin/tables/interfaces.py | Refactors row attr lambda for readability. |
| netbox_librenms_plugin/tables/device_status.py | Minor comment/formatting updates related to backend permission handling. |
| docs/usage_tips/permissions.md | Adds user-facing permissions guide for the new permission model. |
| mkdocs.yml | Adds permissions guide to MkDocs nav. |
| docs/SUMMARY.md | Adds permissions guide to docs summary. |
| @@ -33,7 +34,7 @@ class InterfaceTypeMappingCreateView(generic.ObjectEditView): | |||
|
|
|||
There was a problem hiding this comment.
These views perform write operations (create/edit/delete/bulk actions) but LibreNMSPermissionMixin only requires the plugin view permission. If write actions are intended to be gated by change_librenmssettings (as described elsewhere in this PR), these classes should require the change permission as well (e.g., override permission_required for write views or add a method-based permission check).
Validate Referer header with url_has_allowed_host_and_scheme before using it for HX-Redirect or redirect targets. Falls back to request.path when the referrer is external or missing.
Add dcim.add_virtualchassis to bulk import permission checks. Explicitly validate object_type in sync views, raising Http404 for invalid values instead of silently defaulting to VM permissions.
Replace inline HTML alert response with messages.error and HX-Redirect to match the permission denial pattern used elsewhere.
Summary
Adds a two-tier permission system to all plugin views:
view_librenmssettingsgates page access;change_librenmssettingsgates write actionsdcim.add_cable,dcim.change_device)Changes
Core
LibreNMSPermissionMixinandNetBoxObjectPermissionMixininviews/mixins.pyconstants.pyLibreNMSPluginPermissionclass for API endpointsViews
LibreNMSPermissionMixinrequire_write_permission()/require_all_permissions()Background Jobs
/api/core/background-tasks/to superusers)Navigation
view_librenmssettings— unauthorized users don't see the menuDocumentation
docs/usage_tips/permissions.mdTests
test_permissions.py(780+ lines) covering mixins, API permissions, object permission helperstest_background_jobs.pyfor superuser fallback logic