From ef460a38edd2c02d2fd887eb00f8599345550ea2 Mon Sep 17 00:00:00 2001 From: Arthur Date: Tue, 3 Oct 2023 10:22:17 -0700 Subject: [PATCH 01/18] 13944 fix report detail api --- netbox/extras/reports.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/netbox/extras/reports.py b/netbox/extras/reports.py index 9b12065ca..cc279a49a 100644 --- a/netbox/extras/reports.py +++ b/netbox/extras/reports.py @@ -23,7 +23,7 @@ logger = logging.getLogger(__name__) def get_module_and_report(module_name, report_name): module = ReportModule.objects.get(file_path=f'{module_name}.py') - report = module.reports.get(report_name) + report = module.reports.get(report_name)() return module, report From 5cb1a6b79050afc0ec8fbd5b05d19aa0851d12fb Mon Sep 17 00:00:00 2001 From: Arthur Date: Mon, 2 Oct 2023 12:07:28 -0700 Subject: [PATCH 02/18] 13872 fix bulk import --- netbox/templates/generic/bulk_import.html | 2 ++ 1 file changed, 2 insertions(+) diff --git a/netbox/templates/generic/bulk_import.html b/netbox/templates/generic/bulk_import.html index b9cb0d4cb..f78cb0bf5 100644 --- a/netbox/templates/generic/bulk_import.html +++ b/netbox/templates/generic/bulk_import.html @@ -67,6 +67,7 @@ Context: {% render_field form.upload_file %} {% render_field form.format %} + {% render_field form.csv_delimiter %}
@@ -88,6 +89,7 @@ Context: {% render_field form.data_source %} {% render_field form.data_file %} {% render_field form.format %} + {% render_field form.csv_delimiter %}
From 6dc560596d54274a0450fc771ecf544c1cb6b518 Mon Sep 17 00:00:00 2001 From: yash-pal1 Date: Wed, 27 Sep 2023 15:45:46 +0530 Subject: [PATCH 03/18] added device button under platform view pre-populated role field instead of platform field --- netbox/templates/dcim/platform.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/netbox/templates/dcim/platform.html b/netbox/templates/dcim/platform.html index 29f405b6e..9448ad3e5 100644 --- a/netbox/templates/dcim/platform.html +++ b/netbox/templates/dcim/platform.html @@ -13,7 +13,7 @@ {% block extra_controls %} {% if perms.dcim.add_device %} - + {% trans "Add Device" %} {% endif %} From 6093debb7192c76c5a395eb21c278168aefe88c9 Mon Sep 17 00:00:00 2001 From: Arthur Hanson Date: Tue, 3 Oct 2023 12:41:40 -0700 Subject: [PATCH 04/18] 12328 update GFK object in clean (#13946) * 12328 update GFK object in clean * Add missing import statement --------- Co-authored-by: Jeremy Stretch --- netbox/netbox/models/__init__.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/netbox/netbox/models/__init__.py b/netbox/netbox/models/__init__.py index 596357ea4..9d7696696 100644 --- a/netbox/netbox/models/__init__.py +++ b/netbox/netbox/models/__init__.py @@ -1,5 +1,6 @@ from django.conf import settings from django.contrib.contenttypes.fields import GenericForeignKey +from django.core.exceptions import ObjectDoesNotExist from django.core.validators import ValidationError from django.db import models from django.utils.translation import gettext_lazy as _ @@ -85,11 +86,16 @@ class NetBoxModel(NetBoxFeatureSet, models.Model): if ct_value and fk_value: klass = getattr(self, field.ct_field).model_class() - if not klass.objects.filter(pk=fk_value).exists(): + try: + obj = klass.objects.get(pk=fk_value) + except ObjectDoesNotExist: raise ValidationError({ field.fk_field: f"Related object not found using the provided value: {fk_value}." }) + # update the GFK field value + setattr(self, field.name, obj) + # # NetBox internal base models From a46255ddda73e1e29c610d40aeb7054214014935 Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Tue, 3 Oct 2023 16:29:55 -0400 Subject: [PATCH 05/18] Fixes #13064: Ensure unchecked checkboxes do not revert to original values upon HTMX form refresh --- netbox/netbox/settings.py | 4 ++++ netbox/templates/django/forms/widgets/checkbox.html | 6 ++++++ 2 files changed, 10 insertions(+) create mode 100644 netbox/templates/django/forms/widgets/checkbox.html diff --git a/netbox/netbox/settings.py b/netbox/netbox/settings.py index 8be2800fb..975e86858 100644 --- a/netbox/netbox/settings.py +++ b/netbox/netbox/settings.py @@ -355,6 +355,7 @@ INSTALLED_APPS = [ 'django.contrib.messages', 'django.contrib.staticfiles', 'django.contrib.humanize', + 'django.forms', 'corsheaders', 'debug_toolbar', 'graphiql_debug_toolbar', @@ -430,6 +431,9 @@ TEMPLATES = [ }, ] +# This allows us to override Django's stock form widget templates +FORM_RENDERER = 'django.forms.renderers.TemplatesSetting' + # Set up authentication backends if type(REMOTE_AUTH_BACKEND) not in (list, tuple): REMOTE_AUTH_BACKEND = [REMOTE_AUTH_BACKEND] diff --git a/netbox/templates/django/forms/widgets/checkbox.html b/netbox/templates/django/forms/widgets/checkbox.html new file mode 100644 index 000000000..bbe201a29 --- /dev/null +++ b/netbox/templates/django/forms/widgets/checkbox.html @@ -0,0 +1,6 @@ +{% comment %} + Include a hidden field of the same name to ensure that unchecked checkboxes + are always included in the submitted form data. +{% endcomment %} + +{% include "django/forms/widgets/input.html" %} From b93b331d8614a40c8c4d9095b7e5f684122a8d28 Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Wed, 4 Oct 2023 14:09:29 -0400 Subject: [PATCH 06/18] Fixes #13966: Restore 'last login' column on users table --- docs/release-notes/version-3.6.md | 4 ++++ netbox/users/tables.py | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/docs/release-notes/version-3.6.md b/docs/release-notes/version-3.6.md index 0a7787e43..137825b89 100644 --- a/docs/release-notes/version-3.6.md +++ b/docs/release-notes/version-3.6.md @@ -2,6 +2,10 @@ ## v3.6.4 (FUTURE) +### Bug Fixes + +* [#13966](https://github.com/netbox-community/netbox/issues/13966) - Restore "last login" column on users table + --- ## v3.6.3 (2023-09-26) diff --git a/netbox/users/tables.py b/netbox/users/tables.py index 3b418715a..afb270568 100644 --- a/netbox/users/tables.py +++ b/netbox/users/tables.py @@ -52,7 +52,7 @@ class UserTable(NetBoxTable): model = NetBoxUser fields = ( 'pk', 'id', 'username', 'first_name', 'last_name', 'email', 'groups', 'is_active', 'is_staff', - 'is_superuser', + 'is_superuser', 'last_login', ) default_columns = ('pk', 'username', 'first_name', 'last_name', 'email', 'is_active') From e4a9cad75644d0489b9f87271d9f7baeac1e28ae Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Wed, 4 Oct 2023 14:11:28 -0400 Subject: [PATCH 07/18] Changelog for #12328, #13064, #13872, #13910, #13944 --- docs/release-notes/version-3.6.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/docs/release-notes/version-3.6.md b/docs/release-notes/version-3.6.md index 137825b89..69a8ee62e 100644 --- a/docs/release-notes/version-3.6.md +++ b/docs/release-notes/version-3.6.md @@ -4,6 +4,11 @@ ### Bug Fixes +* [#12328](https://github.com/netbox-community/netbox/issues/12328) - Ensure generic foreign key relationships are populated in REST API serializations of objects +* [#13064](https://github.com/netbox-community/netbox/issues/13064) - Fix resetting of checkbox fields triggered by HTMX form re-rendering +* [#13872](https://github.com/netbox-community/netbox/issues/13872) - Add CSV delimiter field to file upload tab under bulk object upload views +* [#13910](https://github.com/netbox-community/netbox/issues/13910) - Correct "add device" button link under platform view +* [#13944](https://github.com/netbox-community/netbox/issues/13944) - Correct serialization of several report attributes in the REST API * [#13966](https://github.com/netbox-community/netbox/issues/13966) - Restore "last login" column on users table --- From 4d13f4d25294e53bc7691b7f0399d5d10c6fc96c Mon Sep 17 00:00:00 2001 From: Arthur Date: Thu, 5 Oct 2023 08:37:26 -0700 Subject: [PATCH 08/18] 13850 add requests to requirements --- base_requirements.txt | 4 ++++ requirements.txt | 1 + 2 files changed, 5 insertions(+) diff --git a/base_requirements.txt b/base_requirements.txt index 4b75b1313..423a9754b 100644 --- a/base_requirements.txt +++ b/base_requirements.txt @@ -120,6 +120,10 @@ psycopg[binary,pool] # https://github.com/yaml/pyyaml/blob/master/CHANGES PyYAML +# Requests +# https://github.com/psf/requests/blob/main/HISTORY.md +requests + # Sentry SDK # https://github.com/getsentry/sentry-python/blob/master/CHANGELOG.md sentry-sdk diff --git a/requirements.txt b/requirements.txt index 8c676df81..b81042acd 100644 --- a/requirements.txt +++ b/requirements.txt @@ -27,6 +27,7 @@ netaddr==0.9.0 Pillow==10.0.1 psycopg[binary,pool]==3.1.11 PyYAML==6.0.1 +requests==2.28.1 sentry-sdk==1.31.0 social-auth-app-django==5.3.0 social-auth-core[openidconnect]==4.4.2 From 285187542d31fa4f722e564b7a8e0840e6687704 Mon Sep 17 00:00:00 2001 From: sleepinggenius2 Date: Wed, 4 Oct 2023 11:52:21 -0400 Subject: [PATCH 09/18] Adds selection custom field labels to UI --- netbox/extras/models/customfields.py | 5 +++++ netbox/netbox/tables/columns.py | 4 +++- netbox/utilities/templatetags/builtins/tags.py | 6 ++++++ 3 files changed, 14 insertions(+), 1 deletion(-) diff --git a/netbox/extras/models/customfields.py b/netbox/extras/models/customfields.py index e6f339e5a..2bed464bb 100644 --- a/netbox/extras/models/customfields.py +++ b/netbox/extras/models/customfields.py @@ -232,6 +232,11 @@ class CustomField(CloningMixin, ExportTemplatesMixin, ChangeLoggedModel): return self.choice_set.choices return [] + def get_choice_label(self, value): + if not hasattr(self, '_choice_map'): + self._choice_map = dict(self.choices) + return self._choice_map.get(value, value) + def populate_initial_data(self, content_types): """ Populate initial custom field data upon either a) the creation of a new CustomField, or diff --git a/netbox/netbox/tables/columns.py b/netbox/netbox/tables/columns.py index 9e348fb23..d2cd0a0d4 100644 --- a/netbox/netbox/tables/columns.py +++ b/netbox/netbox/tables/columns.py @@ -483,8 +483,10 @@ class CustomFieldColumn(tables.Column): return mark_safe('') if self.customfield.type == CustomFieldTypeChoices.TYPE_URL: return mark_safe(f'{escape(value)}') + if self.customfield.type == CustomFieldTypeChoices.TYPE_SELECT: + return self.customfield.get_choice_label(value) if self.customfield.type == CustomFieldTypeChoices.TYPE_MULTISELECT: - return ', '.join(v for v in value) + return ', '.join(self.customfield.get_choice_label(v) for v in value) if self.customfield.type == CustomFieldTypeChoices.TYPE_MULTIOBJECT: return mark_safe(', '.join( self._linkify_item(obj) for obj in self.customfield.deserialize(value) diff --git a/netbox/utilities/templatetags/builtins/tags.py b/netbox/utilities/templatetags/builtins/tags.py index 35aec1000..68541ae5a 100644 --- a/netbox/utilities/templatetags/builtins/tags.py +++ b/netbox/utilities/templatetags/builtins/tags.py @@ -1,6 +1,7 @@ from django import template from django.http import QueryDict +from extras.choices import CustomFieldTypeChoices from utilities.utils import dict_to_querydict __all__ = ( @@ -38,6 +39,11 @@ def customfield_value(customfield, value): customfield: A CustomField instance value: The custom field value applied to an object """ + if value: + if customfield.type == CustomFieldTypeChoices.TYPE_SELECT: + value = customfield.get_choice_label(value) + elif customfield.type == CustomFieldTypeChoices.TYPE_MULTISELECT: + value = [customfield.get_choice_label(v) for v in value] return { 'customfield': customfield, 'value': value, From bbb133019d708abd93efe790e338bb07e2155f4e Mon Sep 17 00:00:00 2001 From: Arthur Hanson Date: Thu, 5 Oct 2023 12:15:50 -0700 Subject: [PATCH 10/18] 13815 document view permissions for scripts (#13943) * 13815 document view permissions for scripts * Replicate permissions note for reports * Remove duplicated text --------- Co-authored-by: Jeremy Stretch --- docs/customization/custom-scripts.md | 2 +- docs/customization/reports.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/customization/custom-scripts.md b/docs/customization/custom-scripts.md index 3811474d2..0b1ed11df 100644 --- a/docs/customization/custom-scripts.md +++ b/docs/customization/custom-scripts.md @@ -288,7 +288,7 @@ An IPv4 or IPv6 network with a mask. Returns a `netaddr.IPNetwork` object. Two a ## Running Custom Scripts !!! note - To run a custom script, a user must be assigned the `extras.run_script` permission. This is achieved by assigning the user (or group) a permission on the Script object and specifying the `run` action in the admin UI as shown below. + To run a custom script, a user must be assigned via permissions for `Extras > Script`, `Extras > ScriptModule`, and `Core > ManagedFile` objects. They must also be assigned the `extras.run_script` permission. This is achieved by assigning the user (or group) a permission on the Script object and specifying the `run` action in the admin UI as shown below. ![Adding the run action to a permission](../media/admin_ui_run_permission.png) diff --git a/docs/customization/reports.md b/docs/customization/reports.md index 7e3681304..a821c5da7 100644 --- a/docs/customization/reports.md +++ b/docs/customization/reports.md @@ -132,7 +132,7 @@ Once you have created a report, it will appear in the reports list. Initially, r ## Running Reports !!! note - To run a report, a user must be assigned the `extras.run_report` permission. This is achieved by assigning the user (or group) a permission on the Report object and specifying the `run` action in the admin UI as shown below. + To run a report, a user must be assigned via permissions for `Extras > Report`, `Extras > ReportModule`, and `Core > ManagedFile` objects. They must also be assigned the `extras.run_report` permission. This is achieved by assigning the user (or group) a permission on the Report object and specifying the `run` action in the admin UI as shown below. ![Adding the run action to a permission](../media/admin_ui_run_permission.png) From d03859b27b9bbc264f138d93d17773726949a1ab Mon Sep 17 00:00:00 2001 From: Arthur Hanson Date: Thu, 5 Oct 2023 12:53:57 -0700 Subject: [PATCH 11/18] 13746 fix available ips API for posting custom-fields (#13889) --- netbox/ipam/api/views.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/netbox/ipam/api/views.py b/netbox/ipam/api/views.py index da6463e23..643e6a8e0 100644 --- a/netbox/ipam/api/views.py +++ b/netbox/ipam/api/views.py @@ -289,7 +289,7 @@ class AvailableObjectsView(ObjectValidationMixin, APIView): ) # Prepare object data for deserialization - requested_objects = self.prep_object_data(serializer.validated_data, available_objects, parent) + requested_objects = self.prep_object_data(requested_objects, available_objects, parent) # Initialize the serializer with a list or a single object depending on what was requested serializer_class = get_serializer_for_model(self.queryset.model) From a543bd469ad7dfee989f4edab6604134271095b2 Mon Sep 17 00:00:00 2001 From: Arthur Date: Thu, 5 Oct 2023 13:17:18 -0700 Subject: [PATCH 12/18] 11987 change cable bulk import to check if same cable --- netbox/dcim/forms/bulk_import.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/netbox/dcim/forms/bulk_import.py b/netbox/dcim/forms/bulk_import.py index 70aceaa49..e41e875e4 100644 --- a/netbox/dcim/forms/bulk_import.py +++ b/netbox/dcim/forms/bulk_import.py @@ -1192,7 +1192,7 @@ class CableImportForm(NetBoxModelImportForm): termination_object = model.objects.get(device__in=device.virtual_chassis.members.all(), name=name) else: termination_object = model.objects.get(device=device, name=name) - if termination_object.cable is not None: + if termination_object.cable is not None and termination_object.cable != self.instance: raise forms.ValidationError(f"Side {side.upper()}: {device} {termination_object} is already connected") except ObjectDoesNotExist: raise forms.ValidationError(f"{side.upper()} side termination not found: {device} {name}") From e23b246d46c348d7af8f67735f8e3414105219da Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Thu, 5 Oct 2023 16:55:15 -0400 Subject: [PATCH 13/18] Changelog for #11987, #13440, #13746, #13876, #13950 --- docs/release-notes/version-3.6.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/docs/release-notes/version-3.6.md b/docs/release-notes/version-3.6.md index 69a8ee62e..cb09ee463 100644 --- a/docs/release-notes/version-3.6.md +++ b/docs/release-notes/version-3.6.md @@ -2,11 +2,19 @@ ## v3.6.4 (FUTURE) +### Enhancements + +* [#13950](https://github.com/netbox-community/netbox/issues/13950) - Display custom choice field labels rather than values in UI + ### Bug Fixes +* [#11987](https://github.com/netbox-community/netbox/issues/11987) - Fix validation of bulk cable updates via bulk import form * [#12328](https://github.com/netbox-community/netbox/issues/12328) - Ensure generic foreign key relationships are populated in REST API serializations of objects * [#13064](https://github.com/netbox-community/netbox/issues/13064) - Fix resetting of checkbox fields triggered by HTMX form re-rendering +* [#13440](https://github.com/netbox-community/netbox/issues/13440) - Fix support for assigning a tenant when creating "next available" VLANs via the REST API +* [#13746](https://github.com/netbox-community/netbox/issues/13746) - Fix support for setting custom field values when creating "next available" IP addresses via the REST API * [#13872](https://github.com/netbox-community/netbox/issues/13872) - Add CSV delimiter field to file upload tab under bulk object upload views +* [#13876](https://github.com/netbox-community/netbox/issues/13876) - Fix support for assigning an interface when creating "next available" IP addresses via the REST API * [#13910](https://github.com/netbox-community/netbox/issues/13910) - Correct "add device" button link under platform view * [#13944](https://github.com/netbox-community/netbox/issues/13944) - Correct serialization of several report attributes in the REST API * [#13966](https://github.com/netbox-community/netbox/issues/13966) - Restore "last login" column on users table From 383285fb943bf3e511a04e11510c6a04ed966ff7 Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Fri, 6 Oct 2023 13:34:25 -0400 Subject: [PATCH 14/18] Closes #13997: Update runner versions (#13998) * Update runner versions * Update stale & lock runners --- .github/workflows/ci.yml | 8 ++++---- .github/workflows/lock.yml | 2 +- .github/workflows/stale.yml | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1d9692194..9d580baa4 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -31,15 +31,15 @@ jobs: steps: - name: Check out repo - uses: actions/checkout@v2 + uses: actions/checkout@v4 - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v2 + uses: actions/setup-python@v4 with: python-version: ${{ matrix.python-version }} - name: Use Node.js ${{ matrix.node-version }} - uses: actions/setup-node@v2 + uses: actions/setup-node@v3 with: node-version: ${{ matrix.node-version }} @@ -47,7 +47,7 @@ jobs: run: npm install -g yarn - name: Setup Node.js with Yarn Caching - uses: actions/setup-node@v2 + uses: actions/setup-node@v3 with: node-version: ${{ matrix.node-version }} cache: yarn diff --git a/.github/workflows/lock.yml b/.github/workflows/lock.yml index 6019cef5d..a3e66a429 100644 --- a/.github/workflows/lock.yml +++ b/.github/workflows/lock.yml @@ -14,7 +14,7 @@ jobs: lock: runs-on: ubuntu-latest steps: - - uses: dessant/lock-threads@v3 + - uses: dessant/lock-threads@v4 with: issue-inactive-days: 90 pr-inactive-days: 30 diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml index 3b37aae56..22de146a2 100644 --- a/.github/workflows/stale.yml +++ b/.github/workflows/stale.yml @@ -15,7 +15,7 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/stale@v6 + - uses: actions/stale@v8 with: close-issue-message: > This issue has been automatically closed due to lack of activity. In an From 4286c1cde255a9bf146b3b192e1ac17566af0094 Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Fri, 6 Oct 2023 15:14:33 -0400 Subject: [PATCH 15/18] Closes #12831: Include circuit description in cable trace SVG image --- docs/release-notes/version-3.6.md | 1 + netbox/dcim/svg/cables.py | 2 ++ 2 files changed, 3 insertions(+) diff --git a/docs/release-notes/version-3.6.md b/docs/release-notes/version-3.6.md index cb09ee463..6cbcf3e19 100644 --- a/docs/release-notes/version-3.6.md +++ b/docs/release-notes/version-3.6.md @@ -4,6 +4,7 @@ ### Enhancements +* [#12831](https://github.com/netbox-community/netbox/issues/12831) - Include circuit description in cable trace SVG image * [#13950](https://github.com/netbox-community/netbox/issues/13950) - Display custom choice field labels rather than values in UI ### Bug Fixes diff --git a/netbox/dcim/svg/cables.py b/netbox/dcim/svg/cables.py index c01e656fd..acc4fcad9 100644 --- a/netbox/dcim/svg/cables.py +++ b/netbox/dcim/svg/cables.py @@ -160,6 +160,8 @@ class CableTraceSVG: elif instance._meta.model_name == 'circuit': labels[0] = f'Circuit {instance}' labels.append(instance.provider) + if instance.description: + labels.append(instance.description) elif instance._meta.model_name == 'circuittermination': if instance.xconnect_id: labels.append(f'{instance.xconnect_id}') From 01c894e6257b9a4c746bab4d0ca9d0b888730a23 Mon Sep 17 00:00:00 2001 From: Arthur Date: Thu, 12 Oct 2023 09:45:16 -0700 Subject: [PATCH 16/18] 14013 fix device role filter --- netbox/dcim/forms/filtersets.py | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/netbox/dcim/forms/filtersets.py b/netbox/dcim/forms/filtersets.py index 43e5f4481..7f99d1ca4 100644 --- a/netbox/dcim/forms/filtersets.py +++ b/netbox/dcim/forms/filtersets.py @@ -109,7 +109,7 @@ class DeviceComponentFilterForm(NetBoxModelFilterSetForm): required=False, label=_('Device type') ) - role_id = DynamicModelMultipleChoiceField( + device_role_id = DynamicModelMultipleChoiceField( queryset=DeviceRole.objects.all(), required=False, label=_('Device role') @@ -1136,7 +1136,7 @@ class ConsolePortFilterForm(PathEndpointFilterForm, DeviceComponentFilterForm): (None, ('q', 'filter_id', 'tag')), (_('Attributes'), ('name', 'label', 'type', 'speed')), (_('Location'), ('region_id', 'site_group_id', 'site_id', 'location_id', 'rack_id')), - (_('Device'), ('device_type_id', 'role_id', 'device_id', 'virtual_chassis_id')), + (_('Device'), ('device_type_id', 'device_role_id', 'device_id', 'virtual_chassis_id')), (_('Connection'), ('cabled', 'connected', 'occupied')), ) type = forms.MultipleChoiceField( @@ -1158,7 +1158,7 @@ class ConsoleServerPortFilterForm(PathEndpointFilterForm, DeviceComponentFilterF (None, ('q', 'filter_id', 'tag')), (_('Attributes'), ('name', 'label', 'type', 'speed')), (_('Location'), ('region_id', 'site_group_id', 'site_id', 'location_id', 'rack_id')), - (_('Device'), ('device_type_id', 'role_id', 'device_id', 'virtual_chassis_id')), + (_('Device'), ('device_type_id', 'device_role_id', 'device_id', 'virtual_chassis_id')), (_('Connection'), ('cabled', 'connected', 'occupied')), ) type = forms.MultipleChoiceField( @@ -1180,7 +1180,7 @@ class PowerPortFilterForm(PathEndpointFilterForm, DeviceComponentFilterForm): (None, ('q', 'filter_id', 'tag')), (_('Attributes'), ('name', 'label', 'type')), (_('Location'), ('region_id', 'site_group_id', 'site_id', 'location_id', 'rack_id')), - (_('Device'), ('device_type_id', 'role_id', 'device_id', 'virtual_chassis_id')), + (_('Device'), ('device_type_id', 'device_role_id', 'device_id', 'virtual_chassis_id')), (_('Connection'), ('cabled', 'connected', 'occupied')), ) type = forms.MultipleChoiceField( @@ -1197,7 +1197,7 @@ class PowerOutletFilterForm(PathEndpointFilterForm, DeviceComponentFilterForm): (None, ('q', 'filter_id', 'tag')), (_('Attributes'), ('name', 'label', 'type')), (_('Location'), ('region_id', 'site_group_id', 'site_id', 'location_id', 'rack_id')), - (_('Device'), ('device_type_id', 'role_id', 'device_id', 'virtual_chassis_id')), + (_('Device'), ('device_type_id', 'device_role_id', 'device_id', 'virtual_chassis_id')), (_('Connection'), ('cabled', 'connected', 'occupied')), ) type = forms.MultipleChoiceField( @@ -1217,7 +1217,7 @@ class InterfaceFilterForm(PathEndpointFilterForm, DeviceComponentFilterForm): (_('PoE'), ('poe_mode', 'poe_type')), (_('Wireless'), ('rf_role', 'rf_channel', 'rf_channel_width', 'tx_power')), (_('Location'), ('region_id', 'site_group_id', 'site_id', 'location_id', 'rack_id')), - (_('Device'), ('device_type_id', 'role_id', 'device_id', 'virtual_chassis_id', 'vdc_id')), + (_('Device'), ('device_type_id', 'device_role_id', 'device_id', 'virtual_chassis_id', 'vdc_id')), (_('Connection'), ('cabled', 'connected', 'occupied')), ) vdc_id = DynamicModelMultipleChoiceField( @@ -1324,7 +1324,7 @@ class FrontPortFilterForm(CabledFilterForm, DeviceComponentFilterForm): (None, ('q', 'filter_id', 'tag')), (_('Attributes'), ('name', 'label', 'type', 'color')), (_('Location'), ('region_id', 'site_group_id', 'site_id', 'location_id', 'rack_id')), - (_('Device'), ('device_type_id', 'role_id', 'device_id', 'virtual_chassis_id')), + (_('Device'), ('device_type_id', 'device_role_id', 'device_id', 'virtual_chassis_id')), (_('Cable'), ('cabled', 'occupied')), ) model = FrontPort @@ -1346,7 +1346,7 @@ class RearPortFilterForm(CabledFilterForm, DeviceComponentFilterForm): (None, ('q', 'filter_id', 'tag')), (_('Attributes'), ('name', 'label', 'type', 'color')), (_('Location'), ('region_id', 'site_group_id', 'site_id', 'location_id', 'rack_id')), - (_('Device'), ('device_type_id', 'role_id', 'device_id', 'virtual_chassis_id')), + (_('Device'), ('device_type_id', 'device_role_id', 'device_id', 'virtual_chassis_id')), (_('Cable'), ('cabled', 'occupied')), ) type = forms.MultipleChoiceField( @@ -1367,7 +1367,7 @@ class ModuleBayFilterForm(DeviceComponentFilterForm): (None, ('q', 'filter_id', 'tag')), (_('Attributes'), ('name', 'label', 'position')), (_('Location'), ('region_id', 'site_group_id', 'site_id', 'location_id', 'rack_id')), - (_('Device'), ('device_type_id', 'role_id', 'device_id', 'virtual_chassis_id')), + (_('Device'), ('device_type_id', 'device_role_id', 'device_id', 'virtual_chassis_id')), ) tag = TagFilterField(model) position = forms.CharField( @@ -1382,7 +1382,7 @@ class DeviceBayFilterForm(DeviceComponentFilterForm): (None, ('q', 'filter_id', 'tag')), (_('Attributes'), ('name', 'label')), (_('Location'), ('region_id', 'site_group_id', 'site_id', 'location_id', 'rack_id')), - (_('Device'), ('device_type_id', 'role_id', 'device_id', 'virtual_chassis_id')), + (_('Device'), ('device_type_id', 'device_role_id', 'device_id', 'virtual_chassis_id')), ) tag = TagFilterField(model) @@ -1393,7 +1393,7 @@ class InventoryItemFilterForm(DeviceComponentFilterForm): (None, ('q', 'filter_id', 'tag')), (_('Attributes'), ('name', 'label', 'role_id', 'manufacturer_id', 'serial', 'asset_tag', 'discovered')), (_('Location'), ('region_id', 'site_group_id', 'site_id', 'location_id', 'rack_id')), - (_('Device'), ('device_type_id', 'role_id', 'device_id', 'virtual_chassis_id')), + (_('Device'), ('device_type_id', 'device_role_id', 'device_id', 'virtual_chassis_id')), ) role_id = DynamicModelMultipleChoiceField( queryset=InventoryItemRole.objects.all(), From 2522056bd1a3d4c403ea4d9406c1c093a5b62cb1 Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Fri, 6 Oct 2023 15:25:47 -0400 Subject: [PATCH 17/18] Closes #12872: Introduce DATA_UPLOAD_MAX_MEMORY_SIZE config parameter --- docs/configuration/miscellaneous.md | 12 ++++++++++-- netbox/netbox/settings.py | 1 + 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/docs/configuration/miscellaneous.md b/docs/configuration/miscellaneous.md index fd410a9d4..f143be139 100644 --- a/docs/configuration/miscellaneous.md +++ b/docs/configuration/miscellaneous.md @@ -80,6 +80,14 @@ changes in the database indefinitely. --- +## DATA_UPLOAD_MAX_MEMORY_SIZE + +Default: `2621440` (2.5 MB) + +The maximum size (in bytes) of an incoming HTTP request (i.e. `GET` or `POST` data). Requests which exceed this size will raise a `RequestDataTooBig` exception. + +--- + ## ENFORCE_GLOBAL_UNIQUE !!! tip "Dynamic Configuration Parameter" @@ -90,9 +98,9 @@ By default, NetBox will permit users to create duplicate prefixes and IP address --- -## `FILE_UPLOAD_MAX_MEMORY_SIZE` +## FILE_UPLOAD_MAX_MEMORY_SIZE -Default: `2621440` (2.5 MB). +Default: `2621440` (2.5 MB) The maximum amount (in bytes) of uploaded data that will be held in memory before being written to the filesystem. Changing this setting can be useful for example to be able to upload files bigger than 2.5MB to custom scripts for processing. diff --git a/netbox/netbox/settings.py b/netbox/netbox/settings.py index 975e86858..15c456584 100644 --- a/netbox/netbox/settings.py +++ b/netbox/netbox/settings.py @@ -95,6 +95,7 @@ CORS_ORIGIN_WHITELIST = getattr(configuration, 'CORS_ORIGIN_WHITELIST', []) CSRF_COOKIE_NAME = getattr(configuration, 'CSRF_COOKIE_NAME', 'csrftoken') CSRF_COOKIE_SECURE = getattr(configuration, 'CSRF_COOKIE_SECURE', False) CSRF_TRUSTED_ORIGINS = getattr(configuration, 'CSRF_TRUSTED_ORIGINS', []) +DATA_UPLOAD_MAX_MEMORY_SIZE = getattr(configuration, 'DATA_UPLOAD_MAX_MEMORY_SIZE', 2621440) DATE_FORMAT = getattr(configuration, 'DATE_FORMAT', 'N j, Y') DATETIME_FORMAT = getattr(configuration, 'DATETIME_FORMAT', 'N j, Y g:i a') DEBUG = getattr(configuration, 'DEBUG', False) From 72f01b3e8931386a37a1225f7b3c28e54d88fc53 Mon Sep 17 00:00:00 2001 From: Tobias Genannt Date: Thu, 12 Oct 2023 16:50:20 +0200 Subject: [PATCH 18/18] Fix #14026: Only get the needed amount of objects --- netbox/ipam/api/views.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/netbox/ipam/api/views.py b/netbox/ipam/api/views.py index 643e6a8e0..662b393de 100644 --- a/netbox/ipam/api/views.py +++ b/netbox/ipam/api/views.py @@ -266,6 +266,7 @@ class AvailableObjectsView(ObjectValidationMixin, APIView): # Normalize request data to a list of objects requested_objects = request.data if isinstance(request.data, list) else [request.data] + limit = len(requested_objects) # Serialize and validate the request data serializer = self.write_serializer_class(data=requested_objects, many=True, context={ @@ -279,7 +280,7 @@ class AvailableObjectsView(ObjectValidationMixin, APIView): ) with advisory_lock(ADVISORY_LOCK_KEYS[self.advisory_lock_key]): - available_objects = self.get_available_objects(parent) + available_objects = self.get_available_objects(parent, limit) # Determine if the requested number of objects is available if not self.check_sufficient_available(serializer.validated_data, available_objects):