Compare commits

...

20 Commits

Author SHA1 Message Date
bctiemann
de1c5120dd Merge pull request #21346 from netbox-community/release-v4.5.2
CI / build (20.x, 3.13) (push) Failing after 14s
CI / build (20.x, 3.12) (push) Failing after 16s
CI / build (20.x, 3.14) (push) Failing after 18s
CodeQL / Analyze (actions) (push) Failing after 32s
CodeQL / Analyze (javascript-typescript) (push) Failing after 25s
CodeQL / Analyze (python) (push) Failing after 25s
Release v4.5.2
2026-02-03 08:42:21 -05:00
Jeremy Stretch
87d2e02c85 Release v4.5.2 2026-02-03 08:09:14 -05:00
github-actions
cbbc4f74b8 Update source translation strings
CodeQL / Analyze (actions) (push) Failing after 30s
CodeQL / Analyze (javascript-typescript) (push) Failing after 28s
CodeQL / Analyze (python) (push) Failing after 27s
2026-02-03 05:22:13 +00:00
Martin Hauser
be5bd74d4e feat(ipam): Add parent object fields for Services
CI / build (20.x, 3.12) (push) Failing after 13s
CI / build (20.x, 3.13) (push) Failing after 9s
CI / build (20.x, 3.14) (push) Failing after 9s
CodeQL / Analyze (actions) (push) Failing after 31s
CodeQL / Analyze (python) (push) Failing after 36s
CodeQL / Analyze (javascript-typescript) (push) Failing after 40s
Include `parent_object_type` and `parent_object_id` in `clone_fields`
for services. This improves cloning behavior for models using parent
object references, ensuring more accurate data duplication.

Fixes #21168
2026-02-02 16:05:09 -05:00
Jason Novinger
cf12bb5bf5 Fixes #20902: Avoid conflict when Git URL contains embedded username (#21252)
CI / build (20.x, 3.12) (push) Failing after 14s
CI / build (20.x, 3.13) (push) Failing after 17s
CI / build (20.x, 3.14) (push) Failing after 15s
CodeQL / Analyze (actions) (push) Failing after 37s
CodeQL / Analyze (javascript-typescript) (push) Failing after 38s
CodeQL / Analyze (python) (push) Failing after 36s
2026-02-02 11:16:32 -08:00
Jeremy Stretch
c060eef1d8 Closes #21300: Cache model-specific custom field lookups for the duration of a request (#21334) 2026-02-02 10:58:12 -08:00
bctiemann
96f0debe6e Merge pull request #21328 from netbox-community/21327-ContentTypeField-caching
Closes #21327: Leverage `get_by_natural_key()` to resolve ContentTypes
2026-02-02 13:46:04 -05:00
Martin Hauser
b26c7f34cd feat(models): Handle GFK attributes in CloningMixin
Extend the CloningMixin to inject GenericForeignKey (GFK) attributes
when both content type and ID fields are present. Improves support for
models using GFK fields during cloning operations.

Fixes #21201
2026-02-02 13:02:32 -05:00
bctiemann
d6428c6aa4 Merge pull request #21314 from marsteel/21233-UI-Add-horizontal-padding-to-Release-info-section
Fixes #21233: UI Add horizontal padding to Release info section in Navigation menu
2026-02-02 11:17:30 -05:00
github-actions
e3eca98897 Update source translation strings
CodeQL / Analyze (actions) (push) Failing after 31s
CodeQL / Analyze (javascript-typescript) (push) Failing after 46s
CodeQL / Analyze (python) (push) Failing after 49s
2026-01-31 05:14:50 +00:00
Jeremy Stretch
cdc735fe41 Closes #21302: Avoid redundant uniqueness checks in REST API serializers
CI / build (20.x, 3.12) (push) Failing after 13s
CI / build (20.x, 3.13) (push) Failing after 13s
CI / build (20.x, 3.14) (push) Failing after 24s
CodeQL / Analyze (actions) (push) Failing after 33s
CodeQL / Analyze (javascript-typescript) (push) Failing after 45s
CodeQL / Analyze (python) (push) Failing after 40s
2026-01-30 19:36:42 -05:00
Jeremy Stretch
aa4a9da955 Closes #21303: Cache serialized post-change data on object (#21325)
* Closes #21303: Cache serialized post-change data on object

* Set to_objectchange.alters_data

* Restructure logic for determining post-change snapshot
2026-01-30 14:49:12 -05:00
Jeremy Stretch
5c6fc2fb6f Closes #21110: Support for cursor-based pagination in GraphQL API (#21322) 2026-01-30 11:45:35 -08:00
Jeremy Stretch
ad29cb2d66 Closes #21263: Prefetch related objects after creating/updating objects via REST API (#21329)
* Closes #21263: Prefetch related objects after creating/updating objects via REST API

* Add comment re: ordering by PK
2026-01-30 14:13:05 -05:00
Aditya Sharma
bec5ecf6a9 Closes #21209: Accept case-insensitive model names in configuration (#21275)
CI / build (20.x, 3.12) (push) Failing after 9s
CI / build (20.x, 3.13) (push) Failing after 8s
CI / build (20.x, 3.14) (push) Failing after 8s
CodeQL / Analyze (actions) (push) Failing after 25s
CodeQL / Analyze (javascript-typescript) (push) Failing after 35s
CodeQL / Analyze (python) (push) Failing after 37s
NetBox now accepts case-insensitive model identifiers in configuration, allowing
both lowercase (e.g. "dcim.site") and PascalCase (e.g. "dcim.Site") for
DEFAULT_DASHBOARD, CUSTOM_VALIDATORS, and PROTECTION_RULES.
This makes model name handling consistent with FIELD_CHOICES.

