Commit Graph

15510 Commits

Author SHA1 Message Date
Jeremy Stretch 4f4e97f1a6
Fixes #22530: Remove hidden select inputs from the accessibility tree (#22541) 2026-06-26 10:26:42 -07:00
Martin Hauser 9f140e6442
fix(extras): Prevent Script uploads from overwriting files (#22554)
Reject duplicate ScriptModule uploads before writing to storage to
prevent failed uploads from corrupting existing files. Add existence
check in cleanup path to avoid deleting files referenced by concurrent
uploads that won the race.

Fixes #22543
2026-06-26 10:19:12 -07:00
Jeremy Stretch 80a243045e
Fixes #22529: Ensure navigation menu is navigable via keyboard (#22540) 2026-06-26 10:14:06 -07:00
Jeremy Stretch 18fc16df8e
Closes #20547: Consolidate unique constraints comprising nullable fields (#22549) 2026-06-26 18:51:09 +02:00
Martin Hauser 021b7c5f5b
Closes #22174: Include DNS names for primary/OOB IPs and NAT data for VDCs (#22553) 2026-06-26 11:34:30 -05:00
Jeremy Stretch 68c1153325
Closes #22526: Avoid query timeouts when updating custom fields on a large number of objects (#22556) 2026-06-26 11:22:15 -05:00
Jamie (Bear) Murphy 2f87dab011
Closes #21710: Support multi-select fields for module type profile array enums (#22495) 2026-06-26 12:19:18 -04:00
Martin Hauser 4da65854e1 feat(dcim): Add 1C8P:8C1P breakout cable profile
Introduce Breakout1C8Px8C1PCableProfile to map a single 8-position
connector to eight single-position connectors. Add profile choice,
registration, and bidirectional link peer tests for the new breakout.

Fixes #22279
2026-06-26 12:08:22 -04:00
Jeremy Stretch 1077ff7169 Fixes #22528: Fix keyboard navigation for object list tabs 2026-06-26 08:22:16 -04:00
Jeremy Stretch 76f82989bf
Fixes #22532: Ensure all empty table headers have an ARIA label (#22545) 2026-06-26 05:08:15 -05:00
github-actions 84d9c428ee Update source translation strings 2026-06-26 06:21:47 +00:00
Jeremy Stretch 9c73c7a8ae
Fixes #22531: Ensure Saved Filter selector has unique element ID (#22542) 2026-06-25 18:04:56 +02:00
Jeremy Stretch 742cd0b5b6
Fixes #22527: Notify screen reader of quick search updates (#22534) 2026-06-25 13:35:33 +02:00
bctiemann 4daa1a0165
Merge pull request #22524 from netbox-community/22441-exec-time-jobs-table
Closes #22441: Add execution_time to background jobs
2026-06-24 18:54:33 -04:00
Jason Novinger 2dcc98b41e
Closes #21326: Defer global search cache updates to a background job (#22481)
Defer CachedValue updates from post_save/post_delete signal handlers to a
SearchCacheJob that runs after the surrounding transaction commits. Coalesce
pending updates per database alias and savepoint scope, preserving rollback
semantics while reducing synchronous write latency.

When no worker is available, or Redis cannot be reached during dispatch, apply
the update inline so existing single-process installs continue to behave
correctly. Replay the originating database alias during deferred reads and
writes so cache updates remain routed to the schema that emitted the signal.

Keep deferral private to CachedValueSearchBackend so custom SEARCH_BACKEND
implementations continue to use the existing synchronous cache/remove contract.
Move the job runner to search/jobs.py and keep the CachedValue-specific update
logic on the backend.

Document the eventual consistency of global search results and add coverage for
coalescing, rollback/savepoint behavior, worker dispatch, inline fallback,
deleted objects, and the custom backend contract.
2026-06-24 17:48:55 +02:00
Jason Novinger f1f84faa7f Fixes #22441: Address claudebot review feedback
- humanize_duration: guard on 'is None' instead of falsiness so
  timedelta(0) renders as '0s' rather than blank
- execution_time filter: add label= for consistency with sibling filters
2026-06-24 17:31:13 +02:00
Jason Novinger e7e1362c35 Closes #22441: Add execution_time field to background jobs
Adds a nullable DurationField computed as completed - started, set in
Job.terminate(). Exposes it as an orderable table column, detail-panel
attr, REST API field, and UI/API range filters (execution_time__gte /
execution_time__lte).

A plain stored field (not a GeneratedField) keeps the migration
metadata-only, avoiding a full table rewrite on core_job.
2026-06-24 16:39:59 +02:00
bctiemann 7b1e1a1dab
Closes #22419: Replace DeprecationWarning with FutureWarning for user-facing deprecations (#22510)
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-24 09:14:59 -05:00
github-actions f25a1c7474 Update source translation strings 2026-06-24 06:19:17 +00:00
Martin Hauser a1db254104 fix(dcim): Refresh Device search cache on VC rename
Add post_save signal handler to update cached virtual_chassis field for
member Devices when a VirtualChassis is renamed. Skip updates for
creates, raw saves, or targeted saves excluding the name field.

Fixes stale search cache entries after VirtualChassis name changes.

Fixes #22489
2026-06-23 13:58:15 -04:00
Jason Novinger d7c566aee6
Closes #22169: Cache image file size on ImageAttachment (#22465) 2026-06-23 08:40:19 -07:00
bctiemann b3489cd529
Merge pull request #22013 from netbox-community/21988-authorization-bypass-in-nested-object-resolution-via
Fixes #21988: Enforce object permissions for nested related objects in the REST API
2026-06-22 20:31:04 -04:00
bctiemann bf78a45204
Merge pull request #22491 from JCWasmx86/22442-cache-serializers
chore(netbox): Cache serializers
2026-06-22 20:28:57 -04:00
bctiemann 41f792c53b
Merge pull request #22473 from netbox-community/21367-mac-address
#21367 - Add is_primary field to MAC address REST API serializer
2026-06-22 20:22:46 -04:00
Jason Novinger 8c73f46cc9
Fixes #22507: Check is_active in restrict() and IsSuperuser superuser bypass (#22508)
RestrictedQuerySet.restrict() and IsSuperuser short-circuited on is_superuser
without checking is_active, so a deactivated superuser was granted the full
superuser bypass. restrict() in particular fails open, returning the
unrestricted queryset. Both now also require is_active, matching the existing
guard in ObjectPermissionMixin.has_perm.
2026-06-22 22:03:33 +02:00
Jeremy Stretch a5974ee265
Fixes #21310: Fix IntegrityError exception when `AUTH_LDAP_MIRROR_GROUPS` is enabled (#22492) 2026-06-22 05:35:38 -05:00
Jeremy Stretch 482537c72f
Closes #22393: Drop support for Redis 5.x (#22471) 2026-06-22 02:49:34 -05:00
Martin Hauser e597107b01
fix(api): Enforce Object Permissions for Nested Serializer input
Apply object-level view restrictions when nested Serializers resolve
related objects from REST API write input. Nested create and update
operations now resolve related objects from a permission-restricted
queryset, causing hidden related objects to fail validation the same as
nonexistent objects.

Fixes #21988
2026-06-20 18:13:14 +02:00
github-actions 78d4f4765e Update source translation strings 2026-06-20 06:28:34 +00:00
Arthur Hanson 626e1ef1f8
Fixes #22439: Enforce view permissions for Custom Links (#22469)
Filter custom links by the current user's view permissions before rendering
them on object detail views and table columns.
2026-06-19 09:38:47 +02:00
Jeremy Stretch 83439ba00f
Fixes #22440: Remove errant changelog filter from OpenAPI spec (#22494) 2026-06-18 23:09:33 +02:00
Jeremy Stretch e92367b3f6
Fixes #22480: Revert forced handling of image attachments as downloads (#22493) 2026-06-18 14:09:04 -07:00
mburggraf d217acdc85
Closes #22487: Remove release notes for NetBox v2.x (#22490) 2026-06-18 14:55:59 -04:00
JCWasmx86 4e1e7e9e2e chore(netbox): Cache serializers 2026-06-18 19:41:09 +02:00
mburggraf f9ce0a6741
Closes #22464: Update Documentation to use v2 Tokens in examples (#22477) 2026-06-17 13:44:29 -07:00
Arthur Hanson 4a878397a8
#22300 - Drop reverse relationship defined by OwnerMixin (#22474) 2026-06-17 16:29:46 -04:00
Martin Hauser 0e9c99ec7a test(graphql): Add GraphQL schema coverage test framework
Introduce GraphQLSchemaCoverageTestCase to verify every model-backed
GraphQL type exposed as a root query field is covered by a test. Add
type_class and graphql_test_exempt attributes to GraphQLTestCase for
explicit type declaration and coverage exclusion. Include
graphql_object_permission_assertions flag to gate permission checks for
types not enforcing object permissions.

Fixes #22089
2026-06-17 09:34:56 -04:00
Arthur 409f63c922 optimize mac address check 2026-06-16 15:02:16 -07:00
Arthur c3d8a2dc0f Add is_primary field to MAC address REST API serializer 2026-06-16 14:39:55 -07:00
Jeremy Stretch bf954f08d6 Merge branch 'main' into feature 2026-06-16 14:55:03 -04:00
Jeremy Stretch 0c26f973ff Release v4.6.3 2026-06-16 11:59:12 -04:00
Jeremy Stretch 288c47d445
#21025: Optimize rendering of config context data (#22294)
* #21025: WIP

* Fixes #22357: Remove unused `local_context_data` field from dcim.Module (#22364)

* Add partial index for checking null CC data

* Ensure the data returned by get_config_context() is safe for mutation

* Implement selective backup queryset annotation to avoid n+1 overhead on cold cache

* Fix migration conflict

* Replace MPTT with Ltree per #21418
2026-06-16 08:41:11 -07:00
Jeremy Stretch 086b1cf34d Fixes #22466: Fix test failure against SSL-enabled PosgtreSQL 2026-06-16 11:03:14 -04:00
Brian Tiemann 61696c8633 Closes #22427: Validate JSONFilter.path; add JSONStringLookup with regex
- Add _validate_json_path(): each __-separated path segment must match
  [A-Za-z0-9_][A-Za-z0-9_-]* (allows leading underscores per Jeremy's
  suggestion; ORM operator names like 'date'/'regex' are valid JSON keys
  and are not blocked — the trailing __ JSONFilter appends makes them
  key traversal steps, not ORM transforms)
- Add JSONStringLookup: explicit string-filter type for JSONLookup.
  regex/i_regex are included (they offer no additional oracle power
  beyond starts_with, which is also present, per Jeremy's observation)
- JSONFilter.filter() validates self.path and returns empty Q() on
  invalid input rather than passing untrusted user input to the ORM
- 19 unit tests for path validation and JSONStringLookup field presence

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-16 09:25:09 -04:00
Martin Hauser f46090076d refactor(graphql): Update filter lookups for strawberry-django 0.86
Update strawberry-graphql-django to 0.86.1 and remove redundant type
parameters from StrFilterLookup, DateFilterLookup, TimeFilterLookup, and
DatetimeFilterLookup annotations across model-backed GraphQL filters.

Add NetBox-local JSON date, time, and datetime lookup input types to
preserve the previous string-backed JSON filter schema without relying
on deprecated upstream generic lookup annotations. These local types
keep the legacy GraphQL type names and date/time sub-lookup fields
intact.

Fixes #22353
2026-06-16 08:50:03 -04:00
Jeremy Stretch 16c70c3657
Fixes #22448: Ensure all objects are escaped under handle_protectederror() (#22449) 2026-06-16 13:43:52 +02:00
Jason Novinger 89504b2502
Closes #21992: Enable background job support for REST API bulk requests (#22452)
Bulk write operations (create/update/delete a JSON list at a model's list
endpoint) can opt into background processing with the ?background=true query
parameter. The request is validated synchronously and, if accepted, an
AsyncAPIJob is enqueued and a 202 Accepted is returned with the job id and
poll URL; the write is performed later by a worker that re-invokes the same
viewset action, so behavior matches the synchronous path (including
all-or-nothing transaction semantics).

- AsyncAPIJob reconstructs the request in the worker, re-applies object
  permissions, runs within the request processors (change logging/events),
  and captures the action's response into job.data as {status_code, data}.
- Handled rejections are translated to match the synchronous API: APIException
  via handle_exception(), and AbortRequest/ProtectedError/RestrictedError via a
  new NetBoxModelViewSet.exception_to_response() helper. These terminate the
  job as "failed" (reserving "errored" for unexpected crashes).
- Background processing is refused with 503 when no worker is servicing the
  queue, and rejected with 400 when combined with an If-Match precondition
  (which cannot be honored once execution is deferred).
- Single-object writes, GET requests, and non-list payloads ignore the
  parameter and run synchronously.

exception_to_response() intentionally duplicates the translation logic in
dispatch() rather than dispatch() being refactored to call it; consolidating
the two is left as a follow-up to keep this change off the synchronous hot path.

* Address code review feedback (#21992)

- Carry the request's scheme and host into the background worker so absolute
  URLs in the captured job result point at the real server instead of a
  hardcoded http://localhost/.
- Emit the same protected-delete warning log in exception_to_response() that
  dispatch() produces, restoring application-log parity for background failures.
- Drop the inert `_authenticator = None` assignment: setting request.user
  already prevents lazy re-authentication via the public API, and nothing on
  the worker's action path reads the authenticator.
- Remove the redundant success-path job.save() (JobRunner.handle() ->
  terminate() persists job.data) and hoist the AsyncAPIJob import in mixins.py
  to module level (no real import cycle through it).
- Add a test asserting result URLs reflect the request host.

* Fix IPv6 host parsing in background API request reconstruction

Parse the carried host with urlsplit (and pass it verbatim as HTTP_HOST)
instead of host.partition(':'), which split bracketed IPv6 hosts like
[::1]:8443 on their inner colons. Extract request construction into
AsyncAPIJob._build_request and add a test asserting the IPv6 host round-trips.

* Address review feedback (#21992)

- Make the bulk mixins safe to use without BackgroundOperationMixin: guard the
  _background_requested / _maybe_background_bulk_create calls with a getattr
  fallback so BulkUpdateModelMixin/BulkDestroyModelMixin/SequentialBulkCreatesMixin
  retain their standalone behavior in custom viewset composition.
- Add a test covering the background ProtectedError/RestrictedError path: a bulk
  delete of a protected object records the same 409 the synchronous API returns
  (job failed, status_code 409, object preserved), via exception_to_response().
2026-06-16 12:48:17 +02:00
Jeremy Stretch 0994ce9f0c
Closes #22457: Use `hmac.compare_digest()` to authenticate API tokens (#22458) 2026-06-16 04:51:36 -05:00
Martin Hauser 025074c390
Closes #22280: Set 91% test coverage threshold and exclude non-testable paths (#22450) 2026-06-16 04:38:21 -05:00
github-actions 1264797fa6 Update source translation strings 2026-06-16 06:47:17 +00:00