Commit Graph

15866 Commits

Author SHA1 Message Date
github-actions f903cbf41d Update source translation strings 2026-08-12 05:29:58 +00:00
bctiemann 4592e7a339
Merge pull request #22904 from netbox-community/19821-gfk-field-qa-tests
#19821: Pre-release QA
2026-08-11 19:18:34 -04:00
bctiemann a08d9f13fc
Merge pull request #22867 from netbox-community/22812-script-delete-memory-exhaustion
Closes #22812: Avoid loading all jobs into memory when deleting a JobsMixin object
2026-08-11 19:17:15 -04:00
Jeremy Stretch f6e1bacfa1 Correct error message for bodyless DELETE requests 2026-08-11 13:49:27 -04:00
Jeremy Stretch bee7f3f745 Standardize the all-fields error key 2026-08-11 12:03:00 -04:00
Jason Novinger ead10f5dd6 #19821: Address review feedback on GFK QA tests
- Make the cross-content-type test select a Site pk that is not also a
  valid Region pk, rather than asserting the precondition (the two tables'
  sequences are independent and not rolled back between test classes, so
  the assertion could turn a pk collision into a spurious failure).
- Add a bulk-edit nullification test: clearing a scope via _nullify must
  null both concrete columns and must not raise the incomplete-scope
  validation error. This exercises the GenericForeignKey branch in
  BulkEditView._update_objects(), previously uncovered.
- Strengthen the malformed-input test: use an object ID which overflows
  PositiveBigIntegerField (the value that actually reaches the database)
  instead of an in-range pk, and assert the rejection lands on the scope
  field.
2026-08-11 10:28:36 -05:00
Jeremy Stretch d384136045 Return a 403 when attempting to alter non-permitted objects 2026-08-11 11:22:17 -04:00
Jason Novinger eaf24f21fa #19821: Pre-release QA
Add view-layer test coverage for the GenericObjectChoiceField scope
handling introduced by #22537, covering behaviors reachable only through
a real request:

- A bulk edit which sets a scope persists the generic foreign key to
  every selected object (previously untested).
- A constrained ObjectPermission narrows the scope object selector: a
  user cannot assign a scope object they may not view, while a permitted
  object still validates. This replaces a test which simulated the
  restriction by assigning the field queryset directly.
- An object ID belonging to a content type other than the selected one
  is rejected rather than silently accepted.
- Malformed scope input (non-integer or out-of-range identifiers) is
  rejected as invalid rather than raising a server error.
