first commit
Some checks failed
ci / deploy (push) Has been cancelled
CodeQL Advanced / Analyze (actions) (push) Has been cancelled
CodeQL Advanced / Analyze (javascript-typescript) (push) Has been cancelled
CodeQL Advanced / Analyze (python) (push) Has been cancelled

This commit is contained in:
Vlastislav Svatek
2026-06-05 10:39:05 +02:00
commit 673e67106e
217 changed files with 76612 additions and 0 deletions

View File

@@ -0,0 +1,194 @@
import logging
from django.contrib import messages
from django.http import HttpResponse
from django.shortcuts import redirect, render
from django.utils.html import escape
from django.views import View
from netbox_librenms_plugin.forms import ImportSettingsForm, ServerConfigForm
from netbox_librenms_plugin.librenms_api import LibreNMSAPI
from netbox_librenms_plugin.models import LibreNMSSettings
from netbox_librenms_plugin.utils import save_user_pref
from netbox_librenms_plugin.views.mixins import LibreNMSPermissionMixin
logger = logging.getLogger(__name__)
class LibreNMSSettingsView(LibreNMSPermissionMixin, View):
"""
View for managing plugin settings including server selection and import options.
Uses two separate forms for cleaner validation and separation of concerns.
"""
template_name = "netbox_librenms_plugin/settings.html"
def get(self, request):
"""Display both settings forms."""
# Get or create the settings object
settings, created = LibreNMSSettings.objects.get_or_create()
# Instantiate both forms
server_form = ServerConfigForm(instance=settings)
import_form = ImportSettingsForm(instance=settings)
return render(
request,
self.template_name,
{
"server_form": server_form,
"import_form": import_form,
"object": settings,
},
)
def post(self, request):
"""Handle form submission - process the appropriate form based on form_type."""
# Check write permission for POST actions
if error := self.require_write_permission():
return error
# Get or create the settings object
settings, created = LibreNMSSettings.objects.get_or_create()
# Determine which form was submitted
form_type = request.POST.get("form_type")
if form_type == "server_config":
# Process server configuration form
server_form = ServerConfigForm(request.POST, instance=settings)
import_form = ImportSettingsForm(instance=settings) # Unbound form for display
if server_form.is_valid():
server_form.save()
messages.success(
request,
f"LibreNMS server settings updated successfully. Active server: {server_form.cleaned_data['selected_server']}",
)
return redirect("plugins:netbox_librenms_plugin:settings")
elif form_type == "import_settings":
# Process import settings form
server_form = ServerConfigForm(instance=settings) # Unbound form for display
import_form = ImportSettingsForm(request.POST, instance=settings)
if import_form.is_valid():
import_form.save()
# Also update current user's preferences to match new defaults
try:
save_user_pref(
request,
"plugins.netbox_librenms_plugin.use_sysname",
import_form.cleaned_data.get("use_sysname_default", False),
)
save_user_pref(
request,
"plugins.netbox_librenms_plugin.strip_domain",
import_form.cleaned_data.get("strip_domain_default", False),
)
except (TypeError, ValueError) as e:
logger.warning(
"Failed to update user preferences due to invalid value: %s (user: %s)",
e,
request.user,
)
except Exception as e:
logger.exception(
"Unexpected error while updating user preferences for user %s: %s",
request.user,
e,
)
messages.success(
request,
"Import settings updated successfully.",
)
return redirect("plugins:netbox_librenms_plugin:settings")
else:
# Unknown form_type - shouldn't happen, but handle gracefully
messages.error(request, "Invalid form submission.")
return redirect("plugins:netbox_librenms_plugin:settings")
# If we get here, validation failed - render both forms
return render(
request,
self.template_name,
{
"server_form": server_form,
"import_form": import_form,
"object": settings,
"active_tab": form_type, # Pass which tab should be active
},
)
class TestLibreNMSConnectionView(LibreNMSPermissionMixin, View):
"""
HTMX view to test LibreNMS server connection.
Returns HTML fragment instead of JSON for HTMX compatibility.
"""
def post(self, request):
"""Test connection to selected LibreNMS server."""
server_key = request.POST.get("selected_server")
if not server_key:
return HttpResponse(
'<div class="alert alert-warning">'
'<i class="ti ti-alert-circle me-2"></i>'
"<strong>No server selected.</strong> Please select a server first."
"</div>"
)
try:
# Initialize LibreNMS API client
api_client = LibreNMSAPI(server_key=server_key)
# Test the connection by calling the /system endpoint
system_info = api_client.test_connection()
if system_info and not system_info.get("error"):
version = escape(system_info.get("local_ver", "Unknown"))
database = escape(system_info.get("database_ver", "Unknown"))
php_version = escape(system_info.get("php_ver", "Unknown"))
return HttpResponse(
f'<div class="alert alert-success">'
f'<i class="ti ti-check me-2"></i>'
f"<strong>Connection successful!</strong><br>"
f"LibreNMS Version: {version}<br>"
f"Database: {database}<br>"
f"PHP Version: {php_version}"
f"</div>"
)
elif system_info and system_info.get("error"):
error_msg = escape(system_info.get("message", "Unknown error occurred"))
return HttpResponse(
f'<div class="alert alert-danger">'
f'<i class="ti ti-alert-circle me-2"></i>'
f"<strong>Connection failed:</strong><br>{error_msg}"
f"</div>"
)
else:
return HttpResponse(
'<div class="alert alert-danger">'
'<i class="ti ti-alert-circle me-2"></i>'
"<strong>Connection failed:</strong><br>"
"Failed to retrieve system information"
"</div>"
)
except ValueError as e:
return HttpResponse(
f'<div class="alert alert-danger">'
f'<i class="ti ti-alert-circle me-2"></i>'
f"<strong>Configuration error:</strong><br>{escape(str(e))}"
f"</div>"
)
except Exception as e:
return HttpResponse(
f'<div class="alert alert-danger">'
f'<i class="ti ti-alert-circle me-2"></i>'
f"<strong>Connection failed:</strong><br>{escape(str(e))}"
f"</div>"
)