Compare commits

..

9 Commits

Author SHA1 Message Date
Adam
ae03723e43 Fixes #21105: Update help text for token field on API page. (#21106)
Some checks are pending
CI / build (20.x, 3.12) (push) Waiting to run
CI / build (20.x, 3.13) (push) Waiting to run
CI / build (20.x, 3.14) (push) Waiting to run
CodeQL / Analyze (actions) (push) Waiting to run
CodeQL / Analyze (javascript-typescript) (push) Waiting to run
CodeQL / Analyze (python) (push) Waiting to run
Co-authored-by: Jason Novinger <jnovinger@gmail.com>
2026-01-12 19:17:35 -06:00
Jeremy Stretch
c0f79df91f Introduce a new issue type for feature removals (#21092)
Co-authored-by: Jason Novinger <jnovinger@gmail.com>
2026-01-12 15:41:25 -06:00
Jeremy Stretch
edbfd0bae6 Fixes #21117: Avoid exception when attempting to create v2 token without API_TOKEN_PEPPERS defined (#21132) 2026-01-12 15:40:42 -06:00
Mario
c11f4b3716 21075-rename-l2vpn-terminations-menu-entry
Some checks failed
CI / build (20.x, 3.12) (push) Has been cancelled
CI / build (20.x, 3.13) (push) Has been cancelled
CI / build (20.x, 3.14) (push) Has been cancelled
CodeQL / Analyze (actions) (push) Has been cancelled
CodeQL / Analyze (javascript-typescript) (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
2026-01-12 10:40:45 -05:00
Martin Hauser
3624b88c3f Closes #21035: Add .gitkeep to track the media directory (#21074)
Some checks failed
Close stale issues/PRs / stale (push) Has been cancelled
Close incomplete issues / stale (push) Has been cancelled
Update translation strings / makemessages (push) Has been cancelled
CI / build (20.x, 3.12) (push) Has been cancelled
CI / build (20.x, 3.13) (push) Has been cancelled
CI / build (20.x, 3.14) (push) Has been cancelled
CodeQL / Analyze (actions) (push) Has been cancelled
CodeQL / Analyze (javascript-typescript) (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
Lock threads / lock (push) Has been cancelled
2026-01-08 14:33:06 -06:00
github-actions
f54ed8bb7f Update source translation strings
Some checks failed
CodeQL / Analyze (actions) (push) Has been cancelled
CodeQL / Analyze (javascript-typescript) (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
Lock threads / lock (push) Has been cancelled
2026-01-08 05:04:46 +00:00
Jeremy Stretch
5d0609e729 Bump Python version for update-translation-strings action (#21083)
Some checks failed
CodeQL / Analyze (actions) (push) Has been cancelled
CodeQL / Analyze (javascript-typescript) (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
CI / build (20.x, 3.12) (push) Has been cancelled
CI / build (20.x, 3.13) (push) Has been cancelled
CI / build (20.x, 3.14) (push) Has been cancelled
Lock threads / lock (push) Has been cancelled
Close stale issues/PRs / stale (push) Has been cancelled
Close incomplete issues / stale (push) Has been cancelled
Update translation strings / makemessages (push) Has been cancelled
2026-01-07 15:26:21 -08:00
Brian Tiemann
865b88e724 Make module_bay recursion check on Module.clean tolerant of unset module.module_bay
Some checks failed
CI / build (20.x, 3.12) (push) Has been cancelled
CI / build (20.x, 3.13) (push) Has been cancelled
CI / build (20.x, 3.14) (push) Has been cancelled
CodeQL / Analyze (actions) (push) Has been cancelled
CodeQL / Analyze (javascript-typescript) (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
2026-01-07 10:19:02 -05:00
Jeremy Stretch
e73db97d46 Merge pull request #21079 from netbox-community/feature
Some checks failed
CI / build (20.x, 3.12) (push) Has been cancelled
CI / build (20.x, 3.13) (push) Has been cancelled
CI / build (20.x, 3.14) (push) Has been cancelled
CodeQL / Analyze (actions) (push) Has been cancelled
CodeQL / Analyze (javascript-typescript) (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
Lock threads / lock (push) Has been cancelled
Close stale issues/PRs / stale (push) Has been cancelled
Close incomplete issues / stale (push) Has been cancelled
Update translation strings / makemessages (push) Has been cancelled
Release v4.5.0
2026-01-06 16:12:06 -05:00
13 changed files with 4769 additions and 4460 deletions

View File

@@ -1,20 +1,26 @@
--- ---
name: 🗑 Deprecation name: Deprecation
type: Deprecation type: Deprecation
description: The removal of an existing feature or resource description: Designation of a feature or behavior that will be removed in a future release
labels: ["netbox", "type: deprecation"] labels: ["netbox", "type: deprecation"]
body: body:
- type: textarea - type: textarea
attributes: attributes:
label: Proposed Changes label: Deprecated Functionality
description: > description: >
Describe in detail the proposed changes. What is being removed? Describe the feature(s) and/or behavior that is being flagged for deprecation.
validations:
required: true
- type: input
attributes:
label: Scheduled removal
description: In what future release will the deprecated functionality be removed?
validations: validations:
required: true required: true
- type: textarea - type: textarea
attributes: attributes:
label: Justification label: Justification
description: Please provide justification for the proposed change(s). description: Please provide justification for the deprecation.
validations: validations:
required: true required: true
- type: textarea - type: textarea

View File

@@ -0,0 +1,20 @@
---
name: 🗑️ Feature Removal
type: Removal
description: The removal of a deprecated feature or resource
labels: ["netbox", "type: removal"]
body:
- type: input
attributes:
label: Deprecation Issue
description: Specify the issue in which this deprecation was announced.
placeholder: "#1234"
validations:
required: true
- type: textarea
attributes:
label: Summary of Changes
description: >
List all changes necessary to remove the deprecated feature or resource.
validations:
required: true

View File

@@ -34,7 +34,7 @@ jobs:
- name: Set up Python - name: Set up Python
uses: actions/setup-python@v5 uses: actions/setup-python@v5
with: with:
python-version: 3.11 python-version: 3.12
- name: Install system dependencies - name: Install system dependencies
run: sudo apt install -y gettext run: sudo apt install -y gettext

3
.gitignore vendored
View File

@@ -9,7 +9,8 @@ yarn-error.log*
/netbox/netbox/configuration.py /netbox/netbox/configuration.py
/netbox/netbox/ldap_config.py /netbox/netbox/ldap_config.py
/netbox/local/* /netbox/local/*
/netbox/media /netbox/media/*
!/netbox/media/.gitkeep
/netbox/reports/* /netbox/reports/*
!/netbox/reports/__init__.py !/netbox/reports/__init__.py
/netbox/scripts/* /netbox/scripts/*

View File

@@ -10,11 +10,9 @@ Change records are exposed in the API via the read-only endpoint `/api/extras/ob
## User Messages ## User Messages
When creating, modifying, or deleting an object in NetBox, a user has the option of recording an arbitrary message (up to 200 characters) that will appear in the change record. This can be helpful to capture additional context, such as the reason for a change or a reference to an external ticket. !!! info "This feature was introduced in NetBox v4.4."
When editing an object via the web UI, the "Changelog message" field appears at the bottom of the form. This field is optional. The changelog message field is available in object create forms, object edit forms, delete confirmation dialogs, and bulk operations. When creating, modifying, or deleting an object in NetBox, a user has the option of recording an arbitrary message that will appear in the change record. This can be helpful to capture additional context, such as the reason for the change.
For information on including changelog messages when making changes via the REST API, see [Changelog Messages](../integrations/rest-api.md#changelog-messages).
## Correlating Changes by Request ## Correlating Changes by Request

View File

@@ -610,7 +610,9 @@ http://netbox/api/dcim/sites/ \
## Changelog Messages ## Changelog Messages
Most objects in NetBox support [change logging](../features/change-logging.md), which generates a detailed record each time an object is created, modified, or deleted. Additionally, users can attach a message to the change record as well. This is accomplished via the REST API by including a `changelog_message` field in the object representation. !!! info "This feature was introduced in NetBox v4.4."
Most objects in NetBox support [change logging](../features/change-logging.md), which generates a detailed record each time an object is created, modified, or deleted. Beginning in NetBox v4.4, users can attach a message to the change record as well. This is accomplished via the REST API by including a `changelog_message` field in the object representation.
For example, the following API request will create a new site and record a message in the resulting changelog entry: For example, the following API request will create a new site and record a message in the resulting changelog entry:
@@ -626,7 +628,7 @@ http://netbox/api/dcim/sites/ \
}' }'
``` ```
This approach works when creating, modifying, or deleting objects, either individually or in bulk. For more information about change logging, see [Change Logging](../features/change-logging.md). This approach works when creating, modifying, or deleting objects, either individually or in bulk.
## Uploading Files ## Uploading Files

View File

@@ -259,11 +259,13 @@ class Module(TrackingModelMixin, PrimaryModel, ConfigContextModel):
module_bays = [] module_bays = []
modules = [] modules = []
while module: while module:
if module.pk in modules or module.module_bay.pk in module_bays: module_module_bay = getattr(module, "module_bay", None)
if module.pk in modules or (module_module_bay and module_module_bay.pk in module_bays):
raise ValidationError(_("A module bay cannot belong to a module installed within it.")) raise ValidationError(_("A module bay cannot belong to a module installed within it."))
modules.append(module.pk) modules.append(module.pk)
module_bays.append(module.module_bay.pk) if module_module_bay:
module = module.module_bay.module if module.module_bay else None module_bays.append(module_module_bay.pk)
module = module_module_bay.module if module_module_bay else None
def save(self, *args, **kwargs): def save(self, *args, **kwargs):
is_new = self.pk is None is_new = self.pk is None

0
netbox/media/.gitkeep Normal file
View File

View File

@@ -232,7 +232,7 @@ VPN_MENU = Menu(
label=_('L2VPNs'), label=_('L2VPNs'),
items=( items=(
get_model_item('vpn', 'l2vpn', _('L2VPNs')), get_model_item('vpn', 'l2vpn', _('L2VPNs')),
get_model_item('vpn', 'l2vpntermination', _('Terminations')), get_model_item('vpn', 'l2vpntermination', _('L2VPN Terminations')),
), ),
), ),
MenuGroup( MenuGroup(

File diff suppressed because it is too large Load Diff

View File

@@ -123,7 +123,7 @@ class UserTokenForm(forms.ModelForm):
token = forms.CharField( token = forms.CharField(
label=_('Token'), label=_('Token'),
help_text=_( help_text=_(
'Tokens must be at least 40 characters in length. <strong>Be sure to record your key</strong> prior to ' 'Tokens must be at least 40 characters in length. <strong>Be sure to record your token</strong> prior to '
'submitting this form, as it will no longer be accessible once the token has been created.' 'submitting this form, as it will no longer be accessible once the token has been created.'
), ),
widget=forms.TextInput( widget=forms.TextInput(

View File

@@ -69,7 +69,7 @@ class Token(models.Model):
write_enabled = models.BooleanField( write_enabled = models.BooleanField(
verbose_name=_('write enabled'), verbose_name=_('write enabled'),
default=True, default=True,
help_text=_('Permit create/update/delete operations using this key') help_text=_('Permit create/update/delete operations using this token')
) )
# For legacy v1 tokens, this field stores the plaintext 40-char token value. Not used for v2. # For legacy v1 tokens, this field stores the plaintext 40-char token value. Not used for v2.
plaintext = models.CharField( plaintext = models.CharField(
@@ -213,6 +213,9 @@ class Token(models.Model):
def clean(self): def clean(self):
super().clean() super().clean()
if self.version == TokenVersionChoices.V2 and not settings.API_TOKEN_PEPPERS:
raise ValidationError(_("Unable to save v2 tokens: API_TOKEN_PEPPERS is not defined."))
if self._state.adding: if self._state.adding:
if self.pepper_id is not None and self.pepper_id not in settings.API_TOKEN_PEPPERS: if self.pepper_id is not None and self.pepper_id not in settings.API_TOKEN_PEPPERS:
raise ValidationError(_( raise ValidationError(_(

View File

@@ -1,9 +1,10 @@
from datetime import timedelta from datetime import timedelta
from django.core.exceptions import ValidationError from django.core.exceptions import ValidationError
from django.test import TestCase from django.test import TestCase, override_settings
from django.utils import timezone from django.utils import timezone
from users.choices import TokenVersionChoices
from users.models import User, Token from users.models import User, Token
from utilities.testing import create_test_user from utilities.testing import create_test_user
@@ -94,6 +95,15 @@ class TokenTest(TestCase):
token.refresh_from_db() token.refresh_from_db()
self.assertEqual(token.description, 'New Description') self.assertEqual(token.description, 'New Description')
@override_settings(API_TOKEN_PEPPERS={})
def test_v2_without_peppers_configured(self):
"""
Attempting to save a v2 token without API_TOKEN_PEPPERS defined should raise a ValidationError.
"""
token = Token(version=TokenVersionChoices.V2)
with self.assertRaises(ValidationError):
token.clean()
class UserConfigTest(TestCase): class UserConfigTest(TestCase):