diff --git a/netbox/utilities/forms.py b/netbox/utilities/forms.py index 59e581ff4..0d15d34df 100644 --- a/netbox/utilities/forms.py +++ b/netbox/utilities/forms.py @@ -15,6 +15,7 @@ from django.forms import BoundField from django.forms.models import fields_for_model from django.urls import reverse +from utilities.querysets import RestrictedQuerySet from .choices import ColorChoices, unpack_grouped_choices from .validators import EnhancedURLValidator @@ -138,6 +139,16 @@ def form_from_model(model, fields): return type('FormFromModel', (forms.Form,), form_fields) +def restrict_form_fields(form, user, action='view'): + """ + Restrict all form fields which reference a RestrictedQuerySet. This ensures that users see only permitted objects + as available choices. + """ + for field in form.fields.values(): + if hasattr(field, 'queryset') and issubclass(field.queryset.__class__, RestrictedQuerySet): + field.queryset = field.queryset.restrict(user, action) + + # # Widgets # diff --git a/netbox/utilities/views.py b/netbox/utilities/views.py index 5785da93f..7fd41804b 100644 --- a/netbox/utilities/views.py +++ b/netbox/utilities/views.py @@ -28,7 +28,7 @@ from django_tables2 import RequestConfig from extras.models import CustomField, CustomFieldValue, ExportTemplate from extras.querysets import CustomFieldQueryset from utilities.exceptions import AbortTransaction -from utilities.forms import BootstrapMixin, BulkRenameForm, CSVDataField, TableConfigForm +from utilities.forms import BootstrapMixin, BulkRenameForm, CSVDataField, TableConfigForm, restrict_form_fields from utilities.permissions import get_permission_for_model, resolve_permission from utilities.utils import csv_format, prepare_cloned_fields from .error_handlers import handle_protectederror @@ -352,6 +352,7 @@ class ObjectEditView(GetReturnURLMixin, ObjectPermissionRequiredMixin, View): # Parse initial data manually to avoid setting field values as lists initial_data = {k: request.GET[k] for k in request.GET} form = self.model_form(instance=obj, initial=initial_data) + restrict_form_fields(form, request.user) return render(request, self.template_name, { 'obj': obj, @@ -368,6 +369,7 @@ class ObjectEditView(GetReturnURLMixin, ObjectPermissionRequiredMixin, View): files=request.FILES, instance=obj ) + restrict_form_fields(form, request.user) if form.is_valid(): logger.debug("Form validation was successful")