2026-08-11 10:15:30 -05:00
Jeremy Stretch 8aed00afdf Fix handling of string-typed object IDs 2026-08-11 10:42:24 -04:00
Jeremy Stretch a7971ee7d4 Correct behavior of returning a 400 vs. 409 2026-08-11 09:59:30 -04:00
Jeremy Stretch 3db98de783 Release v4.6.8 2026-08-11 09:37:13 -04:00
Jeremy Stretch 257c322e48 Revert "Fixes #22854: Set USE_SHADOW_DOM=False to fix GraphiQL queries w/debug enabled"
This reverts commit 30d2c9b537.
2026-08-11 09:37:13 -04:00
Jeremy Stretch 66480beeca Document bulk errors format in OpenAPI schema 2026-08-11 09:36:48 -04:00
Arthur Hanson a94878aa08
22745 - Enforce object permissions on Script REST API write operations (#22777) 2026-08-11 08:09:13 -04:00
github-actions a7cf21a068 Update source translation strings 2026-08-11 05:23:07 +00:00
bctiemann bc879dc48f
Merge pull request #22900 from netbox-community/22896-merge-main-into-feature
Merge main to feature
2026-08-10 20:32:09 -04:00
Jeremy Stretch b1d1919db3 Ensure a consistent error structure for both single and bulk requests 2026-08-10 16:33:25 -04:00
Jeremy Stretch 7de5a62451 Flag duplicate object IDs in bulk operations 2026-08-10 16:15:55 -04:00
Brian Tiemann fde10cbf22 Merge branch 'feature' into 22896-merge-main-into-feature
Resolves all conflicts between main and feature for #22896. Notable
resolutions:

- dcim/signals.py, dcim/tests/test_signals.py: main's cache_presave_scope_fields
  / sync_cached_scope_fields addition is fully superseded by feature's
  PostgreSQL-trigger-based denormalization (confirmed via feature's own
  migration docstrings); dropped in favor of feature's existing approach.
  Both files now match feature's originals exactly.

- netbox/tables/columns.py: combined main's generic get_ordering_annotation()
  protocol with feature's nulls_first-aware order() override. These two
  mechanisms cannot both apply to the same column (django-tables2 negates an
  entire order_by tuple uniformly on direction toggle, so a fixed nulls_first
  placement and multi-column sort composition are mutually exclusive for one
  column) -- preserved nulls_first (existing, wired through forms/API/GraphQL)
  and removed main's two composition-only tests for CustomFieldColumn. See the
  comment on CustomFieldColumn.order() for full reasoning.

- extras/customfields.py, extras/graphql/mixins.py: combined main's
  request-cache optimization and has_key-scoped batch updates with feature's
  resolve_selection_value() (shared select-field label resolution between
  REST and GraphQL).

- extras/events.py, extras/event_rules.py: main's "Honor Script defaults when
  triggered by Event Rules" (#22852) fix was written against the old inline
  action-type dispatch, which feature had already replaced with a pluggable
  action-provider registry (#22770). Re-applied the same two-line fix
  (notifications/job_timeout) inside ScriptAction.enqueue() in event_rules.py
  instead.

- utilities/jinja2.py: fixed a config-attribute name mismatch the raw merge
  would have introduced (main's JINJA2_FILTERS vs feature's renamed
  JINJA_FILTERS) by updating the shared _jinja2_filters() helper.

- ipam/migrations/: renumbered main's 0094_ipaddress_host_index to 0096 and
  added a merge migration, since main and feature had each independently
  added a migration numbered 0094.

- dcim/tests/query_counts.json: regenerated via UPDATE_QUERY_COUNTS=1 against
  the merged codebase rather than hand-merging counts.

Verified: manage.py check clean, full migration graph applies cleanly from
scratch, ruff clean, and full test suites pass for dcim, ipam, netbox, extras,
circuits, vpn, wireless, tenancy, virtualization, core, users, and account
(fresh databases, no state carried over between runs).
2026-08-10 16:13:01 -04:00
Jeremy Stretch e6dfad94c5 Move sequential creation behavior into BulkCreateModelMixin to ensure consistent error reports 2026-08-10 15:55:00 -04:00
Jeremy Stretch f68c4f63a7 Handle AbortRequest to ensure error details are returned 2026-08-10 15:22:18 -04:00
Jeremy Stretch e17227d67d Raise error when attempting to update/delete objects by unknown ID 2026-08-10 14:58:20 -04:00
Jeremy Stretch 02a350dc67 Clear events queue on rollback (single and bulk changes) 2026-08-10 14:18:16 -04:00
bctiemann ae8fa4c074
Merge pull request #22870 from netbox-community/22852-scripts-run-from-event-rules-ignore-notifications_default
Fixes #22852: Honor Custom Script execution defaults for Event Rules and `runscript`
2026-08-10 14:02:25 -04:00
Jeremy Stretch a4dcd82606
Fixes #22894: Sanitize error message rendered during exception in CustomLinkColumn (#22895) 2026-08-10 19:47:36 +02:00
Graham fca786bdf2
Closes #22502: Add direct unit tests for is_api_request() and is_graphql_request() (#22880) 2026-08-10 09:56:44 -05:00
Jeremy Stretch d76340f55e
Fixes #22882: Fix support for DISTINCT on nested GraphQL lists (#22892) 2026-08-10 09:52:01 -05:00
Jason Novinger f355a3de05 Fixes #22812: Address review — DB alias, batch size, MRO note
- batch_delete_jobs now writes through the same DB alias it reads from. In JobsMixin.delete
  the read queryset is bound to the instance's DB while Job.objects would use the router
  default; if those diverged on a multi-DB setup the deleted rows never left the read side
  and the batch loop never terminated.
- JobsMixin.delete and ScriptModule.delete honor a caller-supplied `using`, matching
  DeleteMixin.delete, instead of always recomputing it.
- Raise JOB_DELETE_BATCH_SIZE from 100 to 1000 and correct its rationale. With only('pk')
  the per-batch payload is gone, so the size now bounds per-cycle work rather than memory;
  1000 matches EXPORT_CHUNK_SIZE and was the fastest of 100/1000/5000 when benchmarked
  against a 200k-job deletion.
- Document that JobsMixin must precede DeleteMixin in the MRO or the batching is bypassed,
  and scope the ScriptModule.delete comment so it doesn't imply the on-disk file removal is
  transactional.
- Add a module-path rollback test alongside the existing script-path one.
2026-08-10 09:39:43 -05:00
Martin Hauser 53efbe0a00
Fixes #22805: Prevent repeated execution of LDAP configuration (#22809) 2026-08-10 09:04:16 -05:00
Jeremy Stretch 4b5fc1a260
#18645: Pre-release QA (#22873) 2026-08-07 16:48:41 -07:00
bctiemann 0984be8c04
#20897: Pre-release QA (#22864) 2026-08-07 16:38:32 -07:00
Martin Hauser 4660fbb0ab fix(ui): Improve dark mode form control contrast
Fixes form check input border contrast in dark mode by using solid grey
instead of translucent border. Updates checked checkbox glyph color to
rich black for better visibility against teal primary background.

Fixes #22879
2026-08-07 15:21:29 -04:00
Sri Chandraja Reddy Allala f7768e95dd
Fixes #22694: Clear stale Rack assignment when changing a Device's Site (#22764)
Prevent out-of-order dynamic select responses from restoring options for an
earlier dependency state.

Track the latest load request, preserve valid selections across superseding
loads, and properly finalize stale requests and their loading state. Clear any
pending restored value when a request cannot be made or fails.
2026-08-07 13:40:57 +02:00
github-actions a6451297a2 Update source translation strings 2026-08-07 05:30:32 +00:00
bctiemann 60e0973363
Merge pull request #22871 from netbox-community/22441-cleanup
#22441: Pre-release QA
2026-08-06 19:47:19 -04:00
Martin Hauser d61528e464
Fixes #22821: Prevent Tenant Group deletion from creating duplicate ungrouped Tenant names or slugs (#22830) 2026-08-06 15:08:41 -05:00
Jeremy Stretch 80231a9706
Closes #22835: Improve performance when provisioning new custom fields (#22866) 2026-08-06 14:56:22 -05:00
Jeremy Stretch d924937ef1 Keep completed as a default column 2026-08-06 15:14:26 -04:00
Jeremy Stretch b1ee8297d2 Closes #22877: Improve caching logic when retrieving custom fields via get_for_model() 2026-08-06 13:28:18 -04:00
Jeremy Stretch aed86db7e9 Revert implementation of elapsed_time for running jobs 2026-08-06 13:16:16 -04:00
github-actions e160359e6e Update source translation strings 2026-08-06 05:57:19 +00:00
Jeremy Stretch feaa8698a0 Move the negative-duration clamp out of humanize_duration()
humanize_duration() is a general-purpose helper, newly exposed as a template
filter, so clamping negatives inside it made every present and future caller
suppress the exact symptom of clock skew. It now renders a negative duration
with a leading minus sign, which also fixes the nonsensical output the divmod
decomposition previously produced for one (e.g. "-1d 23h 59m 55s").

The floor moves to Job.elapsed_time, which is the value NetBox displays and
covers the list, the detail panel, the script result view and runscript in one
place. The stored execution_time is untouched, so the API and exports still
surface the anomaly.

Also renames the sub-second branch's variable, which held a value in seconds
rather than milliseconds.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-05 19:38:15 -04:00
Jeremy Stretch 7f91228fbf Document that execution time sorts and filters differently
The jobs list sorts by the displayed value, so a running job orders by how
long it has been going, while execution_time__gte/__lte match only the
recorded column — a long-running job can therefore top a descending sort yet
be excluded by a filter on the same attribute.

Keeping the filters on the stored column is deliberate: the filterset is
shared with the REST API, where matching against a live, clock-dependent
value would make results non-reproducible. Document the distinction, along
with the export's use of the recorded value, rather than reconciling them.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-05 19:38:03 -04:00
Jeremy Stretch 4d3871009c Retain Job.duration as a deprecated property
Job.duration has been public since 3.4 and is reachable from user-authored
export templates as well as plugins, so removing it outright was a silent
breaking change. Restore the original implementation verbatim — including the
fallback to `created` when a job never started, and the preformatted string —
so existing templates keep working, and warn on access. Planned for removal
in v5.0, matching the rack legacy fields.

Note that elapsed_time deliberately does not reproduce the `created`
fallback: measuring from creation conflates queue wait time with execution
time, which is what the new field is meant to record.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-05 19:37:50 -04:00
Jeremy Stretch c9185e1eb7 Revert the DurationColumn extension and export execution_time verbatim
JobTable defines both render_execution_time() and value_execution_time(), so
django-tables2 never invoked DurationColumn for that column and the new
timedelta branch was unreachable and untested. Restore the column to its
minutes-only form and use a plain Column, which is what the table was
effectively getting anyway.

The export path also passed through the render path's clamping, so an
anomalous negative execution_time was normalized to zero in the one output
intended for analysis, and a running job's provisional elapsed time was
indistinguishable from a completed job's final value. Export the recorded
value verbatim and leave the still-running distinction to the UI.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-05 17:10:51 -04:00
Jeremy Stretch 26b5eb8a83 Label the job detail panel attribute "Execution Time"
Renaming the attribute to elapsed_time changed its auto-derived label to
"Elapsed time", disagreeing with the list column, the filter form, the API
field and the model docs. The derived label is also built at runtime before
being passed to gettext, so it would never have been extracted into the
message catalog. An explicit label addresses both.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-05 17:10:38 -04:00
Jeremy Stretch f427e61063 Fix elapsed_time_expression() for jobs completed without an execution time
The expression coalesced to Now() - started with no regard for whether the
job had finished, so a row with both started and completed set but a null
execution_time resolved to an ever-growing interval, while the elapsed_time
property returned None for the same row. Sorting the jobs table descending
by execution time therefore ranked those rows above every real value.

Gate the live branch on completed__isnull=True so the expression agrees with
the property.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-05 17:10:26 -04:00
Jeremy Stretch 5346dab1c3 Move the execution_time backfill into its own non-atomic migration
Batching the backfill bounded statement size but not lock duration: sharing
a transaction with the AddField meant the ACCESS EXCLUSIVE lock from ALTER
TABLE was held for the whole run, which is exactly the case the batching was
meant to help. 0025 goes back to adding the column only, and the backfill
moves to 0026 with atomic = False so the lock is released first.

The backfill now also skips rows which already have a value, making it
idempotent and letting an interrupted run simply be resumed. As a separate
migration it additionally reaches installations which had already applied
0025, rather than silently leaving their historical jobs unpopulated.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-05 17:10:13 -04:00
Jeremy Stretch bab3ccd216 Keep the job completion filters alongside the other scheduling fields
started__* and completed__* are two halves of the same time range, so
splitting them across the Scheduling and Execution field sets made a run
window awkward to filter. Execution now holds only execution_time, and the
grouping matches JobSchedulingPanel on the detail view.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-05 17:09:59 -04:00
Jeremy Stretch d642a43121
#22486: Pre-release QA (#22862)
Normalize RQ timeout values before validating global and per-webhook
timeouts, including duration strings and RQ's default and unlimited values.

Improve timeout logging and visibility in the UI and documentation, raise
the default webhook timeout to 60 seconds, and add coverage for the new
validation and filtering behavior.
2026-08-05 22:54:08 +02:00