- Add a shared case-insensitive config lookup helper (get_config_value_ci())
- Use the helper in extras/signals.py and core/signals.py
- Update FIELD_CHOICES ChoiceSetMeta to support case-insensitive replace/extend
  (only compute extend choices if no replacement is defined)
- Add unit tests for get_config_value_ci()
- Add integration tests for case-insensitive FIELD_CHOICES replacement/extension
- Update documentation examples to use PascalCase consistently
2026-01-30 13:48:38 +01:00
github-actions
c98f55dbd2 Update source translation strings
CodeQL / Analyze (actions) (push) Failing after 32s
CodeQL / Analyze (javascript-typescript) (push) Failing after 50s
CodeQL / Analyze (python) (push) Failing after 52s
2026-01-30 05:18:59 +00:00
Brian Tiemann
03853c3120 Merge branch 'main' into 20490-restrict-script-permissions
CI / build (20.x, 3.12) (push) Failing after 13s
CI / build (20.x, 3.13) (push) Failing after 16s
CI / build (20.x, 3.14) (push) Failing after 16s
2026-01-29 21:55:32 -05:00
Jeremy Stretch
dfe20532a1 Closes #21327: Leverage get_by_natural_key() to resolve ContentTypes 2026-01-29 19:46:22 -05:00
MA Gang
43ae52089f Add padding to release info div
Add padding to release info div in layout.html
2026-01-28 14:29:38 +01:00
Brian Tiemann
dc6a54ec21 Add filtering of Script objects based on object permissions with custom constraints 2026-01-18 17:23:51 -05:00
3 changed files with 98 additions and 72 deletions
+11 -1
View File
@@ -18,7 +18,17 @@ They can also be used as a mechanism for validating the integrity of data within
Custom scripts are Python code which exists outside the NetBox code base, so they can be updated and changed without interfering with the core NetBox installation. And because they're completely custom, there is no inherent limitation on what a script can accomplish. Custom scripts are Python code which exists outside the NetBox code base, so they can be updated and changed without interfering with the core NetBox installation. And because they're completely custom, there is no inherent limitation on what a script can accomplish.
!!! danger "Only install trusted scripts" !!! danger "Only install trusted scripts"
Custom scripts have unrestricted access to change anything in the databse and are inherently unsafe and should only be installed and run from trusted sources. You should also review and set permissions for who can run scripts if the script can modify any data. Custom scripts have unrestricted access to change anything in the database and are inherently unsafe and should only be installed and run from trusted sources. You should also review and set permissions for who can run scripts if the script can modify any data.
!!! tip "Permissions for Custom Scripts"
A user can be granted permissions on all Custom Scripts via the "Managed File" object-level permission. To further restrict a user to only be able to access certain scripts, create an additional permission on the "Script" object type, with appropriate queryset-style constraints matching fields available on Script. For example:
```json
{
"name__in": [
"MyScript"
]
}
```
## Writing Custom Scripts ## Writing Custom Scripts
+14
View File
@@ -24,9 +24,11 @@ from extras.utils import SharedObjectViewMixin
from netbox.object_actions import * from netbox.object_actions import *
from netbox.views import generic from netbox.views import generic
from netbox.views.generic.mixins import TableMixin from netbox.views.generic.mixins import TableMixin
from users.models import ObjectPermission
from utilities.forms import ConfirmationForm, get_field_value from utilities.forms import ConfirmationForm, get_field_value
from utilities.htmx import htmx_partial, htmx_maybe_redirect_current_page from utilities.htmx import htmx_partial, htmx_maybe_redirect_current_page
from utilities.paginator import EnhancedPaginator, get_paginate_count from utilities.paginator import EnhancedPaginator, get_paginate_count
from utilities.permissions import qs_filter_from_constraints
from utilities.query import count_related from utilities.query import count_related
from utilities.querydict import normalize_querydict from utilities.querydict import normalize_querydict
from utilities.request import copy_safe_request from utilities.request import copy_safe_request
@@ -1441,12 +1443,24 @@ class ScriptListView(ContentTypePermissionRequiredMixin, View):
return 'extras.view_script' return 'extras.view_script'
def get(self, request): def get(self, request):
# Permissions for the Scripts page are given via the "Managed File" object permission. To further restrict
# users to access only specified scripts, create permissions on the "Script" object with appropriate
# queryset-style constraints matching fields available on Script.
script_modules = ScriptModule.objects.restrict(request.user).prefetch_related( script_modules = ScriptModule.objects.restrict(request.user).prefetch_related(
'data_source', 'data_file', 'jobs' 'data_source', 'data_file', 'jobs'
) )
script_ct = ContentType.objects.get_for_model(Script)
script_permissions = qs_filter_from_constraints(
ObjectPermission.objects.filter(
users=self.request.user, object_types=script_ct
).values_list("constraints", flat=True)
)
available_scripts = Script.objects.filter(script_permissions, module__in=script_modules)
context = { context = {
'model': ScriptModule, 'model': ScriptModule,
'script_modules': script_modules, 'script_modules': script_modules,
'available_scripts': available_scripts,
} }
# Use partial template for dashboard widgets # Use partial template for dashboard widgets
@@ -38,6 +38,7 @@
</thead> </thead>
<tbody> <tbody>
{% for script in scripts %} {% for script in scripts %}
{% if script in available_scripts %}
{% with last_job=script.get_latest_jobs|first %} {% with last_job=script.get_latest_jobs|first %}
<tr> <tr>
<td> <td>
@@ -113,6 +114,7 @@
{% endfor %} {% endfor %}
{% endif %} {% endif %}
{% endwith %} {% endwith %}
{% endif %}
{% endfor %} {% endfor %}
</tbody> </tbody>
</table> </table>