From 70c2b358ad6c778344b2ee0639dab6b76f751fdc Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Tue, 20 Jun 2023 14:27:18 -0400 Subject: [PATCH 01/18] PRVB --- docs/release-notes/version-3.5.md | 4 ++++ netbox/netbox/settings.py | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/docs/release-notes/version-3.5.md b/docs/release-notes/version-3.5.md index 49d2e6347..7ad333e47 100644 --- a/docs/release-notes/version-3.5.md +++ b/docs/release-notes/version-3.5.md @@ -1,5 +1,9 @@ # NetBox v3.5 +## v3.5.5 (FUTURE) + +--- + ## v3.5.4 (2023-06-20) ### Enhancements diff --git a/netbox/netbox/settings.py b/netbox/netbox/settings.py index 22193dbac..31363144f 100644 --- a/netbox/netbox/settings.py +++ b/netbox/netbox/settings.py @@ -25,7 +25,7 @@ from netbox.constants import RQ_QUEUE_DEFAULT, RQ_QUEUE_HIGH, RQ_QUEUE_LOW # Environment setup # -VERSION = '3.5.4' +VERSION = '3.5.5-dev' # Hostname HOSTNAME = platform.node() From 13315f36d45a9181183561eb3b135444236c697f Mon Sep 17 00:00:00 2001 From: Abhimanyu Saharan Date: Fri, 23 Jun 2023 23:29:28 +0530 Subject: [PATCH 02/18] fixes device type and module type tag import #12949 --- netbox/dcim/forms/bulk_import.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/netbox/dcim/forms/bulk_import.py b/netbox/dcim/forms/bulk_import.py index de7575acb..8c8c4f79a 100644 --- a/netbox/dcim/forms/bulk_import.py +++ b/netbox/dcim/forms/bulk_import.py @@ -306,7 +306,7 @@ class DeviceTypeImportForm(NetBoxModelImportForm): model = DeviceType fields = [ 'manufacturer', 'default_platform', 'model', 'slug', 'part_number', 'u_height', 'is_full_depth', - 'subdevice_role', 'airflow', 'description', 'weight', 'weight_unit', 'comments', + 'subdevice_role', 'airflow', 'description', 'weight', 'weight_unit', 'comments', 'tags', ] @@ -327,7 +327,7 @@ class ModuleTypeImportForm(NetBoxModelImportForm): class Meta: model = ModuleType - fields = ['manufacturer', 'model', 'part_number', 'description', 'weight', 'weight_unit', 'comments'] + fields = ['manufacturer', 'model', 'part_number', 'description', 'weight', 'weight_unit', 'comments', 'tags'] class DeviceRoleImportForm(NetBoxModelImportForm): From 7f96c7fee7e713b43a9cc611b60ea6ca579e243e Mon Sep 17 00:00:00 2001 From: Abhimanyu Saharan Date: Fri, 23 Jun 2023 22:23:20 +0530 Subject: [PATCH 03/18] fixes most schema warnings #12257 --- netbox/ipam/filtersets.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/netbox/ipam/filtersets.py b/netbox/ipam/filtersets.py index a128b6acc..d011472d9 100644 --- a/netbox/ipam/filtersets.py +++ b/netbox/ipam/filtersets.py @@ -4,6 +4,8 @@ from django.contrib.contenttypes.models import ContentType from django.core.exceptions import ValidationError from django.db.models import Q from django.utils.translation import gettext as _ +from drf_spectacular.utils import extend_schema_field +from drf_spectacular.types import OpenApiTypes from netaddr.core import AddrFormatError from dcim.models import Device, Interface, Region, Site, SiteGroup @@ -414,6 +416,7 @@ class PrefixFilterSet(NetBoxModelFilterSet, TenancyFilterSet): except (AddrFormatError, ValueError): return queryset.none() + @extend_schema_field(OpenApiTypes.STR) def filter_present_in_vrf(self, queryset, name, vrf): if vrf is None: return queryset.none @@ -659,6 +662,7 @@ class IPAddressFilterSet(NetBoxModelFilterSet, TenancyFilterSet): return queryset return queryset.filter(address__net_mask_length=value) + @extend_schema_field(OpenApiTypes.STR) def filter_present_in_vrf(self, queryset, name, vrf): if vrf is None: return queryset.none @@ -727,6 +731,7 @@ class FHRPGroupFilterSet(NetBoxModelFilterSet): Q(name__icontains=value) ) + @extend_schema_field(OpenApiTypes.STR) def filter_related_ip(self, queryset, name, value): """ Filter by VRF & prefix of assigned IP addresses. @@ -941,9 +946,11 @@ class VLANFilterSet(NetBoxModelFilterSet, TenancyFilterSet): pass return queryset.filter(qs_filter) + @extend_schema_field(OpenApiTypes.STR) def get_for_device(self, queryset, name, value): return queryset.get_for_device(value) + @extend_schema_field(OpenApiTypes.STR) def get_for_virtualmachine(self, queryset, name, value): return queryset.get_for_virtualmachine(value) From 49af70a77d425ddd5caf11ffd3cf786df2d05400 Mon Sep 17 00:00:00 2001 From: Abhimanyu Saharan Date: Fri, 23 Jun 2023 21:31:30 +0530 Subject: [PATCH 04/18] fixes choice field schema for response #12960 --- netbox/core/api/schema.py | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/netbox/core/api/schema.py b/netbox/core/api/schema.py index 9550df3ea..b7e537c23 100644 --- a/netbox/core/api/schema.py +++ b/netbox/core/api/schema.py @@ -1,5 +1,6 @@ import re import typing +from collections import OrderedDict from drf_spectacular.extensions import OpenApiSerializerFieldExtension from drf_spectacular.openapi import AutoSchema @@ -28,14 +29,19 @@ class ChoiceFieldFix(OpenApiSerializerFieldExtension): target_class = 'netbox.api.fields.ChoiceField' def map_serializer_field(self, auto_schema, direction): + build_cf = build_choice_field(self.target) + if direction == 'request': - return build_choice_field(self.target) + return build_cf elif direction == "response": + value = build_cf + label = {**build_basic_type(OpenApiTypes.STR), "enum": list(OrderedDict.fromkeys(self.target.choices.values()))} + return build_object_type( properties={ - "value": build_basic_type(OpenApiTypes.STR), - "label": build_basic_type(OpenApiTypes.STR), + "value": value, + "label": label } ) From 79c8219202e971d29ccda6450c3c0ddd4a560e1c Mon Sep 17 00:00:00 2001 From: Abhimanyu Saharan Date: Fri, 23 Jun 2023 20:39:57 +0530 Subject: [PATCH 05/18] fixes device interface serializer #12533 --- netbox/dcim/api/serializers.py | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/netbox/dcim/api/serializers.py b/netbox/dcim/api/serializers.py index 3f6d55da7..c4aa838ea 100644 --- a/netbox/dcim/api/serializers.py +++ b/netbox/dcim/api/serializers.py @@ -880,12 +880,12 @@ class InterfaceSerializer(NetBoxModelSerializer, CabledObjectSerializer, Connect parent = NestedInterfaceSerializer(required=False, allow_null=True) bridge = NestedInterfaceSerializer(required=False, allow_null=True) lag = NestedInterfaceSerializer(required=False, allow_null=True) - mode = ChoiceField(choices=InterfaceModeChoices, required=False, allow_blank=True, allow_null=True) + mode = ChoiceField(choices=InterfaceModeChoices, required=False, allow_blank=True) duplex = ChoiceField(choices=InterfaceDuplexChoices, required=False, allow_blank=True, allow_null=True) - rf_role = ChoiceField(choices=WirelessRoleChoices, required=False, allow_blank=True, allow_null=True) - rf_channel = ChoiceField(choices=WirelessChannelChoices, required=False, allow_blank=True, allow_null=True) - poe_mode = ChoiceField(choices=InterfacePoEModeChoices, required=False, allow_blank=True, allow_null=True) - poe_type = ChoiceField(choices=InterfacePoETypeChoices, required=False, allow_blank=True, allow_null=True) + rf_role = ChoiceField(choices=WirelessRoleChoices, required=False, allow_blank=True) + rf_channel = ChoiceField(choices=WirelessChannelChoices, required=False, allow_blank=True) + poe_mode = ChoiceField(choices=InterfacePoEModeChoices, required=False, allow_blank=True) + poe_type = ChoiceField(choices=InterfacePoETypeChoices, required=False, allow_blank=True) untagged_vlan = NestedVLANSerializer(required=False, allow_null=True) tagged_vlans = SerializedPKRelatedField( queryset=VLAN.objects.all(), @@ -907,9 +907,10 @@ class InterfaceSerializer(NetBoxModelSerializer, CabledObjectSerializer, Connect mac_address = serializers.CharField( required=False, default=None, + allow_blank=True, allow_null=True ) - wwn = serializers.CharField(required=False, default=None) + wwn = serializers.CharField(required=False, default=None, allow_blank=True, allow_null=True) class Meta: model = Interface From c83b2499f014fe0cb317941939c5b5532778ec93 Mon Sep 17 00:00:00 2001 From: Abhimanyu Saharan Date: Fri, 23 Jun 2023 18:11:32 +0530 Subject: [PATCH 06/18] fix db maintenance mode exception #12966 --- netbox/netbox/middleware.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/netbox/netbox/middleware.py b/netbox/netbox/middleware.py index 76b3e42a8..ba6967f1f 100644 --- a/netbox/netbox/middleware.py +++ b/netbox/netbox/middleware.py @@ -203,7 +203,7 @@ class MaintenanceModeMiddleware: """ Prevent any write-related database operations if an exception is raised. """ - if isinstance(exception, InternalError): + if get_config().MAINTENANCE_MODE and isinstance(exception, InternalError): error_message = 'NetBox is currently operating in maintenance mode and is unable to perform write ' \ 'operations. Please try again later.' From 27e850a68db676b96cd7f54ab9b376dc42f636c7 Mon Sep 17 00:00:00 2001 From: Abhimanyu Saharan Date: Fri, 23 Jun 2023 18:08:20 +0530 Subject: [PATCH 07/18] fix ip address assignment #12953 --- netbox/ipam/forms/model_forms.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/netbox/ipam/forms/model_forms.py b/netbox/ipam/forms/model_forms.py index b0b08e4e0..6fa0f95ea 100644 --- a/netbox/ipam/forms/model_forms.py +++ b/netbox/ipam/forms/model_forms.py @@ -345,7 +345,7 @@ class IPAddressForm(TenancyForm, NetBoxModelForm): }) elif selected_objects: assigned_object = self.cleaned_data[selected_objects[0]] - if self.cleaned_data['primary_for_parent'] and assigned_object != self.instance.assigned_object: + if self.instance.pk and self.cleaned_data['primary_for_parent'] and assigned_object != self.instance.assigned_object: raise ValidationError( "Cannot reassign IP address while it is designated as the primary IP for the parent object" ) From 882f29192cfebb206b444e957423f738609737cb Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Fri, 23 Jun 2023 15:23:40 -0400 Subject: [PATCH 08/18] Fixes #12975: Correct URL for VirtualDeviceContext API serializer --- netbox/dcim/api/serializers.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/netbox/dcim/api/serializers.py b/netbox/dcim/api/serializers.py index c4aa838ea..2f854d3e4 100644 --- a/netbox/dcim/api/serializers.py +++ b/netbox/dcim/api/serializers.py @@ -707,7 +707,7 @@ class DeviceWithConfigContextSerializer(DeviceSerializer): class VirtualDeviceContextSerializer(NetBoxModelSerializer): - url = serializers.HyperlinkedIdentityField(view_name='dcim-api:device-detail') + url = serializers.HyperlinkedIdentityField(view_name='dcim-api:virtualdevicecontext-detail') device = NestedDeviceSerializer() tenant = NestedTenantSerializer(required=False, allow_null=True, default=None) primary_ip = NestedIPAddressSerializer(read_only=True, allow_null=True) From 32fe9fe8ecae89807e32034dbdf300a7edf05a90 Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Fri, 23 Jun 2023 15:26:48 -0400 Subject: [PATCH 09/18] Changelog for #12533, #12960, #12963, #12966, #12975, #12989 --- docs/release-notes/version-3.5.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/docs/release-notes/version-3.5.md b/docs/release-notes/version-3.5.md index 7ad333e47..3d4c7381c 100644 --- a/docs/release-notes/version-3.5.md +++ b/docs/release-notes/version-3.5.md @@ -2,6 +2,15 @@ ## v3.5.5 (FUTURE) +### Bug Fixes + +* [#12533](https://github.com/netbox-community/netbox/issues/12533) - Fix REST API validation of null values for several interface attributes +* [#12960](https://github.com/netbox-community/netbox/issues/12960) - Fix OpenAPI schema for various choice fields +* [#12963](https://github.com/netbox-community/netbox/issues/12963) - Fix designation of primary IP addresses during interface assignment +* [#12966](https://github.com/netbox-community/netbox/issues/12966) - Avoid catching database exceptions when maintenance mode is disabled +* [#12975](https://github.com/netbox-community/netbox/issues/12975) - Correct URL for VirtualDeviceContext API serializer +* [#12989](https://github.com/netbox-community/netbox/issues/12989) - Fix bulk import of tags for devie & module types + --- ## v3.5.4 (2023-06-20) From d131d9b3102bb0966bc073d7c1e335130d103a36 Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Fri, 23 Jun 2023 15:31:18 -0400 Subject: [PATCH 10/18] Correct changelog for #12953 --- docs/release-notes/version-3.5.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/release-notes/version-3.5.md b/docs/release-notes/version-3.5.md index 3d4c7381c..96623f66f 100644 --- a/docs/release-notes/version-3.5.md +++ b/docs/release-notes/version-3.5.md @@ -5,11 +5,11 @@ ### Bug Fixes * [#12533](https://github.com/netbox-community/netbox/issues/12533) - Fix REST API validation of null values for several interface attributes +* [#12953](https://github.com/netbox-community/netbox/issues/12953) - Fix designation of primary IP addresses during interface assignment * [#12960](https://github.com/netbox-community/netbox/issues/12960) - Fix OpenAPI schema for various choice fields -* [#12963](https://github.com/netbox-community/netbox/issues/12963) - Fix designation of primary IP addresses during interface assignment * [#12966](https://github.com/netbox-community/netbox/issues/12966) - Avoid catching database exceptions when maintenance mode is disabled * [#12975](https://github.com/netbox-community/netbox/issues/12975) - Correct URL for VirtualDeviceContext API serializer -* [#12989](https://github.com/netbox-community/netbox/issues/12989) - Fix bulk import of tags for devie & module types +* [#12989](https://github.com/netbox-community/netbox/issues/12989) - Fix bulk import of tags for device & module types --- From 74d9fe1ea27829f53ccc6e3b539bd36efd99d9bf Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Fri, 23 Jun 2023 15:54:40 -0400 Subject: [PATCH 11/18] Fixes #12961: Set correct return_url for object contacts tabs --- netbox/templates/tenancy/object_contacts.html | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/netbox/templates/tenancy/object_contacts.html b/netbox/templates/tenancy/object_contacts.html index bbe2d9bc1..e13fedc43 100644 --- a/netbox/templates/tenancy/object_contacts.html +++ b/netbox/templates/tenancy/object_contacts.html @@ -2,10 +2,12 @@ {% load helpers %} {% block extra_controls %} - {% if perms.tenancy.add_contactassignment %} - + {% if perms.tenancy.add_contactassignment %} + {% with viewname=object|viewname:"contacts" %} + Add a contact - + + {% endwith %} {% endif %} {% endblock %} From 290ffd408a1120263b062988154f406cba46ac26 Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Mon, 26 Jun 2023 14:21:26 -0400 Subject: [PATCH 12/18] Fixes #12977: Fix URL parameters for object count dashboard widgets (#12991) * Fixes #12977: Introduce dict_to_querydict() to ensure proper handling of QueryDicts * Remove unused import --- netbox/extras/dashboard/widgets.py | 6 ++---- netbox/extras/models/models.py | 7 +++---- netbox/utilities/templatetags/builtins/tags.py | 5 +++-- netbox/utilities/utils.py | 16 +++++++++++++++- 4 files changed, 23 insertions(+), 11 deletions(-) diff --git a/netbox/extras/dashboard/widgets.py b/netbox/extras/dashboard/widgets.py index b3a4d090c..31e7cb2d3 100644 --- a/netbox/extras/dashboard/widgets.py +++ b/netbox/extras/dashboard/widgets.py @@ -10,7 +10,6 @@ from django.conf import settings from django.contrib.contenttypes.models import ContentType from django.core.cache import cache from django.db.models import Q -from django.http import QueryDict from django.template.loader import render_to_string from django.urls import NoReverseMatch, resolve, reverse from django.utils.translation import gettext as _ @@ -19,7 +18,7 @@ from extras.utils import FeatureQuery from utilities.forms import BootstrapMixin from utilities.permissions import get_permission_for_model from utilities.templatetags.builtins.filters import render_markdown -from utilities.utils import content_type_identifier, content_type_name, get_viewname +from utilities.utils import content_type_identifier, content_type_name, dict_to_querydict, get_viewname from .utils import register_widget __all__ = ( @@ -170,8 +169,7 @@ class ObjectCountsWidget(DashboardWidget): qs = model.objects.restrict(request.user, 'view') # Apply any specified filters if filters := self.config.get('filters'): - params = QueryDict(mutable=True) - params.update(filters) + params = dict_to_querydict(filters) filterset = getattr(resolve(url).func.view_class, 'filterset', None) qs = filterset(params, qs).qs url = f'{url}?{params.urlencode()}' diff --git a/netbox/extras/models/models.py b/netbox/extras/models/models.py index b7034645f..4b4b6fbfd 100644 --- a/netbox/extras/models/models.py +++ b/netbox/extras/models/models.py @@ -9,7 +9,7 @@ from django.contrib.contenttypes.models import ContentType from django.core.cache import cache from django.core.validators import ValidationError from django.db import models -from django.http import HttpResponse, QueryDict +from django.http import HttpResponse from django.urls import reverse from django.utils import timezone from django.utils.formats import date_format @@ -26,7 +26,7 @@ from netbox.models.features import ( CloningMixin, CustomFieldsMixin, CustomLinksMixin, ExportTemplatesMixin, SyncedDataMixin, TagsMixin, ) from utilities.querysets import RestrictedQuerySet -from utilities.utils import clean_html, render_jinja2 +from utilities.utils import clean_html, dict_to_querydict, render_jinja2 __all__ = ( 'ConfigRevision', @@ -462,8 +462,7 @@ class SavedFilter(CloningMixin, ExportTemplatesMixin, ChangeLoggedModel): @property def url_params(self): - qd = QueryDict(mutable=True) - qd.update(self.parameters) + qd = dict_to_querydict(self.parameters) return qd.urlencode() diff --git a/netbox/utilities/templatetags/builtins/tags.py b/netbox/utilities/templatetags/builtins/tags.py index dc86586e7..f9fe5f4e3 100644 --- a/netbox/utilities/templatetags/builtins/tags.py +++ b/netbox/utilities/templatetags/builtins/tags.py @@ -1,6 +1,8 @@ from django import template from django.http import QueryDict +from utilities.utils import dict_to_querydict + __all__ = ( 'badge', 'checkmark', @@ -87,8 +89,7 @@ def htmx_table(context, viewname, return_url=None, **kwargs): viewname: The name of the view to use for the HTMX request (e.g. `dcim:site_list`) return_url: The URL to pass as the `return_url`. If not provided, the current request's path will be used. """ - url_params = QueryDict(mutable=True) - url_params.update(kwargs) + url_params = dict_to_querydict(kwargs) url_params['return_url'] = return_url or context['request'].path return { 'viewname': viewname, diff --git a/netbox/utilities/utils.py b/netbox/utilities/utils.py index 4b4a2631a..114397dae 100644 --- a/netbox/utilities/utils.py +++ b/netbox/utilities/utils.py @@ -11,8 +11,9 @@ from django.core import serializers from django.db.models import Count, OuterRef, Subquery from django.db.models.functions import Coalesce from django.http import QueryDict -from django.utils.html import escape from django.utils import timezone +from django.utils.datastructures import MultiValueDict +from django.utils.html import escape from django.utils.timezone import localtime from jinja2.sandbox import SandboxedEnvironment from mptt.models import MPTTModel @@ -231,6 +232,19 @@ def dict_to_filter_params(d, prefix=''): return params +def dict_to_querydict(d, mutable=True): + """ + Create a QueryDict instance from a regular Python dictionary. + """ + qd = QueryDict(mutable=True) + for k, v in d.items(): + item = MultiValueDict({k: v}) if isinstance(v, (list, tuple, set)) else {k: v} + qd.update(item) + if not mutable: + qd._mutable = False + return qd + + def normalize_querydict(querydict): """ Convert a QueryDict to a normal, mutable dictionary, preserving list values. For example, From f1858a7c2304aa3a40ffab436b58799e62ec6656 Mon Sep 17 00:00:00 2001 From: Alexander Votteler Date: Tue, 27 Jun 2023 07:57:59 +0200 Subject: [PATCH 13/18] Fixes #13011: Allow comma in custom links --- netbox/extras/models/models.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/netbox/extras/models/models.py b/netbox/extras/models/models.py index 4b4b6fbfd..fcf5c26a2 100644 --- a/netbox/extras/models/models.py +++ b/netbox/extras/models/models.py @@ -285,7 +285,7 @@ class CustomLink(CloningMixin, ExportTemplatesMixin, ChangeLoggedModel): text = clean_html(text, allowed_schemes) # Sanitize link - link = urllib.parse.quote(link, safe='/:?&=%+[]@#') + link = urllib.parse.quote(link, safe='/:?&=%+[]@#,') # Verify link scheme is allowed result = urllib.parse.urlparse(link) From 16d5107b719d146bcd1060c9f9ece010d828ddde Mon Sep 17 00:00:00 2001 From: pobradovic08 Date: Tue, 27 Jun 2023 01:38:33 +0200 Subject: [PATCH 14/18] Add QSFP-DD (100GE) interface type --- netbox/dcim/choices.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/netbox/dcim/choices.py b/netbox/dcim/choices.py index cc388b750..f2f401718 100644 --- a/netbox/dcim/choices.py +++ b/netbox/dcim/choices.py @@ -810,6 +810,7 @@ class InterfaceTypeChoices(ChoiceSet): TYPE_100GE_CXP = '100gbase-x-cxp' TYPE_100GE_CPAK = '100gbase-x-cpak' TYPE_100GE_QSFP28 = '100gbase-x-qsfp28' + TYPE_100GE_QSFP_DD = '100gbase-x-qsfpdd' TYPE_200GE_CFP2 = '200gbase-x-cfp2' TYPE_200GE_QSFP56 = '200gbase-x-qsfp56' TYPE_200GE_QSFP_DD = '200gbase-x-qsfpdd' @@ -959,6 +960,7 @@ class InterfaceTypeChoices(ChoiceSet): (TYPE_100GE_CXP, 'CXP (100GE)'), (TYPE_100GE_CPAK, 'Cisco CPAK (100GE)'), (TYPE_100GE_QSFP28, 'QSFP28 (100GE)'), + (TYPE_100GE_QSFP_DD, 'QSFP-DD (100GE)'), (TYPE_200GE_QSFP56, 'QSFP56 (200GE)'), (TYPE_200GE_QSFP_DD, 'QSFP-DD (200GE)'), (TYPE_400GE_QSFP_DD, 'QSFP-DD (400GE)'), From c99e5654268773d920d4ef58b3ad5782aed2bc58 Mon Sep 17 00:00:00 2001 From: rmanyari Date: Mon, 26 Jun 2023 14:39:38 -0400 Subject: [PATCH 15/18] fix remote auth backend check --- netbox/netbox/api/authentication.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/netbox/netbox/api/authentication.py b/netbox/netbox/api/authentication.py index 814ca1ed6..f0bd5fd27 100644 --- a/netbox/netbox/api/authentication.py +++ b/netbox/netbox/api/authentication.py @@ -60,7 +60,7 @@ class TokenAuthentication(authentication.TokenAuthentication): user = token.user # When LDAP authentication is active try to load user data from LDAP directory - if settings.REMOTE_AUTH_BACKEND == 'netbox.authentication.LDAPBackend': + if 'netbox.authentication.LDAPBackend' in settings.REMOTE_AUTH_BACKEND: from netbox.authentication import LDAPBackend ldap_backend = LDAPBackend() From 34d32374a8dcd176abba5e13d1d1db80887251ed Mon Sep 17 00:00:00 2001 From: Harm Geerts Date: Mon, 26 Jun 2023 14:07:29 +0200 Subject: [PATCH 16/18] Fix #12983 bulk edit of M2M fields when nothing is selected Partially revert 41c92483a0b9b820dd0ca0c43c6c6d6e560043ed to restore bulk edit with m2m fields. The m2m cleaned_data yields a empty queryset when nothing is selected. By setting the m2m relation unless set null is checked even when nothing is selected the m2m relation is always cleared. This commit only sets the m2m relation when a selection is made. --- netbox/netbox/views/generic/bulk_views.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/netbox/netbox/views/generic/bulk_views.py b/netbox/netbox/views/generic/bulk_views.py index e66e79a7a..35caa31b3 100644 --- a/netbox/netbox/views/generic/bulk_views.py +++ b/netbox/netbox/views/generic/bulk_views.py @@ -551,7 +551,7 @@ class BulkEditView(GetReturnURLMixin, BaseMultiObjectView): for name, m2m_field in m2m_fields.items(): if name in form.nullable_fields and name in nullified_fields: getattr(obj, name).clear() - else: + elif form.cleaned_data[name]: getattr(obj, name).set(form.cleaned_data[name]) # Add/remove tags From 6b01b1df408fecc71e4dd1ffd499ddbea28a6dc6 Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Tue, 27 Jun 2023 08:39:51 -0400 Subject: [PATCH 17/18] Changelog for #12849, #12945, #12961, #12977, #12983, #13011 --- docs/release-notes/version-3.5.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/docs/release-notes/version-3.5.md b/docs/release-notes/version-3.5.md index 96623f66f..7b82ed07c 100644 --- a/docs/release-notes/version-3.5.md +++ b/docs/release-notes/version-3.5.md @@ -2,14 +2,23 @@ ## v3.5.5 (FUTURE) +### Enhancements + +* [#12945](https://github.com/netbox-community/netbox/issues/12945) - Add 100GE QSFP-DD interface type + ### Bug Fixes * [#12533](https://github.com/netbox-community/netbox/issues/12533) - Fix REST API validation of null values for several interface attributes +* [#12849](https://github.com/netbox-community/netbox/issues/12849) - Fix LDAP group permissions assignment for API clients * [#12953](https://github.com/netbox-community/netbox/issues/12953) - Fix designation of primary IP addresses during interface assignment * [#12960](https://github.com/netbox-community/netbox/issues/12960) - Fix OpenAPI schema for various choice fields +* [#12961](https://github.com/netbox-community/netbox/issues/12961) - Set correct return URL for object contacts tabs * [#12966](https://github.com/netbox-community/netbox/issues/12966) - Avoid catching database exceptions when maintenance mode is disabled * [#12975](https://github.com/netbox-community/netbox/issues/12975) - Correct URL for VirtualDeviceContext API serializer +* [#12977](https://github.com/netbox-community/netbox/issues/12977) - Fix URL parameters for object count dashboard widgets +* [#12983](https://github.com/netbox-community/netbox/issues/12983) - Avoid erroneously clearing many-to-many assignments during bulk edit * [#12989](https://github.com/netbox-community/netbox/issues/12989) - Fix bulk import of tags for device & module types +* [#13011](https://github.com/netbox-community/netbox/issues/13011) - Do not escape commas when rendering custom links --- From b13f9d27d954419389715ddfab594e97de3c6121 Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Tue, 27 Jun 2023 10:19:12 -0400 Subject: [PATCH 18/18] Fix Repography charts --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 6e2b34fb8..b7dfc9e43 100644 --- a/README.md +++ b/README.md @@ -52,10 +52,10 @@ as the cornerstone for network automation in thousands of organizations. ## Project Stats
- Timeline graph - Issues graph - Pull requests graph - Top contributors + Timeline graph + Issues graph + Pull requests graph + Top contributors
Stats via Repography