From ef460a38edd2c02d2fd887eb00f8599345550ea2 Mon Sep 17 00:00:00 2001 From: Arthur Date: Tue, 3 Oct 2023 10:22:17 -0700 Subject: [PATCH 01/15] 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/15] 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/15] 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/15] 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/15] 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/15] 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/15] 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/15] 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/15] 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/15] 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/15] 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/15] 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/15] 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/15] 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/15] 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}')