Compare commits

..

1 Commits

Author SHA1 Message Date
Brian Tiemann
dc6a54ec21 Add filtering of Script objects based on object permissions with custom constraints 2026-01-18 17:23:51 -05:00
64 changed files with 66196 additions and 67755 deletions

View File

@@ -15,7 +15,7 @@ body:
attributes: attributes:
label: NetBox version label: NetBox version
description: What version of NetBox are you currently running? description: What version of NetBox are you currently running?
placeholder: v4.5.1 placeholder: v4.4.10
validations: validations:
required: true required: true
- type: dropdown - type: dropdown

View File

@@ -27,7 +27,7 @@ body:
attributes: attributes:
label: NetBox Version label: NetBox Version
description: What version of NetBox are you currently running? description: What version of NetBox are you currently running?
placeholder: v4.5.1 placeholder: v4.4.10
validations: validations:
required: true required: true
- type: dropdown - type: dropdown

File diff suppressed because it is too large Load Diff

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

View File

@@ -40,7 +40,6 @@
* [#20912](https://github.com/netbox-community/netbox/issues/20912) - Fix inconsistent clearing of `module` field on ModuleBay * [#20912](https://github.com/netbox-community/netbox/issues/20912) - Fix inconsistent clearing of `module` field on ModuleBay
* [#20944](https://github.com/netbox-community/netbox/issues/20944) - Ensure cached scope is updated on child objects when a parent region/site/location is changed * [#20944](https://github.com/netbox-community/netbox/issues/20944) - Ensure cached scope is updated on child objects when a parent region/site/location is changed
* [#20948](https://github.com/netbox-community/netbox/issues/20948) - Handle the deletion of related objects with `on_delete=RESTRICT` the same as `CASCADE` * [#20948](https://github.com/netbox-community/netbox/issues/20948) - Handle the deletion of related objects with `on_delete=RESTRICT` the same as `CASCADE`
* [#20966](https://github.com/netbox-community/netbox/issues/20966) - Fix UI rendering issue when scrolling list of object types in permissions form
* [#20969](https://github.com/netbox-community/netbox/issues/20969) - Fix querying of front port templates by `rear_port_id` * [#20969](https://github.com/netbox-community/netbox/issues/20969) - Fix querying of front port templates by `rear_port_id`
* [#21011](https://github.com/netbox-community/netbox/issues/21011) - Avoid writing to the database when loading active ConfigRevision * [#21011](https://github.com/netbox-community/netbox/issues/21011) - Avoid writing to the database when loading active ConfigRevision
* [#21032](https://github.com/netbox-community/netbox/issues/21032) - Avoid SQL subquery in RestrictedQuerySet where unnecessary * [#21032](https://github.com/netbox-community/netbox/issues/21032) - Avoid SQL subquery in RestrictedQuerySet where unnecessary

View File

@@ -1,41 +1,4 @@
# NetBox v4.5 ## v4.5.0 (FUTURE)
## v4.5.1 (2026-01-20)
### Enhancements
* [#21018](https://github.com/netbox-community/netbox/issues/21018) - Enable filtering prefixes by location/site/site group/region directly via GraphQL API
* [#21142](https://github.com/netbox-community/netbox/issues/21142) - Enable filtering device components by site/location/rack directly via GraphQL API
* [#21144](https://github.com/netbox-community/netbox/issues/21144) - Enable specifying a prefix length for IP addresses when utilizing the `/api/ipam/prefixes/<id>/available-ips/` REST API endpoint
* [#21165](https://github.com/netbox-community/netbox/issues/21165) - VLAN selector should default to group (instead of site)
* [#21178](https://github.com/netbox-community/netbox/issues/21178) - Improve consistency of rack measurements in UI
### Bug Fixes
* [#19901](https://github.com/netbox-community/netbox/issues/19901) - Fix `RelatedObjectDoesNotExist` exception when importing modules into unnamed devices
* [#20239](https://github.com/netbox-community/netbox/issues/20239) - Prevent shared mutable state in PluginMenuItem & PluginMenuButton
* [#20933](https://github.com/netbox-community/netbox/issues/20933) - Fix writable `data_file` assignment for ConfigContext and ConfigContextProfile via the REST API
* [#21039](https://github.com/netbox-community/netbox/issues/21039) - Fix support for AVIF image uploads
* [#21050](https://github.com/netbox-community/netbox/issues/21050) - Clear device OOB IP assignments when reassigning IP addresses
* [#21051](https://github.com/netbox-community/netbox/issues/21051) - Remove irrelevant object types from permissions form
* [#21097](https://github.com/netbox-community/netbox/issues/21097) - Fix comparison lookups for ID filters in GraphQL API
* [#21102](https://github.com/netbox-community/netbox/issues/21102) - Fix GraphiQL explorer UI
* [#21117](https://github.com/netbox-community/netbox/issues/21117) - Avoid `ValueError` exception when `API_TOKEN_PEPPERS` is not defined
* [#21118](https://github.com/netbox-community/netbox/issues/21118) - Address performance issue when saving sites with many assigned objects
* [#21124](https://github.com/netbox-community/netbox/issues/21124) - Fix front/rear port mapping for module types
* [#21134](https://github.com/netbox-community/netbox/issues/21134) - Fix bulk renaming for module types
* [#21139](https://github.com/netbox-community/netbox/issues/21139) - Support `fields` parameter for job, object change, and object type REST API endpoints
* [#21140](https://github.com/netbox-community/netbox/issues/21140) - Restore translation for object attribute labels on several UI views
* [#21160](https://github.com/netbox-community/netbox/issues/21160) - Fix performance issue loading UI views caused by unintended `APISelect` choices resolution
* [#21166](https://github.com/netbox-community/netbox/issues/21166) - Fix support for 32-bit ASN filtering in GraphQL API
* [#21175](https://github.com/netbox-community/netbox/issues/21175) - Fix pending migrations warning when `DEFAULT_LANGUAGE` is set
* [#21181](https://github.com/netbox-community/netbox/issues/21181) - Handle `AuthenticationFailed` exception when using an invalid API token to fetch media files
* [#21213](https://github.com/netbox-community/netbox/issues/21213) - Tag weight field should be marked as required in UI forms
* [#21231](https://github.com/netbox-community/netbox/issues/21231) - Presence of object types table should be checked only during migration (performance improvement)
---
## v4.5.0 (2026-01-06)
### Breaking Changes ### Breaking Changes

View File

@@ -11,6 +11,7 @@ from rest_framework.decorators import action
from rest_framework.exceptions import PermissionDenied from rest_framework.exceptions import PermissionDenied
from rest_framework.response import Response from rest_framework.response import Response
from rest_framework.routers import APIRootView from rest_framework.routers import APIRootView
from rest_framework.viewsets import ReadOnlyModelViewSet
from rq.job import Job as RQ_Job from rq.job import Job as RQ_Job
from rq.worker import Worker from rq.worker import Worker
@@ -63,7 +64,7 @@ class DataFileViewSet(NetBoxReadOnlyModelViewSet):
filterset_class = filtersets.DataFileFilterSet filterset_class = filtersets.DataFileFilterSet
class JobViewSet(NetBoxReadOnlyModelViewSet): class JobViewSet(ReadOnlyModelViewSet):
""" """
Retrieve a list of job results Retrieve a list of job results
""" """
@@ -72,20 +73,19 @@ class JobViewSet(NetBoxReadOnlyModelViewSet):
filterset_class = filtersets.JobFilterSet filterset_class = filtersets.JobFilterSet
class ObjectChangeViewSet(NetBoxReadOnlyModelViewSet): class ObjectChangeViewSet(ReadOnlyModelViewSet):
""" """
Retrieve a list of recent changes. Retrieve a list of recent changes.
""" """
metadata_class = ContentTypeMetadata metadata_class = ContentTypeMetadata
queryset = ObjectChange.objects.all()
serializer_class = serializers.ObjectChangeSerializer serializer_class = serializers.ObjectChangeSerializer
filterset_class = filtersets.ObjectChangeFilterSet filterset_class = filtersets.ObjectChangeFilterSet
def get_queryset(self): def get_queryset(self):
return super().get_queryset().valid_models() return ObjectChange.objects.valid_models()
class ObjectTypeViewSet(NetBoxReadOnlyModelViewSet): class ObjectTypeViewSet(ReadOnlyModelViewSet):
""" """
Read-only list of ObjectTypes. Read-only list of ObjectTypes.
""" """
@@ -94,16 +94,6 @@ class ObjectTypeViewSet(NetBoxReadOnlyModelViewSet):
serializer_class = serializers.ObjectTypeSerializer serializer_class = serializers.ObjectTypeSerializer
filterset_class = filtersets.ObjectTypeFilterSet filterset_class = filtersets.ObjectTypeFilterSet
def initial(self, request, *args, **kwargs):
"""
Override initial() to skip the restrict() call since ObjectType (a ContentType proxy)
doesn't use RestrictedQuerySet and is publicly accessible metadata.
"""
# Call GenericViewSet.initial() directly, skipping BaseViewSet.initial()
# which would try to call restrict() on the queryset
from rest_framework.viewsets import GenericViewSet
GenericViewSet.initial(self, request, *args, **kwargs)
class BaseRQViewSet(viewsets.ViewSet): class BaseRQViewSet(viewsets.ViewSet):
""" """

View File

@@ -35,10 +35,6 @@ class ObjectTypeQuerySet(models.QuerySet):
class ObjectTypeManager(models.Manager): class ObjectTypeManager(models.Manager):
# TODO: Remove this in NetBox v5.0
# Cache the result of introspection to avoid repeated queries.
_table_exists = False
def get_queryset(self): def get_queryset(self):
return ObjectTypeQuerySet(self.model, using=self._db) return ObjectTypeQuerySet(self.model, using=self._db)
@@ -73,12 +69,10 @@ class ObjectTypeManager(models.Manager):
# TODO: Remove this in NetBox v5.0 # TODO: Remove this in NetBox v5.0
# If the ObjectType table has not yet been provisioned (e.g. because we're in a pre-v4.4 migration), # If the ObjectType table has not yet been provisioned (e.g. because we're in a pre-v4.4 migration),
# fall back to ContentType. # fall back to ContentType.
if not ObjectTypeManager._table_exists: if 'core_objecttype' not in connection.introspection.table_names():
if 'core_objecttype' not in connection.introspection.table_names(): ct = ContentType.objects.get_for_model(model, for_concrete_model=for_concrete_model)
ct = ContentType.objects.get_for_model(model, for_concrete_model=for_concrete_model) ct.features = get_model_features(ct.model_class())
ct.features = get_model_features(ct.model_class()) return ct
return ct
ObjectTypeManager._table_exists = True
if not inspect.isclass(model): if not inspect.isclass(model):
model = model.__class__ model = model.__class__

View File

@@ -13,7 +13,6 @@ if TYPE_CHECKING:
from netbox.graphql.filter_lookups import IntegerLookup from netbox.graphql.filter_lookups import IntegerLookup
from extras.graphql.filters import ConfigTemplateFilter from extras.graphql.filters import ConfigTemplateFilter
from ipam.graphql.filters import VLANFilter, VLANTranslationPolicyFilter from ipam.graphql.filters import VLANFilter, VLANTranslationPolicyFilter
from dcim.graphql.filters import LocationFilter, RegionFilter, SiteFilter, SiteGroupFilter
from .filters import * from .filters import *
__all__ = ( __all__ = (
@@ -36,20 +35,6 @@ class ScopedFilterMixin:
) )
scope_id: ID | None = strawberry_django.filter_field() scope_id: ID | None = strawberry_django.filter_field()
# Cached relations
_location: Annotated['LocationFilter', strawberry.lazy('dcim.graphql.filters')] | None = (
strawberry_django.filter_field(name='location')
)
_region: Annotated['RegionFilter', strawberry.lazy('dcim.graphql.filters')] | None = (
strawberry_django.filter_field(name='region')
)
_site_group: Annotated['SiteGroupFilter', strawberry.lazy('dcim.graphql.filters')] | None = (
strawberry_django.filter_field(name='site_group')
)
_site: Annotated['SiteFilter', strawberry.lazy('dcim.graphql.filters')] | None = (
strawberry_django.filter_field(name='site')
)
@dataclass @dataclass
class ComponentModelFilterMixin: class ComponentModelFilterMixin:

View File

@@ -31,7 +31,7 @@ class RackDimensionsPanel(panels.ObjectAttributesPanel):
outer_width = attrs.NumericAttr('outer_width', unit_accessor='get_outer_unit_display') outer_width = attrs.NumericAttr('outer_width', unit_accessor='get_outer_unit_display')
outer_height = attrs.NumericAttr('outer_height', unit_accessor='get_outer_unit_display') outer_height = attrs.NumericAttr('outer_height', unit_accessor='get_outer_unit_display')
outer_depth = attrs.NumericAttr('outer_depth', unit_accessor='get_outer_unit_display') outer_depth = attrs.NumericAttr('outer_depth', unit_accessor='get_outer_unit_display')
mounting_depth = attrs.TextAttr('mounting_depth', format_string=_('{} millimeters')) mounting_depth = attrs.TextAttr('mounting_depth', format_string='{} mm')
class RackNumberingPanel(panels.ObjectAttributesPanel): class RackNumberingPanel(panels.ObjectAttributesPanel):

View File

@@ -4,17 +4,6 @@ from extras.choices import LogLevelChoices
# Custom fields # Custom fields
CUSTOMFIELD_EMPTY_VALUES = (None, '', []) CUSTOMFIELD_EMPTY_VALUES = (None, '', [])
# ImageAttachment
IMAGE_ATTACHMENT_IMAGE_FORMATS = {
'avif': 'image/avif',
'bmp': 'image/bmp',
'gif': 'image/gif',
'jpeg': 'image/jpeg',
'jpg': 'image/jpeg',
'png': 'image/png',
'webp': 'image/webp',
}
# Template Export # Template Export
DEFAULT_MIME_TYPE = 'text/plain; charset=utf-8' DEFAULT_MIME_TYPE = 'text/plain; charset=utf-8'

View File

@@ -271,6 +271,10 @@ class EventRuleImportForm(OwnerCSVMixin, NetBoxModelImportForm):
class TagImportForm(OwnerCSVMixin, CSVModelForm): class TagImportForm(OwnerCSVMixin, CSVModelForm):
slug = SlugField() slug = SlugField()
weight = forms.IntegerField(
label=_('Weight'),
required=False
)
object_types = CSVMultipleContentTypeField( object_types = CSVMultipleContentTypeField(
label=_('Object types'), label=_('Object types'),
queryset=ObjectType.objects.with_feature('tags'), queryset=ObjectType.objects.with_feature('tags'),

View File

@@ -9,7 +9,6 @@ from django.utils.translation import gettext_lazy as _
from core.forms.mixins import SyncedDataMixin from core.forms.mixins import SyncedDataMixin
from core.models import ObjectType from core.models import ObjectType
from dcim.models import DeviceRole, DeviceType, Location, Platform, Region, Site, SiteGroup from dcim.models import DeviceRole, DeviceType, Location, Platform, Region, Site, SiteGroup
from extras.constants import IMAGE_ATTACHMENT_IMAGE_FORMATS
from extras.choices import * from extras.choices import *
from extras.models import * from extras.models import *
from netbox.events import get_event_type_choices from netbox.events import get_event_type_choices
@@ -571,6 +570,10 @@ class TagForm(ChangelogMessageMixin, OwnerMixin, forms.ModelForm):
queryset=ObjectType.objects.with_feature('tags'), queryset=ObjectType.objects.with_feature('tags'),
required=False required=False
) )
weight = forms.IntegerField(
label=_('Weight'),
required=False
)
fieldsets = ( fieldsets = (
FieldSet('name', 'slug', 'color', 'weight', 'description', 'object_types', name=_('Tag')), FieldSet('name', 'slug', 'color', 'weight', 'description', 'object_types', name=_('Tag')),
@@ -781,11 +784,8 @@ class ImageAttachmentForm(forms.ModelForm):
fields = [ fields = [
'image', 'name', 'description', 'image', 'name', 'description',
] ]
# Explicitly set 'image/avif' to support AVIF selection in Firefox help_texts = {
widgets = { 'name': _("If no name is specified, the file name will be used.")
'image': forms.ClearableFileInput(
attrs={'accept': ','.join(sorted(set(IMAGE_ATTACHMENT_IMAGE_FORMATS.values())))}
),
} }

View File

@@ -10,7 +10,6 @@ from taggit.managers import _TaggableManager
from netbox.context import current_request from netbox.context import current_request
from .constants import IMAGE_ATTACHMENT_IMAGE_FORMATS
from .validators import CustomValidator from .validators import CustomValidator
__all__ = ( __all__ = (
@@ -79,7 +78,7 @@ def image_upload(instance, filename):
""" """
upload_dir = 'image-attachments' upload_dir = 'image-attachments'
default_filename = 'unnamed' default_filename = 'unnamed'
allowed_img_extensions = IMAGE_ATTACHMENT_IMAGE_FORMATS.keys() allowed_img_extensions = ('bmp', 'gif', 'jpeg', 'jpg', 'png', 'webp')
# Normalize Windows paths and create a Path object. # Normalize Windows paths and create a Path object.
normalized_filename = str(filename).replace('\\', '/') normalized_filename = str(filename).replace('\\', '/')

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

View File

@@ -19,7 +19,6 @@ from ..field_serializers import IPAddressField, IPNetworkField
__all__ = ( __all__ = (
'AggregateSerializer', 'AggregateSerializer',
'AvailableIPSerializer', 'AvailableIPSerializer',
'AvailableIPRequestSerializer',
'AvailablePrefixSerializer', 'AvailablePrefixSerializer',
'IPAddressSerializer', 'IPAddressSerializer',
'IPRangeSerializer', 'IPRangeSerializer',
@@ -148,43 +147,6 @@ class IPRangeSerializer(PrimaryModelSerializer):
# IP addresses # IP addresses
# #
class AvailableIPRequestSerializer(serializers.Serializer):
"""
Request payload for creating IP addresses from the available-ips endpoint.
"""
prefix_length = serializers.IntegerField(required=False)
def to_internal_value(self, data):
data = super().to_internal_value(data)
prefix_length = data.get('prefix_length')
if prefix_length is None:
# No override requested; the parent prefix/range mask length will be used.
return data
parent = self.context.get('parent')
if parent is None:
return data
# Validate the requested prefix length
if prefix_length < parent.mask_length:
raise serializers.ValidationError({
'prefix_length': 'Prefix length must be greater than or equal to the parent mask length ({})'.format(
parent.mask_length
)
})
elif parent.family == 4 and prefix_length > 32:
raise serializers.ValidationError({
'prefix_length': 'Invalid prefix length ({}) for IPv6'.format(prefix_length)
})
elif parent.family == 6 and prefix_length > 128:
raise serializers.ValidationError({
'prefix_length': 'Invalid prefix length ({}) for IPv4'.format(prefix_length)
})
return data
class IPAddressSerializer(PrimaryModelSerializer): class IPAddressSerializer(PrimaryModelSerializer):
family = ChoiceField(choices=IPAddressFamilyChoices, read_only=True) family = ChoiceField(choices=IPAddressFamilyChoices, read_only=True)
address = IPAddressField() address = IPAddressField()

View File

@@ -400,7 +400,7 @@ class AvailablePrefixesView(AvailableObjectsView):
class AvailableIPAddressesView(AvailableObjectsView): class AvailableIPAddressesView(AvailableObjectsView):
queryset = IPAddress.objects.all() queryset = IPAddress.objects.all()
read_serializer_class = serializers.AvailableIPSerializer read_serializer_class = serializers.AvailableIPSerializer
write_serializer_class = serializers.AvailableIPRequestSerializer write_serializer_class = serializers.AvailableIPSerializer
advisory_lock_key = 'available-ips' advisory_lock_key = 'available-ips'
def get_available_objects(self, parent, limit=None): def get_available_objects(self, parent, limit=None):
@@ -421,9 +421,8 @@ class AvailableIPAddressesView(AvailableObjectsView):
def prep_object_data(self, requested_objects, available_objects, parent): def prep_object_data(self, requested_objects, available_objects, parent):
available_ips = iter(available_objects) available_ips = iter(available_objects)
for i, request_data in enumerate(requested_objects): for i, request_data in enumerate(requested_objects):
prefix_length = request_data.pop('prefix_length', None) or parent.mask_length
request_data.update({ request_data.update({
'address': f'{next(available_ips)}/{prefix_length}', 'address': f'{next(available_ips)}/{parent.mask_length}',
'vrf': parent.vrf.pk if parent.vrf else None, 'vrf': parent.vrf.pk if parent.vrf else None,
}) })
@@ -436,7 +435,7 @@ class AvailableIPAddressesView(AvailableObjectsView):
@extend_schema( @extend_schema(
methods=["post"], methods=["post"],
responses={201: serializers.IPAddressSerializer(many=True)}, responses={201: serializers.IPAddressSerializer(many=True)},
request=serializers.AvailableIPRequestSerializer(many=True), request=serializers.IPAddressSerializer(many=True),
) )
def post(self, request, pk): def post(self, request, pk):
return super().post(request, pk) return super().post(request, pk)

View File

@@ -20,7 +20,7 @@ from tenancy.graphql.filter_mixins import ContactFilterMixin, TenancyFilterMixin
from virtualization.models import VMInterface from virtualization.models import VMInterface
if TYPE_CHECKING: if TYPE_CHECKING:
from netbox.graphql.filter_lookups import BigIntegerLookup, IntegerLookup, IntegerRangeArrayLookup from netbox.graphql.filter_lookups import IntegerLookup, IntegerRangeArrayLookup
from circuits.graphql.filters import ProviderFilter from circuits.graphql.filters import ProviderFilter
from core.graphql.filters import ContentTypeFilter from core.graphql.filters import ContentTypeFilter
from dcim.graphql.filters import SiteFilter from dcim.graphql.filters import SiteFilter
@@ -53,7 +53,7 @@ __all__ = (
class ASNFilter(TenancyFilterMixin, PrimaryModelFilter): class ASNFilter(TenancyFilterMixin, PrimaryModelFilter):
rir: Annotated['RIRFilter', strawberry.lazy('ipam.graphql.filters')] | None = strawberry_django.filter_field() rir: Annotated['RIRFilter', strawberry.lazy('ipam.graphql.filters')] | None = strawberry_django.filter_field()
rir_id: ID | None = strawberry_django.filter_field() rir_id: ID | None = strawberry_django.filter_field()
asn: Annotated['BigIntegerLookup', strawberry.lazy('netbox.graphql.filter_lookups')] | None = ( asn: Annotated['IntegerLookup', strawberry.lazy('netbox.graphql.filter_lookups')] | None = (
strawberry_django.filter_field() strawberry_django.filter_field()
) )
sites: ( sites: (
@@ -70,10 +70,10 @@ class ASNRangeFilter(TenancyFilterMixin, OrganizationalModelFilter):
slug: FilterLookup[str] | None = strawberry_django.filter_field() slug: FilterLookup[str] | None = strawberry_django.filter_field()
rir: Annotated['RIRFilter', strawberry.lazy('ipam.graphql.filters')] | None = strawberry_django.filter_field() rir: Annotated['RIRFilter', strawberry.lazy('ipam.graphql.filters')] | None = strawberry_django.filter_field()
rir_id: ID | None = strawberry_django.filter_field() rir_id: ID | None = strawberry_django.filter_field()
start: Annotated['BigIntegerLookup', strawberry.lazy('netbox.graphql.filter_lookups')] | None = ( start: Annotated['IntegerLookup', strawberry.lazy('netbox.graphql.filter_lookups')] | None = (
strawberry_django.filter_field() strawberry_django.filter_field()
) )
end: Annotated['BigIntegerLookup', strawberry.lazy('netbox.graphql.filter_lookups')] | None = ( end: Annotated['IntegerLookup', strawberry.lazy('netbox.graphql.filter_lookups')] | None = (
strawberry_django.filter_field() strawberry_django.filter_field()
) )

View File

@@ -595,31 +595,6 @@ class PrefixTest(APIViewTestCases.APIViewTestCase):
self.assertHttpStatus(response, status.HTTP_201_CREATED) self.assertHttpStatus(response, status.HTTP_201_CREATED)
self.assertEqual(len(response.data), 8) self.assertEqual(len(response.data), 8)
def test_create_available_ip_with_mask(self):
"""
Test the creation of an available IP address with a specific prefix length.
"""
prefix = Prefix.objects.create(prefix=IPNetwork('192.0.2.0/24'))
url = reverse('ipam-api:prefix-available-ips', kwargs={'pk': prefix.pk})
self.add_permissions('ipam.view_prefix', 'ipam.add_ipaddress')
# Create an available IP with a specific prefix length
data = {
'prefix_length': 32,
'description': 'Test IP 1',
}
response = self.client.post(url, data, format='json', **self.header)
self.assertHttpStatus(response, status.HTTP_201_CREATED)
self.assertEqual(response.data['address'], '192.0.2.1/32')
self.assertEqual(response.data['description'], data['description'])
# Attempt to create an available IP with a prefix length less than its parent prefix
data = {
'prefix_length': 23, # Prefix is a /24
}
response = self.client.post(url, data, format='json', **self.header)
self.assertHttpStatus(response, status.HTTP_400_BAD_REQUEST)
@tag('regression') @tag('regression')
def test_graphql_tenant_prefixes_contains_nested_skips_invalid(self): def test_graphql_tenant_prefixes_contains_nested_skips_invalid(self):
""" """

View File

@@ -19,11 +19,8 @@ from strawberry_django import (
process_filters, process_filters,
) )
from netbox.graphql.scalars import BigInt
__all__ = ( __all__ = (
'ArrayLookup', 'ArrayLookup',
'BigIntegerLookup',
'FloatArrayLookup', 'FloatArrayLookup',
'FloatLookup', 'FloatLookup',
'IntegerArrayLookup', 'IntegerArrayLookup',
@@ -81,29 +78,6 @@ class IntegerLookup:
return process_filters(filters=filters, queryset=queryset, info=info, prefix=prefix) return process_filters(filters=filters, queryset=queryset, info=info, prefix=prefix)
@strawberry.input(one_of=True, description='Lookup for BigInteger fields. Only one of the lookup fields can be set.')
class BigIntegerLookup:
filter_lookup: FilterLookup[BigInt] | None = strawberry_django.filter_field()
range_lookup: RangeLookup[BigInt] | None = strawberry_django.filter_field()
comparison_lookup: ComparisonFilterLookup[BigInt] | None = strawberry_django.filter_field()
def get_filter(self):
for field in self.__strawberry_definition__.fields:
value = getattr(self, field.name, None)
if value is not strawberry.UNSET:
return value
return None
@strawberry_django.filter_field
def filter(self, info: Info, queryset: QuerySet, prefix: DirectiveValue[str] = '') -> Tuple[QuerySet, Q]:
filters = self.get_filter()
if not filters:
return queryset, Q()
return process_filters(filters=filters, queryset=queryset, info=info, prefix=prefix)
@strawberry.input(one_of=True, description='Lookup for Float fields. Only one of the lookup fields can be set.') @strawberry.input(one_of=True, description='Lookup for Float fields. Only one of the lookup fields can be set.')
class FloatLookup: class FloatLookup:
filter_lookup: FilterLookup[float] | None = strawberry_django.filter_field() filter_lookup: FilterLookup[float] | None = strawberry_django.filter_field()

File diff suppressed because one or more lines are too long

View File

@@ -1 +1 @@
svg{--nbx-rack-bg: var(--tblr-bg-surface-secondary);--nbx-rack-border: #000;--nbx-rack-slot-bg: #e9ecef;--nbx-rack-slot-border: #adb5bd;--nbx-rack-slot-hover-bg: #ced4da;--nbx-rack-link-color: #0d6efd;--nbx-rack-unit-color: #6c757d}svg[data-bs-theme=dark]{--nbx-rack-bg: rgb(27, 41, 58);--nbx-rack-border: #6c757d;--nbx-rack-slot-bg: #343a40;--nbx-rack-slot-border: #495057;--nbx-rack-slot-hover-bg: #212529;--nbx-rack-link-color: rgb(158.2, 197, 254.2);--nbx-rack-unit-color: #adb5bd}rect{box-sizing:border-box}text{text-anchor:middle;dominant-baseline:middle}svg{background-color:var(--nbx-rack-bg);font-family:system-ui,-apple-system,Segoe UI,Roboto,Helvetica Neue,Noto Sans,Liberation Sans,Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji",Segoe UI Symbol,"Noto Color Emoji";font-size:.875rem}svg .unit{margin:0;padding:5px 0;fill:var(--nbx-rack-unit-color)}svg .hidden{visibility:hidden}svg rect.shaded,svg image.shaded{opacity:25%}svg text.shaded{opacity:50%}svg .rack{fill:none;stroke-width:2px;stroke:var(--nbx-rack-border)}svg .slot{fill:var(--nbx-rack-slot-bg);stroke:var(--nbx-rack-slot-border)}svg .slot:hover{fill:var(--nbx-rack-slot-hover-bg)}svg .slot+.add-device{fill:var(--nbx-rack-link-color);opacity:0;pointer-events:none}svg .slot:hover+.add-device{opacity:1}svg .slot.occupied[class],svg .slot.occupied:hover[class]{fill:url(#occupied)}svg .slot.blocked[class],svg .slot.blocked:hover[class]{fill:url(#blocked)}svg .slot.blocked:hover+.add-device{opacity:0}svg .reservation[class]{fill:url(#reserved)} svg{--nbx-rack-bg: var(--tblr-bg-surface-secondary);--nbx-rack-border: #000;--nbx-rack-slot-bg: #e9ecef;--nbx-rack-slot-border: #adb5bd;--nbx-rack-slot-hover-bg: #ced4da;--nbx-rack-link-color: #0d6efd;--nbx-rack-unit-color: #6c757d}svg[data-bs-theme=dark]{--nbx-rack-bg: rgb(27, 41, 58);--nbx-rack-border: #6c757d;--nbx-rack-slot-bg: #343a40;--nbx-rack-slot-border: #495057;--nbx-rack-slot-hover-bg: #212529;--nbx-rack-link-color: #9ec5fe;--nbx-rack-unit-color: #adb5bd}rect{box-sizing:border-box}text{text-anchor:middle;dominant-baseline:middle}svg{background-color:var(--nbx-rack-bg);font-family:system-ui,-apple-system,Segoe UI,Roboto,Helvetica Neue,Noto Sans,Liberation Sans,Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji",Segoe UI Symbol,"Noto Color Emoji";font-size:.875rem}svg .unit{margin:0;padding:5px 0;fill:var(--nbx-rack-unit-color)}svg .hidden{visibility:hidden}svg rect.shaded,svg image.shaded{opacity:25%}svg text.shaded{opacity:50%}svg .rack{fill:none;stroke-width:2px;stroke:var(--nbx-rack-border)}svg .slot{fill:var(--nbx-rack-slot-bg);stroke:var(--nbx-rack-slot-border)}svg .slot:hover{fill:var(--nbx-rack-slot-hover-bg)}svg .slot+.add-device{fill:var(--nbx-rack-link-color);opacity:0;pointer-events:none}svg .slot:hover+.add-device{opacity:1}svg .slot.occupied[class],svg .slot.occupied:hover[class]{fill:url(#occupied)}svg .slot.blocked[class],svg .slot.blocked:hover[class]{fill:url(#blocked)}svg .slot.blocked:hover+.add-device{opacity:0}svg .reservation[class]{fill:url(#reserved)}

View File

@@ -37,23 +37,23 @@
"typeface-roboto-mono": "1.1.13" "typeface-roboto-mono": "1.1.13"
}, },
"devDependencies": { "devDependencies": {
"@eslint/compat": "^2.0.1", "@eslint/compat": "^2.0.0",
"@eslint/eslintrc": "^3.3.3", "@eslint/eslintrc": "^3.3.3",
"@eslint/js": "^9.39.2", "@eslint/js": "^9.39.2",
"@types/bootstrap": "5.2.10", "@types/bootstrap": "5.2.10",
"@types/cookie": "^1.0.0", "@types/cookie": "^1.0.0",
"@types/node": "^24.10.1", "@types/node": "^24.10.1",
"@typescript-eslint/eslint-plugin": "^8.53.1", "@typescript-eslint/eslint-plugin": "^8.48.1",
"@typescript-eslint/parser": "^8.53.1", "@typescript-eslint/parser": "^8.48.1",
"esbuild": "^0.27.2", "esbuild": "^0.27.1",
"esbuild-sass-plugin": "^3.6.0", "esbuild-sass-plugin": "^3.3.1",
"eslint": "^9.39.2", "eslint": "^9.39.2",
"eslint-config-prettier": "^10.1.8", "eslint-config-prettier": "^10.1.8",
"eslint-import-resolver-typescript": "^4.4.4", "eslint-import-resolver-typescript": "^4.4.4",
"eslint-plugin-import": "^2.32.0", "eslint-plugin-import": "^2.32.0",
"eslint-plugin-prettier": "^5.5.5", "eslint-plugin-prettier": "^5.5.1",
"globals": "^17.0.0", "globals": "^16.5.0",
"prettier": "^3.8.0", "prettier": "^3.7.4",
"typescript": "^5.9.3" "typescript": "^5.9.3"
}, },
"resolutions": { "resolutions": {

View File

@@ -24,135 +24,142 @@
dependencies: dependencies:
tslib "^2.4.0" tslib "^2.4.0"
"@esbuild/aix-ppc64@0.27.2": "@esbuild/aix-ppc64@0.27.1":
version "0.27.2" version "0.27.1"
resolved "https://registry.yarnpkg.com/@esbuild/aix-ppc64/-/aix-ppc64-0.27.2.tgz#521cbd968dcf362094034947f76fa1b18d2d403c" resolved "https://registry.yarnpkg.com/@esbuild/aix-ppc64/-/aix-ppc64-0.27.1.tgz#116edcd62c639ed8ab551e57b38251bb28384de4"
integrity sha512-GZMB+a0mOMZs4MpDbj8RJp4cw+w1WV5NYD6xzgvzUJ5Ek2jerwfO2eADyI6ExDSUED+1X8aMbegahsJi+8mgpw== integrity sha512-HHB50pdsBX6k47S4u5g/CaLjqS3qwaOVE5ILsq64jyzgMhLuCuZ8rGzM9yhsAjfjkbgUPMzZEPa7DAp7yz6vuA==
"@esbuild/android-arm64@0.27.2": "@esbuild/android-arm64@0.27.1":
version "0.27.2" version "0.27.1"
resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.27.2.tgz#61ea550962d8aa12a9b33194394e007657a6df57" resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.27.1.tgz#31c00d864c80f6de1900a11de8a506dbfbb27349"
integrity sha512-pvz8ZZ7ot/RBphf8fv60ljmaoydPU12VuXHImtAs0XhLLw+EXBi2BLe3OYSBslR4rryHvweW5gmkKFwTiFy6KA== integrity sha512-45fuKmAJpxnQWixOGCrS+ro4Uvb4Re9+UTieUY2f8AEc+t7d4AaZ6eUJ3Hva7dtrxAAWHtlEFsXFMAgNnGU9uQ==
"@esbuild/android-arm@0.27.2": "@esbuild/android-arm@0.27.1":
version "0.27.2" version "0.27.1"
resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.27.2.tgz#554887821e009dd6d853f972fde6c5143f1de142" resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.27.1.tgz#d2b73ab0ba894923a1d1378fd4b15cc20985f436"
integrity sha512-DVNI8jlPa7Ujbr1yjU2PfUSRtAUZPG9I1RwW4F4xFB1Imiu2on0ADiI/c3td+KmDtVKNbi+nffGDQMfcIMkwIA== integrity sha512-kFqa6/UcaTbGm/NncN9kzVOODjhZW8e+FRdSeypWe6j33gzclHtwlANs26JrupOntlcWmB0u8+8HZo8s7thHvg==
"@esbuild/android-x64@0.27.2": "@esbuild/android-x64@0.27.1":
version "0.27.2" version "0.27.1"
resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.27.2.tgz#a7ce9d0721825fc578f9292a76d9e53334480ba2" resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.27.1.tgz#d9f74d8278191317250cfe0c15a13f410540b122"
integrity sha512-z8Ank4Byh4TJJOh4wpz8g2vDy75zFL0TlZlkUkEwYXuPSgX8yzep596n6mT7905kA9uHZsf/o2OJZubl2l3M7A== integrity sha512-LBEpOz0BsgMEeHgenf5aqmn/lLNTFXVfoWMUox8CtWWYK9X4jmQzWjoGoNb8lmAYml/tQ/Ysvm8q7szu7BoxRQ==
"@esbuild/darwin-arm64@0.27.2": "@esbuild/darwin-arm64@0.27.1":
version "0.27.2" version "0.27.1"
resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.27.2.tgz#2cb7659bd5d109803c593cfc414450d5430c8256" resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.27.1.tgz#baf6914b8c57ed9d41f9de54023aa3ff9b084680"
integrity sha512-davCD2Zc80nzDVRwXTcQP/28fiJbcOwvdolL0sOiOsbwBa72kegmVU0Wrh1MYrbuCL98Omp5dVhQFWRKR2ZAlg== integrity sha512-veg7fL8eMSCVKL7IW4pxb54QERtedFDfY/ASrumK/SbFsXnRazxY4YykN/THYqFnFwJ0aVjiUrVG2PwcdAEqQQ==
"@esbuild/darwin-x64@0.27.2": "@esbuild/darwin-x64@0.27.1":
version "0.27.2" version "0.27.1"
resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.27.2.tgz#e741fa6b1abb0cd0364126ba34ca17fd5e7bf509" resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.27.1.tgz#64e37400795f780a76c858a118ff19681a64b4e0"
integrity sha512-ZxtijOmlQCBWGwbVmwOF/UCzuGIbUkqB1faQRf5akQmxRJ1ujusWsb3CVfk/9iZKr2L5SMU5wPBi1UWbvL+VQA== integrity sha512-+3ELd+nTzhfWb07Vol7EZ+5PTbJ/u74nC6iv4/lwIU99Ip5uuY6QoIf0Hn4m2HoV0qcnRivN3KSqc+FyCHjoVQ==
"@esbuild/freebsd-arm64@0.27.2": "@esbuild/freebsd-arm64@0.27.1":
version "0.27.2" version "0.27.1"
resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.27.2.tgz#2b64e7116865ca172d4ce034114c21f3c93e397c" resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.27.1.tgz#6572f2f235933eee906e070dfaae54488ee60acd"
integrity sha512-lS/9CN+rgqQ9czogxlMcBMGd+l8Q3Nj1MFQwBZJyoEKI50XGxwuzznYdwcav6lpOGv5BqaZXqvBSiB/kJ5op+g== integrity sha512-/8Rfgns4XD9XOSXlzUDepG8PX+AVWHliYlUkFI3K3GB6tqbdjYqdhcb4BKRd7C0BhZSoaCxhv8kTcBrcZWP+xg==
"@esbuild/freebsd-x64@0.27.2": "@esbuild/freebsd-x64@0.27.1":
version "0.27.2" version "0.27.1"
resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.27.2.tgz#e5252551e66f499e4934efb611812f3820e990bb" resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.27.1.tgz#83105dba9cf6ac4f44336799446d7f75c8c3a1e1"
integrity sha512-tAfqtNYb4YgPnJlEFu4c212HYjQWSO/w/h/lQaBK7RbwGIkBOuNKQI9tqWzx7Wtp7bTPaGC6MJvWI608P3wXYA== integrity sha512-GITpD8dK9C+r+5yRT/UKVT36h/DQLOHdwGVwwoHidlnA168oD3uxA878XloXebK4Ul3gDBBIvEdL7go9gCUFzQ==
"@esbuild/linux-arm64@0.27.2": "@esbuild/linux-arm64@0.27.1":
version "0.27.2" version "0.27.1"
resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.27.2.tgz#dc4acf235531cd6984f5d6c3b13dbfb7ddb303cb" resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.27.1.tgz#035ff647d4498bdf16eb2d82801f73b366477dfa"
integrity sha512-hYxN8pr66NsCCiRFkHUAsxylNOcAQaxSSkHMMjcpx0si13t1LHFphxJZUiGwojB1a/Hd5OiPIqDdXONia6bhTw== integrity sha512-W9//kCrh/6in9rWIBdKaMtuTTzNj6jSeG/haWBADqLLa9P8O5YSRDzgD5y9QBok4AYlzS6ARHifAb75V6G670Q==
"@esbuild/linux-arm@0.27.2": "@esbuild/linux-arm@0.27.1":
version "0.27.2" version "0.27.1"
resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.27.2.tgz#56a900e39240d7d5d1d273bc053daa295c92e322" resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.27.1.tgz#3516c74d2afbe305582dbb546d60f7978a8ece7f"
integrity sha512-vWfq4GaIMP9AIe4yj1ZUW18RDhx6EPQKjwe7n8BbIecFtCQG4CfHGaHuh7fdfq+y3LIA2vGS/o9ZBGVxIDi9hw== integrity sha512-ieMID0JRZY/ZeCrsFQ3Y3NlHNCqIhTprJfDgSB3/lv5jJZ8FX3hqPyXWhe+gvS5ARMBJ242PM+VNz/ctNj//eA==
"@esbuild/linux-ia32@0.27.2": "@esbuild/linux-ia32@0.27.1":
version "0.27.2" version "0.27.1"
resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.27.2.tgz#d4a36d473360f6870efcd19d52bbfff59a2ed1cc" resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.27.1.tgz#788db5db8ecd3d75dd41c42de0fe8f1fd967a4a7"
integrity sha512-MJt5BRRSScPDwG2hLelYhAAKh9imjHK5+NE/tvnRLbIqUWa+0E9N4WNMjmp/kXXPHZGqPLxggwVhz7QP8CTR8w== integrity sha512-VIUV4z8GD8rtSVMfAj1aXFahsi/+tcoXXNYmXgzISL+KB381vbSTNdeZHHHIYqFyXcoEhu9n5cT+05tRv13rlw==
"@esbuild/linux-loong64@0.27.2": "@esbuild/linux-loong64@0.27.1":
version "0.27.2" version "0.27.1"
resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.27.2.tgz#fcf0ab8c3eaaf45891d0195d4961cb18b579716a" resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.27.1.tgz#8211f08b146916a6302ec2b8f87ec0cc4b62c49e"
integrity sha512-lugyF1atnAT463aO6KPshVCJK5NgRnU4yb3FUumyVz+cGvZbontBgzeGFO1nF+dPueHD367a2ZXe1NtUkAjOtg== integrity sha512-l4rfiiJRN7sTNI//ff65zJ9z8U+k6zcCg0LALU5iEWzY+a1mVZ8iWC1k5EsNKThZ7XCQ6YWtsZ8EWYm7r1UEsg==
"@esbuild/linux-mips64el@0.27.2": "@esbuild/linux-mips64el@0.27.1":
version "0.27.2" version "0.27.1"
resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.27.2.tgz#598b67d34048bb7ee1901cb12e2a0a434c381c10" resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.27.1.tgz#cc58586ea83b3f171e727a624e7883a1c3eb4c04"
integrity sha512-nlP2I6ArEBewvJ2gjrrkESEZkB5mIoaTswuqNFRv/WYd+ATtUpe9Y09RnJvgvdag7he0OWgEZWhviS1OTOKixw== integrity sha512-U0bEuAOLvO/DWFdygTHWY8C067FXz+UbzKgxYhXC0fDieFa0kDIra1FAhsAARRJbvEyso8aAqvPdNxzWuStBnA==
"@esbuild/linux-ppc64@0.27.2": "@esbuild/linux-ppc64@0.27.1":
version "0.27.2" version "0.27.1"
resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.27.2.tgz#3846c5df6b2016dab9bc95dde26c40f11e43b4c0" resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.27.1.tgz#632477bbd98175cf8e53a7c9952d17fb2d6d4115"
integrity sha512-C92gnpey7tUQONqg1n6dKVbx3vphKtTHJaNG2Ok9lGwbZil6DrfyecMsp9CrmXGQJmZ7iiVXvvZH6Ml5hL6XdQ== integrity sha512-NzdQ/Xwu6vPSf/GkdmRNsOfIeSGnh7muundsWItmBsVpMoNPVpM61qNzAVY3pZ1glzzAxLR40UyYM23eaDDbYQ==
"@esbuild/linux-riscv64@0.27.2": "@esbuild/linux-riscv64@0.27.1":
version "0.27.2" version "0.27.1"
resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.27.2.tgz#173d4475b37c8d2c3e1707e068c174bb3f53d07d" resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.27.1.tgz#35435a82435a8a750edf433b83ac0d10239ac3fe"
integrity sha512-B5BOmojNtUyN8AXlK0QJyvjEZkWwy/FKvakkTDCziX95AowLZKR6aCDhG7LeF7uMCXEJqwa8Bejz5LTPYm8AvA== integrity sha512-7zlw8p3IApcsN7mFw0O1Z1PyEk6PlKMu18roImfl3iQHTnr/yAfYv6s4hXPidbDoI2Q0pW+5xeoM4eTCC0UdrQ==
"@esbuild/linux-s390x@0.27.2": "@esbuild/linux-s390x@0.27.1":
version "0.27.2" version "0.27.1"
resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.27.2.tgz#f7a4790105edcab8a5a31df26fbfac1aa3dacfab" resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.27.1.tgz#172edd7086438edacd86c0e2ea25ac9dbb62aac5"
integrity sha512-p4bm9+wsPwup5Z8f4EpfN63qNagQ47Ua2znaqGH6bqLlmJ4bx97Y9JdqxgGZ6Y8xVTixUnEkoKSHcpRlDnNr5w== integrity sha512-cGj5wli+G+nkVQdZo3+7FDKC25Uh4ZVwOAK6A06Hsvgr8WqBBuOy/1s+PUEd/6Je+vjfm6stX0kmib5b/O2Ykw==
"@esbuild/linux-x64@0.27.2": "@esbuild/linux-x64@0.27.1":
version "0.27.2" version "0.27.1"
resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.27.2.tgz#2ecc1284b1904aeb41e54c9ddc7fcd349b18f650" resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.27.1.tgz#09c771de9e2d8169d5969adf298ae21581f08c7f"
integrity sha512-uwp2Tip5aPmH+NRUwTcfLb+W32WXjpFejTIOWZFw/v7/KnpCDKG66u4DLcurQpiYTiYwQ9B7KOeMJvLCu/OvbA== integrity sha512-z3H/HYI9MM0HTv3hQZ81f+AKb+yEoCRlUby1F80vbQ5XdzEMyY/9iNlAmhqiBKw4MJXwfgsh7ERGEOhrM1niMA==
"@esbuild/netbsd-arm64@0.27.2": "@esbuild/netbsd-arm64@0.27.1":
version "0.27.2" version "0.27.1"
resolved "https://registry.yarnpkg.com/@esbuild/netbsd-arm64/-/netbsd-arm64-0.27.2.tgz#e2863c2cd1501845995cb11adf26f7fe4be527b0" resolved "https://registry.yarnpkg.com/@esbuild/netbsd-arm64/-/netbsd-arm64-0.27.1.tgz#475ac0ce7edf109a358b1669f67759de4bcbb7c4"
integrity sha512-Kj6DiBlwXrPsCRDeRvGAUb/LNrBASrfqAIok+xB0LxK8CHqxZ037viF13ugfsIpePH93mX7xfJp97cyDuTZ3cw== integrity sha512-wzC24DxAvk8Em01YmVXyjl96Mr+ecTPyOuADAvjGg+fyBpGmxmcr2E5ttf7Im8D0sXZihpxzO1isus8MdjMCXQ==
"@esbuild/netbsd-x64@0.27.2": "@esbuild/netbsd-x64@0.27.1":
version "0.27.2" version "0.27.1"
resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.27.2.tgz#93f7609e2885d1c0b5a1417885fba8d1fcc41272" resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.27.1.tgz#3c31603d592477dc43b63df1ae100000f7fb59d7"
integrity sha512-HwGDZ0VLVBY3Y+Nw0JexZy9o/nUAWq9MlV7cahpaXKW6TOzfVno3y3/M8Ga8u8Yr7GldLOov27xiCnqRZf0tCA== integrity sha512-1YQ8ybGi2yIXswu6eNzJsrYIGFpnlzEWRl6iR5gMgmsrR0FcNoV1m9k9sc3PuP5rUBLshOZylc9nqSgymI+TYg==
"@esbuild/openbsd-arm64@0.27.2": "@esbuild/openbsd-arm64@0.27.1":
version "0.27.2" version "0.27.1"
resolved "https://registry.yarnpkg.com/@esbuild/openbsd-arm64/-/openbsd-arm64-0.27.2.tgz#a1985604a203cdc325fd47542e106fafd698f02e" resolved "https://registry.yarnpkg.com/@esbuild/openbsd-arm64/-/openbsd-arm64-0.27.1.tgz#482067c847665b10d66431e936d4bc5fa8025abf"
integrity sha512-DNIHH2BPQ5551A7oSHD0CKbwIA/Ox7+78/AWkbS5QoRzaqlev2uFayfSxq68EkonB+IKjiuxBFoV8ESJy8bOHA== integrity sha512-5Z+DzLCrq5wmU7RDaMDe2DVXMRm2tTDvX2KU14JJVBN2CT/qov7XVix85QoJqHltpvAOZUAc3ndU56HSMWrv8g==
"@esbuild/openbsd-x64@0.27.2": "@esbuild/openbsd-x64@0.27.1":
version "0.27.2" version "0.27.1"
resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.27.2.tgz#8209e46c42f1ffbe6e4ef77a32e1f47d404ad42a" resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.27.1.tgz#687a188c2b184e5b671c5f74a6cd6247c0718c52"
integrity sha512-/it7w9Nb7+0KFIzjalNJVR5bOzA9Vay+yIPLVHfIQYG/j+j9VTH84aNB8ExGKPU4AzfaEvN9/V4HV+F+vo8OEg== integrity sha512-Q73ENzIdPF5jap4wqLtsfh8YbYSZ8Q0wnxplOlZUOyZy7B4ZKW8DXGWgTCZmF8VWD7Tciwv5F4NsRf6vYlZtqg==
"@esbuild/openharmony-arm64@0.27.2": "@esbuild/openharmony-arm64@0.27.1":
version "0.27.2" version "0.27.1"
resolved "https://registry.yarnpkg.com/@esbuild/openharmony-arm64/-/openharmony-arm64-0.27.2.tgz#8fade4441893d9cc44cbd7dcf3776f508ab6fb2f" resolved "https://registry.yarnpkg.com/@esbuild/openharmony-arm64/-/openharmony-arm64-0.27.1.tgz#9929ee7fa8c1db2f33ef4d86198018dac9c1744f"
integrity sha512-LRBbCmiU51IXfeXk59csuX/aSaToeG7w48nMwA6049Y4J4+VbWALAuXcs+qcD04rHDuSCSRKdmY63sruDS5qag== integrity sha512-ajbHrGM/XiK+sXM0JzEbJAen+0E+JMQZ2l4RR4VFwvV9JEERx+oxtgkpoKv1SevhjavK2z2ReHk32pjzktWbGg==
"@esbuild/sunos-x64@0.27.2": "@esbuild/sunos-x64@0.27.1":
version "0.27.2" version "0.27.1"
resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.27.2.tgz#980d4b9703a16f0f07016632424fc6d9a789dfc2" resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.27.1.tgz#94071a146f313e7394c6424af07b2b564f1f994d"
integrity sha512-kMtx1yqJHTmqaqHPAzKCAkDaKsffmXkPHThSfRwZGyuqyIeBvf08KSsYXl+abf5HDAPMJIPnbBfXvP2ZC2TfHg== integrity sha512-IPUW+y4VIjuDVn+OMzHc5FV4GubIwPnsz6ubkvN8cuhEqH81NovB53IUlrlBkPMEPxvNnf79MGBoz8rZ2iW8HA==
"@esbuild/win32-arm64@0.27.2": "@esbuild/win32-arm64@0.27.1":
version "0.27.2" version "0.27.1"
resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.27.2.tgz#1c09a3633c949ead3d808ba37276883e71f6111a" resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.27.1.tgz#869fde72a3576fdf48824085d05493fceebe395d"
integrity sha512-Yaf78O/B3Kkh+nKABUF++bvJv5Ijoy9AN1ww904rOXZFLWVc5OLOfL56W+C8F9xn5JQZa3UX6m+IktJnIb1Jjg== integrity sha512-RIVRWiljWA6CdVu8zkWcRmGP7iRRIIwvhDKem8UMBjPql2TXM5PkDVvvrzMtj1V+WFPB4K7zkIGM7VzRtFkjdg==
"@esbuild/win32-ia32@0.27.2": "@esbuild/win32-ia32@0.27.1":
version "0.27.2" version "0.27.1"
resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.27.2.tgz#1b1e3a63ad4bef82200fef4e369e0fff7009eee5" resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.27.1.tgz#31d7585893ed7b54483d0b8d87a4bfeba0ecfff5"
integrity sha512-Iuws0kxo4yusk7sw70Xa2E2imZU5HoixzxfGCdxwBdhiDgt9vX9VUCBhqcwY7/uh//78A1hMkkROMJq9l27oLQ== integrity sha512-2BR5M8CPbptC1AK5JbJT1fWrHLvejwZidKx3UMSF0ecHMa+smhi16drIrCEggkgviBwLYd5nwrFLSl5Kho96RQ==
"@esbuild/win32-x64@0.27.2": "@esbuild/win32-x64@0.27.1":
version "0.27.2" version "0.27.1"
resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.27.2.tgz#9e585ab6086bef994c6e8a5b3a0481219ada862b" resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.27.1.tgz#5efe5a112938b1180e98c76685ff9185cfa4f16e"
integrity sha512-sRdU18mcKf7F+YgheI/zGf5alZatMUTKj/jNS6l744f9u3WFu4v7twcUI9vu4mknF4Y9aDlblIie0IM+5xxaqQ== integrity sha512-d5X6RMYv6taIymSk8JBP+nxv8DQAMY6A51GPgusqLdK9wBz5wWIXy1KjTck6HnjE9hqJzJRdk+1p/t5soSbCtw==
"@eslint-community/eslint-utils@^4.7.0":
version "4.7.0"
resolved "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.7.0.tgz"
integrity sha512-dyybb3AcajC7uha6CvhdVRJqaKyn7w2YKqKyAN37NKYgZT36w+iRb0Dymmc5qEJ549c/S31cMMSFd75bteCpCw==
dependencies:
eslint-visitor-keys "^3.4.3"
"@eslint-community/eslint-utils@^4.8.0": "@eslint-community/eslint-utils@^4.8.0":
version "4.9.0" version "4.9.0"
@@ -161,24 +168,22 @@
dependencies: dependencies:
eslint-visitor-keys "^3.4.3" eslint-visitor-keys "^3.4.3"
"@eslint-community/eslint-utils@^4.9.1": "@eslint-community/regexpp@^4.10.0":
version "4.9.1" version "4.12.1"
resolved "https://registry.yarnpkg.com/@eslint-community/eslint-utils/-/eslint-utils-4.9.1.tgz#4e90af67bc51ddee6cdef5284edf572ec376b595" resolved "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.1.tgz"
integrity sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ== integrity sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==
dependencies:
eslint-visitor-keys "^3.4.3"
"@eslint-community/regexpp@^4.12.1", "@eslint-community/regexpp@^4.12.2": "@eslint-community/regexpp@^4.12.1":
version "4.12.2" version "4.12.2"
resolved "https://registry.yarnpkg.com/@eslint-community/regexpp/-/regexpp-4.12.2.tgz#bccdf615bcf7b6e8db830ec0b8d21c9a25de597b" resolved "https://registry.yarnpkg.com/@eslint-community/regexpp/-/regexpp-4.12.2.tgz#bccdf615bcf7b6e8db830ec0b8d21c9a25de597b"
integrity sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew== integrity sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==
"@eslint/compat@^2.0.1": "@eslint/compat@^2.0.0":
version "2.0.1" version "2.0.0"
resolved "https://registry.yarnpkg.com/@eslint/compat/-/compat-2.0.1.tgz#5894516f8ce9ba884f4d4ba5ecb6b6459b231144" resolved "https://registry.npmjs.org/@eslint/compat/-/compat-2.0.0.tgz"
integrity sha512-yl/JsgplclzuvGFNqwNYV4XNPhP3l62ZOP9w/47atNAdmDtIFCx6X7CSk/SlWUuBGkT4Et/5+UD+WyvX2iiIWA== integrity sha512-T9AfE1G1uv4wwq94ozgTGio5EUQBqAVe1X9qsQtSNVEYW6j3hvtZVm8Smr4qL1qDPFg+lOB2cL5RxTRMzq4CTA==
dependencies: dependencies:
"@eslint/core" "^1.0.1" "@eslint/core" "^1.0.0"
"@eslint/config-array@^0.21.1": "@eslint/config-array@^0.21.1":
version "0.21.1" version "0.21.1"
@@ -203,10 +208,10 @@
dependencies: dependencies:
"@types/json-schema" "^7.0.15" "@types/json-schema" "^7.0.15"
"@eslint/core@^1.0.1": "@eslint/core@^1.0.0":
version "1.0.1" version "1.0.0"
resolved "https://registry.yarnpkg.com/@eslint/core/-/core-1.0.1.tgz#701ff760cbd279f9490bef0ce54095f4088d4def" resolved "https://registry.npmjs.org/@eslint/core/-/core-1.0.0.tgz"
integrity sha512-r18fEAj9uCk+VjzGt2thsbOmychS+4kxI14spVNibUO2vqKX7obOG+ymZljAwuPZl+S3clPGwCwTDtrdqTiY6Q== integrity sha512-PRfWP+8FOldvbApr6xL7mNCw4cJcSTq4GA7tYbgq15mRb0kWKO/wEB2jr+uwjFH3sZvEZneZyCUGTxsv4Sahyw==
dependencies: dependencies:
"@types/json-schema" "^7.0.15" "@types/json-schema" "^7.0.15"
@@ -935,100 +940,101 @@
dependencies: dependencies:
"@types/estree" "*" "@types/estree" "*"
"@typescript-eslint/eslint-plugin@^8.53.1": "@typescript-eslint/eslint-plugin@^8.48.1":
version "8.53.1" version "8.48.1"
resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.53.1.tgz#f6640f6f8749b71d9ab457263939e8932a3c6b46" resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.48.1.tgz#c772d1dbdd97cfddf85f5a161a97783233643631"
integrity sha512-cFYYFZ+oQFi6hUnBTbLRXfTJiaQtYE3t4O692agbBl+2Zy+eqSKWtPjhPXJu1G7j4RLjKgeJPDdq3EqOwmX5Ag== integrity sha512-X63hI1bxl5ohelzr0LY5coufyl0LJNthld+abwxpCoo6Gq+hSqhKwci7MUWkXo67mzgUK6YFByhmaHmUcuBJmA==
dependencies: dependencies:
"@eslint-community/regexpp" "^4.12.2" "@eslint-community/regexpp" "^4.10.0"
"@typescript-eslint/scope-manager" "8.53.1" "@typescript-eslint/scope-manager" "8.48.1"
"@typescript-eslint/type-utils" "8.53.1" "@typescript-eslint/type-utils" "8.48.1"
"@typescript-eslint/utils" "8.53.1" "@typescript-eslint/utils" "8.48.1"
"@typescript-eslint/visitor-keys" "8.53.1" "@typescript-eslint/visitor-keys" "8.48.1"
ignore "^7.0.5" graphemer "^1.4.0"
ignore "^7.0.0"
natural-compare "^1.4.0" natural-compare "^1.4.0"
ts-api-utils "^2.4.0" ts-api-utils "^2.1.0"
"@typescript-eslint/parser@^8.53.1": "@typescript-eslint/parser@^8.48.1":
version "8.53.1" version "8.48.1"
resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-8.53.1.tgz#58d4a70cc2daee2becf7d4521d65ea1782d6ec68" resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-8.48.1.tgz#4e3c66d9ec20683ec142417fafeadab61c479c3f"
integrity sha512-nm3cvFN9SqZGXjmw5bZ6cGmvJSyJPn0wU9gHAZZHDnZl2wF9PhHv78Xf06E0MaNk4zLVHL8hb2/c32XvyJOLQg== integrity sha512-PC0PDZfJg8sP7cmKe6L3QIL8GZwU5aRvUFedqSIpw3B+QjRSUZeeITC2M5XKeMXEzL6wccN196iy3JLwKNvDVA==
dependencies: dependencies:
"@typescript-eslint/scope-manager" "8.53.1" "@typescript-eslint/scope-manager" "8.48.1"
"@typescript-eslint/types" "8.53.1" "@typescript-eslint/types" "8.48.1"
"@typescript-eslint/typescript-estree" "8.53.1" "@typescript-eslint/typescript-estree" "8.48.1"
"@typescript-eslint/visitor-keys" "8.53.1" "@typescript-eslint/visitor-keys" "8.48.1"
debug "^4.4.3" debug "^4.3.4"
"@typescript-eslint/project-service@8.53.1": "@typescript-eslint/project-service@8.48.1":
version "8.53.1" version "8.48.1"
resolved "https://registry.yarnpkg.com/@typescript-eslint/project-service/-/project-service-8.53.1.tgz#4e47856a0b14a1ceb28b0294b4badef3be1e9734" resolved "https://registry.yarnpkg.com/@typescript-eslint/project-service/-/project-service-8.48.1.tgz#cfe1741613b9112d85ae766de9e09b27a7d3f2f1"
integrity sha512-WYC4FB5Ra0xidsmlPb+1SsnaSKPmS3gsjIARwbEkHkoWloQmuzcfypljaJcR78uyLA1h8sHdWWPHSLDI+MtNog== integrity sha512-HQWSicah4s9z2/HifRPQ6b6R7G+SBx64JlFQpgSSHWPKdvCZX57XCbszg/bapbRsOEv42q5tayTYcEFpACcX1w==
dependencies: dependencies:
"@typescript-eslint/tsconfig-utils" "^8.53.1" "@typescript-eslint/tsconfig-utils" "^8.48.1"
"@typescript-eslint/types" "^8.53.1" "@typescript-eslint/types" "^8.48.1"
debug "^4.4.3" debug "^4.3.4"
"@typescript-eslint/scope-manager@8.53.1": "@typescript-eslint/scope-manager@8.48.1":
version "8.53.1" version "8.48.1"
resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-8.53.1.tgz#6c4b8c82cd45ae3b365afc2373636e166743a8fa" resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-8.48.1.tgz#8bc70643e7cca57864b1ff95dd350fc27756bec0"
integrity sha512-Lu23yw1uJMFY8cUeq7JlrizAgeQvWugNQzJp8C3x8Eo5Jw5Q2ykMdiiTB9vBVOOUBysMzmRRmUfwFrZuI2C4SQ== integrity sha512-rj4vWQsytQbLxC5Bf4XwZ0/CKd362DkWMUkviT7DCS057SK64D5lH74sSGzhI6PDD2HCEq02xAP9cX68dYyg1w==
dependencies: dependencies:
"@typescript-eslint/types" "8.53.1" "@typescript-eslint/types" "8.48.1"
"@typescript-eslint/visitor-keys" "8.53.1" "@typescript-eslint/visitor-keys" "8.48.1"
"@typescript-eslint/tsconfig-utils@8.53.1", "@typescript-eslint/tsconfig-utils@^8.53.1": "@typescript-eslint/tsconfig-utils@8.48.1", "@typescript-eslint/tsconfig-utils@^8.48.1":
version "8.53.1" version "8.48.1"
resolved "https://registry.yarnpkg.com/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.53.1.tgz#efe80b8d019cd49e5a1cf46c2eb0cd2733076424" resolved "https://registry.yarnpkg.com/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.48.1.tgz#68139ce2d258f984e2b33a95389158f1212af646"
integrity sha512-qfvLXS6F6b1y43pnf0pPbXJ+YoXIC7HKg0UGZ27uMIemKMKA6XH2DTxsEDdpdN29D+vHV07x/pnlPNVLhdhWiA== integrity sha512-k0Jhs4CpEffIBm6wPaCXBAD7jxBtrHjrSgtfCjUvPp9AZ78lXKdTR8fxyZO5y4vWNlOvYXRtngSZNSn+H53Jkw==
"@typescript-eslint/type-utils@8.53.1": "@typescript-eslint/type-utils@8.48.1":
version "8.53.1" version "8.48.1"
resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-8.53.1.tgz#95de2651a96d580bf5c6c6089ddd694284d558ad" resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-8.48.1.tgz#955bd3ddd648450f0a627925ff12ade63fb7516d"
integrity sha512-MOrdtNvyhy0rHyv0ENzub1d4wQYKb2NmIqG7qEqPWFW7Mpy2jzFC3pQ2yKDvirZB7jypm5uGjF2Qqs6OIqu47w== integrity sha512-1jEop81a3LrJQLTf/1VfPQdhIY4PlGDBc/i67EVWObrtvcziysbLN3oReexHOM6N3jyXgCrkBsZpqwH0hiDOQg==
dependencies: dependencies:
"@typescript-eslint/types" "8.53.1" "@typescript-eslint/types" "8.48.1"
"@typescript-eslint/typescript-estree" "8.53.1" "@typescript-eslint/typescript-estree" "8.48.1"
"@typescript-eslint/utils" "8.53.1" "@typescript-eslint/utils" "8.48.1"
debug "^4.4.3" debug "^4.3.4"
ts-api-utils "^2.4.0" ts-api-utils "^2.1.0"
"@typescript-eslint/types@8.53.1", "@typescript-eslint/types@^8.53.1": "@typescript-eslint/types@8.48.1", "@typescript-eslint/types@^8.48.1":
version "8.53.1" version "8.48.1"
resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-8.53.1.tgz#101f203f0807a63216cceceedb815fabe21d5793" resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-8.48.1.tgz#a9ff808f5f798f28767d5c0b015a88fa7ce46bd7"
integrity sha512-jr/swrr2aRmUAUjW5/zQHbMaui//vQlsZcJKijZf3M26bnmLj8LyZUpj8/Rd6uzaek06OWsqdofN/Thenm5O8A== integrity sha512-+fZ3LZNeiELGmimrujsDCT4CRIbq5oXdHe7chLiW8qzqyPMnn1puNstCrMNVAqwcl2FdIxkuJ4tOs/RFDBVc/Q==
"@typescript-eslint/typescript-estree@8.53.1": "@typescript-eslint/typescript-estree@8.48.1":
version "8.53.1" version "8.48.1"
resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-8.53.1.tgz#b6dce2303c9e27e95b8dcd8c325868fff53e488f" resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-8.48.1.tgz#0d0e31fc47c5796c6463ab50cde19e1718d465b1"
integrity sha512-RGlVipGhQAG4GxV1s34O91cxQ/vWiHJTDHbXRr0li2q/BGg3RR/7NM8QDWgkEgrwQYCvmJV9ichIwyoKCQ+DTg== integrity sha512-/9wQ4PqaefTK6POVTjJaYS0bynCgzh6ClJHGSBj06XEHjkfylzB+A3qvyaXnErEZSaxhIo4YdyBgq6j4RysxDg==
dependencies: dependencies:
"@typescript-eslint/project-service" "8.53.1" "@typescript-eslint/project-service" "8.48.1"
"@typescript-eslint/tsconfig-utils" "8.53.1" "@typescript-eslint/tsconfig-utils" "8.48.1"
"@typescript-eslint/types" "8.53.1" "@typescript-eslint/types" "8.48.1"
"@typescript-eslint/visitor-keys" "8.53.1" "@typescript-eslint/visitor-keys" "8.48.1"
debug "^4.4.3" debug "^4.3.4"
minimatch "^9.0.5" minimatch "^9.0.4"
semver "^7.7.3" semver "^7.6.0"
tinyglobby "^0.2.15" tinyglobby "^0.2.15"
ts-api-utils "^2.4.0" ts-api-utils "^2.1.0"
"@typescript-eslint/utils@8.53.1": "@typescript-eslint/utils@8.48.1":
version "8.53.1" version "8.48.1"
resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-8.53.1.tgz#81fe6c343de288701b774f4d078382f567e6edaa" resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-8.48.1.tgz#6cf7b99e0943b33a983ef687b9a86b65578b5c32"
integrity sha512-c4bMvGVWW4hv6JmDUEG7fSYlWOl3II2I4ylt0NM+seinYQlZMQIaKaXIIVJWt9Ofh6whrpM+EdDQXKXjNovvrg== integrity sha512-fAnhLrDjiVfey5wwFRwrweyRlCmdz5ZxXz2G/4cLn0YDLjTapmN4gcCsTBR1N2rWnZSDeWpYtgLDsJt+FpmcwA==
dependencies: dependencies:
"@eslint-community/eslint-utils" "^4.9.1" "@eslint-community/eslint-utils" "^4.7.0"
"@typescript-eslint/scope-manager" "8.53.1" "@typescript-eslint/scope-manager" "8.48.1"
"@typescript-eslint/types" "8.53.1" "@typescript-eslint/types" "8.48.1"
"@typescript-eslint/typescript-estree" "8.53.1" "@typescript-eslint/typescript-estree" "8.48.1"
"@typescript-eslint/visitor-keys@8.53.1": "@typescript-eslint/visitor-keys@8.48.1":
version "8.53.1" version "8.48.1"
resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-8.53.1.tgz#405f04959be22b9be364939af8ac19c3649b6eb7" resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-8.48.1.tgz#247d4fe6dcc044f45b7f1c15110bf95e5d73b334"
integrity sha512-oy+wV7xDKFPRyNggmXuZQSBzvoLnpmJs+GhzRhPjrxl2b/jIlyjVokzm47CZCDUdXKr2zd7ZLodPfOBpOPyPlg== integrity sha512-BmxxndzEWhE4TIEEMBs8lP3MBWN3jFPs/p6gPm/wkv02o41hI6cq9AuSmGAaTTHPtA1FTi2jBre4A9rm5ZmX+Q==
dependencies: dependencies:
"@typescript-eslint/types" "8.53.1" "@typescript-eslint/types" "8.48.1"
eslint-visitor-keys "^4.2.1" eslint-visitor-keys "^4.2.1"
"@unrs/resolver-binding-android-arm-eabi@1.11.1": "@unrs/resolver-binding-android-arm-eabi@1.11.1":
@@ -1155,6 +1161,14 @@ ansi-styles@^4.1.0:
dependencies: dependencies:
color-convert "^2.0.1" color-convert "^2.0.1"
anymatch@~3.1.2:
version "3.1.3"
resolved "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz"
integrity sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==
dependencies:
normalize-path "^3.0.0"
picomatch "^2.0.4"
argparse@^2.0.1: argparse@^2.0.1:
version "2.0.1" version "2.0.1"
resolved "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz" resolved "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz"
@@ -1274,6 +1288,11 @@ balanced-match@^1.0.0:
resolved "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz" resolved "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz"
integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==
binary-extensions@^2.0.0:
version "2.3.0"
resolved "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz"
integrity sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==
bootstrap@5.3.7: bootstrap@5.3.7:
version "5.3.7" version "5.3.7"
resolved "https://registry.npmjs.org/bootstrap/-/bootstrap-5.3.7.tgz" resolved "https://registry.npmjs.org/bootstrap/-/bootstrap-5.3.7.tgz"
@@ -1299,7 +1318,7 @@ brace-expansion@^2.0.1:
dependencies: dependencies:
balanced-match "^1.0.0" balanced-match "^1.0.0"
braces@^3.0.3: braces@^3.0.3, braces@~3.0.2:
version "3.0.3" version "3.0.3"
resolved "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz" resolved "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz"
integrity sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA== integrity sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==
@@ -1356,6 +1375,21 @@ chalk@^4.0.0:
ansi-styles "^4.1.0" ansi-styles "^4.1.0"
supports-color "^7.1.0" supports-color "^7.1.0"
"chokidar@>=3.0.0 <4.0.0":
version "3.6.0"
resolved "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz"
integrity sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==
dependencies:
anymatch "~3.1.2"
braces "~3.0.2"
glob-parent "~5.1.2"
is-binary-path "~2.1.0"
is-glob "~4.0.1"
normalize-path "~3.0.0"
readdirp "~3.6.0"
optionalDependencies:
fsevents "~2.3.2"
chokidar@^4.0.0: chokidar@^4.0.0:
version "4.0.1" version "4.0.1"
resolved "https://registry.npmjs.org/chokidar/-/chokidar-4.0.1.tgz" resolved "https://registry.npmjs.org/chokidar/-/chokidar-4.0.1.tgz"
@@ -1499,13 +1533,20 @@ debug@^3.2.7:
dependencies: dependencies:
ms "^2.1.1" ms "^2.1.1"
debug@^4.3.1, debug@^4.3.2, debug@^4.4.1, debug@^4.4.3: debug@^4.3.1, debug@^4.3.2, debug@^4.4.1:
version "4.4.3" version "4.4.3"
resolved "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz" resolved "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz"
integrity sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA== integrity sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==
dependencies: dependencies:
ms "^2.1.3" ms "^2.1.3"
debug@^4.3.4:
version "4.4.1"
resolved "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz"
integrity sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==
dependencies:
ms "^2.1.3"
decode-uri-component@^0.4.1: decode-uri-component@^0.4.1:
version "0.4.1" version "0.4.1"
resolved "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.4.1.tgz" resolved "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.4.1.tgz"
@@ -1764,45 +1805,46 @@ es-to-primitive@^1.3.0:
is-date-object "^1.0.5" is-date-object "^1.0.5"
is-symbol "^1.0.4" is-symbol "^1.0.4"
esbuild-sass-plugin@^3.6.0: esbuild-sass-plugin@^3.3.1:
version "3.6.0" version "3.3.1"
resolved "https://registry.yarnpkg.com/esbuild-sass-plugin/-/esbuild-sass-plugin-3.6.0.tgz#6e93d0aec87b6ab7bde2e459c5f1ab472088bd41" resolved "https://registry.npmjs.org/esbuild-sass-plugin/-/esbuild-sass-plugin-3.3.1.tgz"
integrity sha512-lzPJQSEXcnj5amBPPib5lBjsDNPzvdMnX+1Rf7eha9BIpLSM5Ad2pi+Rqg5CAlWMduCgLntS2hLAqG7v1fxWGw== integrity sha512-SnO1ls+d52n6j8gRRpjexXI8MsHEaumS0IdDHaYM29Y6gakzZYMls6i9ql9+AWMSQk/eryndmUpXEgT34QrX1A==
dependencies: dependencies:
resolve "^1.22.11" resolve "^1.22.8"
sass "^1.97.2" safe-identifier "^0.4.2"
sass "^1.71.1"
esbuild@^0.27.2: esbuild@^0.27.1:
version "0.27.2" version "0.27.1"
resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.27.2.tgz#d83ed2154d5813a5367376bb2292a9296fc83717" resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.27.1.tgz#56bf43e6a4b4d2004642ec7c091b78de02b0831a"
integrity sha512-HyNQImnsOC7X9PMNaCIeAm4ISCQXs5a5YasTXVliKv4uuBo1dKrG0A+uQS8M5eXjVMnLg3WgXaKvprHlFJQffw== integrity sha512-yY35KZckJJuVVPXpvjgxiCuVEJT67F6zDeVTv4rizyPrfGBUpZQsvmxnN+C371c2esD/hNMjj4tpBhuueLN7aA==
optionalDependencies: optionalDependencies:
"@esbuild/aix-ppc64" "0.27.2" "@esbuild/aix-ppc64" "0.27.1"
"@esbuild/android-arm" "0.27.2" "@esbuild/android-arm" "0.27.1"
"@esbuild/android-arm64" "0.27.2" "@esbuild/android-arm64" "0.27.1"
"@esbuild/android-x64" "0.27.2" "@esbuild/android-x64" "0.27.1"
"@esbuild/darwin-arm64" "0.27.2" "@esbuild/darwin-arm64" "0.27.1"
"@esbuild/darwin-x64" "0.27.2" "@esbuild/darwin-x64" "0.27.1"
"@esbuild/freebsd-arm64" "0.27.2" "@esbuild/freebsd-arm64" "0.27.1"
"@esbuild/freebsd-x64" "0.27.2" "@esbuild/freebsd-x64" "0.27.1"
"@esbuild/linux-arm" "0.27.2" "@esbuild/linux-arm" "0.27.1"
"@esbuild/linux-arm64" "0.27.2" "@esbuild/linux-arm64" "0.27.1"
"@esbuild/linux-ia32" "0.27.2" "@esbuild/linux-ia32" "0.27.1"
"@esbuild/linux-loong64" "0.27.2" "@esbuild/linux-loong64" "0.27.1"
"@esbuild/linux-mips64el" "0.27.2" "@esbuild/linux-mips64el" "0.27.1"
"@esbuild/linux-ppc64" "0.27.2" "@esbuild/linux-ppc64" "0.27.1"
"@esbuild/linux-riscv64" "0.27.2" "@esbuild/linux-riscv64" "0.27.1"
"@esbuild/linux-s390x" "0.27.2" "@esbuild/linux-s390x" "0.27.1"
"@esbuild/linux-x64" "0.27.2" "@esbuild/linux-x64" "0.27.1"
"@esbuild/netbsd-arm64" "0.27.2" "@esbuild/netbsd-arm64" "0.27.1"
"@esbuild/netbsd-x64" "0.27.2" "@esbuild/netbsd-x64" "0.27.1"
"@esbuild/openbsd-arm64" "0.27.2" "@esbuild/openbsd-arm64" "0.27.1"
"@esbuild/openbsd-x64" "0.27.2" "@esbuild/openbsd-x64" "0.27.1"
"@esbuild/openharmony-arm64" "0.27.2" "@esbuild/openharmony-arm64" "0.27.1"
"@esbuild/sunos-x64" "0.27.2" "@esbuild/sunos-x64" "0.27.1"
"@esbuild/win32-arm64" "0.27.2" "@esbuild/win32-arm64" "0.27.1"
"@esbuild/win32-ia32" "0.27.2" "@esbuild/win32-ia32" "0.27.1"
"@esbuild/win32-x64" "0.27.2" "@esbuild/win32-x64" "0.27.1"
escape-string-regexp@^4.0.0: escape-string-regexp@^4.0.0:
version "4.0.0" version "4.0.0"
@@ -1876,13 +1918,13 @@ eslint-plugin-import@^2.32.0:
string.prototype.trimend "^1.0.9" string.prototype.trimend "^1.0.9"
tsconfig-paths "^3.15.0" tsconfig-paths "^3.15.0"
eslint-plugin-prettier@^5.5.5: eslint-plugin-prettier@^5.5.1:
version "5.5.5" version "5.5.4"
resolved "https://registry.yarnpkg.com/eslint-plugin-prettier/-/eslint-plugin-prettier-5.5.5.tgz#9eae11593faa108859c26f9a9c367d619a0769c0" resolved "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.5.4.tgz"
integrity sha512-hscXkbqUZ2sPithAuLm5MXL+Wph+U7wHngPBv9OMWwlP8iaflyxpjTYZkmdgB4/vPIhemRlBEoLrH7UC1n7aUw== integrity sha512-swNtI95SToIz05YINMA6Ox5R057IMAmWZ26GqPxusAp1TZzj+IdY9tXNWWD3vkF/wEqydCONcwjTFpxybBqZsg==
dependencies: dependencies:
prettier-linter-helpers "^1.0.1" prettier-linter-helpers "^1.0.0"
synckit "^0.11.12" synckit "^0.11.7"
eslint-scope@^8.4.0: eslint-scope@^8.4.0:
version "8.4.0" version "8.4.0"
@@ -2068,6 +2110,11 @@ framer-motion@^12:
motion-utils "^12.23.6" motion-utils "^12.23.6"
tslib "^2.4.0" tslib "^2.4.0"
fsevents@~2.3.2:
version "2.3.3"
resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6"
integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==
function-bind@^1.1.2: function-bind@^1.1.2:
version "1.1.2" version "1.1.2"
resolved "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz" resolved "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz"
@@ -2179,15 +2226,22 @@ glob-parent@^6.0.2:
dependencies: dependencies:
is-glob "^4.0.3" is-glob "^4.0.3"
glob-parent@~5.1.2:
version "5.1.2"
resolved "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz"
integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==
dependencies:
is-glob "^4.0.1"
globals@^14.0.0: globals@^14.0.0:
version "14.0.0" version "14.0.0"
resolved "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz" resolved "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz"
integrity sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ== integrity sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==
globals@^17.0.0: globals@^16.5.0:
version "17.0.0" version "16.5.0"
resolved "https://registry.yarnpkg.com/globals/-/globals-17.0.0.tgz#a4196d9cfeb4d627ba165b4647b1f5853bf90a30" resolved "https://registry.npmjs.org/globals/-/globals-16.5.0.tgz"
integrity sha512-gv5BeD2EssA793rlFWVPMMCqefTlpusw6/2TbAVMy0FzcG8wKJn4O+NqJ4+XWmmwrayJgw5TzrmWjFgmz1XPqw== integrity sha512-c/c15i26VrJ4IRt5Z89DnIzCGDn9EcebibhAOjw5ibqEHsE1wLUgkPn9RDmNcUKyU87GeaL633nyJ+pplFR2ZQ==
globalthis@^1.0.3, globalthis@^1.0.4: globalthis@^1.0.3, globalthis@^1.0.4:
version "1.0.4" version "1.0.4"
@@ -2216,6 +2270,11 @@ gopd@^1.2.0:
resolved "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz" resolved "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz"
integrity sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg== integrity sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==
graphemer@^1.4.0:
version "1.4.0"
resolved "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz"
integrity sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==
graphiql-explorer@^0.9.0: graphiql-explorer@^0.9.0:
version "0.9.0" version "0.9.0"
resolved "https://registry.npmjs.org/graphiql-explorer/-/graphiql-explorer-0.9.0.tgz" resolved "https://registry.npmjs.org/graphiql-explorer/-/graphiql-explorer-0.9.0.tgz"
@@ -2313,11 +2372,16 @@ ignore@^5.2.0:
resolved "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz" resolved "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz"
integrity sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g== integrity sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==
ignore@^7.0.5: ignore@^7.0.0:
version "7.0.5" version "7.0.5"
resolved "https://registry.yarnpkg.com/ignore/-/ignore-7.0.5.tgz#4cb5f6cd7d4c7ab0365738c7aea888baa6d7efd9" resolved "https://registry.npmjs.org/ignore/-/ignore-7.0.5.tgz"
integrity sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg== integrity sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==
immutable@^4.0.0:
version "4.3.7"
resolved "https://registry.npmjs.org/immutable/-/immutable-4.3.7.tgz"
integrity sha512-1hqclzwYwjRDFLjcFxOM5AYkkG0rpFPpr1RLPMEuGczoS7YA8gLhy8SWXYRAA/XwfEHpfo3cw5JGioS32fnMRw==
immutable@^5.0.2: immutable@^5.0.2:
version "5.0.3" version "5.0.3"
resolved "https://registry.npmjs.org/immutable/-/immutable-5.0.3.tgz" resolved "https://registry.npmjs.org/immutable/-/immutable-5.0.3.tgz"
@@ -2396,6 +2460,13 @@ is-bigint@^1.1.0:
dependencies: dependencies:
has-bigints "^1.0.2" has-bigints "^1.0.2"
is-binary-path@~2.1.0:
version "2.1.0"
resolved "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz"
integrity sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==
dependencies:
binary-extensions "^2.0.0"
is-boolean-object@^1.1.0: is-boolean-object@^1.1.0:
version "1.1.2" version "1.1.2"
resolved "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz" resolved "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz"
@@ -2491,7 +2562,7 @@ is-generator-function@^1.0.10:
has-tostringtag "^1.0.2" has-tostringtag "^1.0.2"
safe-regex-test "^1.1.0" safe-regex-test "^1.1.0"
is-glob@^4.0.0, is-glob@^4.0.3: is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3, is-glob@~4.0.1:
version "4.0.3" version "4.0.3"
resolved "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz" resolved "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz"
integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==
@@ -2786,7 +2857,7 @@ minimatch@^3.1.2:
dependencies: dependencies:
brace-expansion "^1.1.7" brace-expansion "^1.1.7"
minimatch@^9.0.5: minimatch@^9.0.4:
version "9.0.5" version "9.0.5"
resolved "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz" resolved "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz"
integrity sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow== integrity sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==
@@ -2830,6 +2901,11 @@ node-addon-api@^7.0.0:
resolved "https://registry.npmjs.org/node-addon-api/-/node-addon-api-7.1.1.tgz" resolved "https://registry.npmjs.org/node-addon-api/-/node-addon-api-7.1.1.tgz"
integrity sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ== integrity sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==
normalize-path@^3.0.0, normalize-path@~3.0.0:
version "3.0.0"
resolved "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz"
integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==
nullthrows@^1.0.0: nullthrows@^1.0.0:
version "1.1.1" version "1.1.1"
resolved "https://registry.npmjs.org/nullthrows/-/nullthrows-1.1.1.tgz" resolved "https://registry.npmjs.org/nullthrows/-/nullthrows-1.1.1.tgz"
@@ -2958,7 +3034,7 @@ path-parse@^1.0.7:
resolved "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz" resolved "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz"
integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==
picomatch@^2.3.1: picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.3.1:
version "2.3.1" version "2.3.1"
resolved "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz" resolved "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz"
integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==
@@ -2978,17 +3054,17 @@ prelude-ls@^1.2.1:
resolved "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz" resolved "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz"
integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g== integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==
prettier-linter-helpers@^1.0.1: prettier-linter-helpers@^1.0.0:
version "1.0.1" version "1.0.0"
resolved "https://registry.yarnpkg.com/prettier-linter-helpers/-/prettier-linter-helpers-1.0.1.tgz#6a31f88a4bad6c7adda253de12ba4edaea80ebcd" resolved "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz"
integrity sha512-SxToR7P8Y2lWmv/kTzVLC1t/GDI2WGjMwNhLLE9qtH8Q13C+aEmuRlzDst4Up4s0Wc8sF2M+J57iB3cMLqftfg== integrity sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==
dependencies: dependencies:
fast-diff "^1.1.2" fast-diff "^1.1.2"
prettier@^3.8.0: prettier@^3.7.4:
version "3.8.0" version "3.7.4"
resolved "https://registry.yarnpkg.com/prettier/-/prettier-3.8.0.tgz#f72cf71505133f40cfa2ef77a2668cdc558fcd69" resolved "https://registry.yarnpkg.com/prettier/-/prettier-3.7.4.tgz#d2f8335d4b1cec47e1c8098645411b0c9dff9c0f"
integrity sha512-yEPsovQfpxYfgWNhCfECjG5AQaO+K3dp6XERmOepyPDVqcJm+bjyCVO3pmU+nAPe0N5dDvekfGezt/EIiRe1TA== integrity sha512-v6UNi1+3hSlVvv8fSaoUbggEM5VErKmmpGA7Pl3HF8V6uKY7rvClBOJlH6yNwQtfTueNkGVpOv/mtWL9L4bgRA==
punycode.js@^2.3.1: punycode.js@^2.3.1:
version "2.3.1" version "2.3.1"
@@ -3061,6 +3137,13 @@ readdirp@^4.0.1:
resolved "https://registry.npmjs.org/readdirp/-/readdirp-4.0.1.tgz" resolved "https://registry.npmjs.org/readdirp/-/readdirp-4.0.1.tgz"
integrity sha512-GkMg9uOTpIWWKbSsgwb5fA4EavTR+SG/PMPoAY8hkhHfEEY0/vqljY+XHqtDf2cr2IJtoNRDbrrEpZUiZCkYRw== integrity sha512-GkMg9uOTpIWWKbSsgwb5fA4EavTR+SG/PMPoAY8hkhHfEEY0/vqljY+XHqtDf2cr2IJtoNRDbrrEpZUiZCkYRw==
readdirp@~3.6.0:
version "3.6.0"
resolved "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz"
integrity sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==
dependencies:
picomatch "^2.2.1"
reflect.getprototypeof@^1.0.6, reflect.getprototypeof@^1.0.9: reflect.getprototypeof@^1.0.6, reflect.getprototypeof@^1.0.9:
version "1.0.10" version "1.0.10"
resolved "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.10.tgz" resolved "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.10.tgz"
@@ -3107,16 +3190,7 @@ resolve-pkg-maps@^1.0.0:
resolved "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz" resolved "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz"
integrity sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw== integrity sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==
resolve@^1.22.11: resolve@^1.22.4, resolve@^1.22.8:
version "1.22.11"
resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.11.tgz#aad857ce1ffb8bfa9b0b1ac29f1156383f68c262"
integrity sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ==
dependencies:
is-core-module "^2.16.1"
path-parse "^1.0.7"
supports-preserve-symlinks-flag "^1.0.0"
resolve@^1.22.4:
version "1.22.8" version "1.22.8"
resolved "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz" resolved "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz"
integrity sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw== integrity sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==
@@ -3146,6 +3220,11 @@ safe-array-concat@^1.1.3:
has-symbols "^1.1.0" has-symbols "^1.1.0"
isarray "^2.0.5" isarray "^2.0.5"
safe-identifier@^0.4.2:
version "0.4.2"
resolved "https://registry.npmjs.org/safe-identifier/-/safe-identifier-0.4.2.tgz"
integrity sha512-6pNbSMW6OhAi9j+N8V+U715yBQsaWJ7eyEUaOrawX+isg5ZxhUlV1NipNtgaKHmFGiABwt+ZF04Ii+3Xjkg+8w==
safe-push-apply@^1.0.0: safe-push-apply@^1.0.0:
version "1.0.0" version "1.0.0"
resolved "https://registry.npmjs.org/safe-push-apply/-/safe-push-apply-1.0.0.tgz" resolved "https://registry.npmjs.org/safe-push-apply/-/safe-push-apply-1.0.0.tgz"
@@ -3172,7 +3251,7 @@ safe-regex-test@^1.1.0:
es-errors "^1.3.0" es-errors "^1.3.0"
is-regex "^1.2.1" is-regex "^1.2.1"
sass@1.97.2, sass@^1.97.2: sass@1.97.2:
version "1.97.2" version "1.97.2"
resolved "https://registry.yarnpkg.com/sass/-/sass-1.97.2.tgz#e515a319092fd2c3b015228e3094b40198bff0da" resolved "https://registry.yarnpkg.com/sass/-/sass-1.97.2.tgz#e515a319092fd2c3b015228e3094b40198bff0da"
integrity sha512-y5LWb0IlbO4e97Zr7c3mlpabcbBtS+ieiZ9iwDooShpFKWXf62zz5pEPdwrLYm+Bxn1fnbwFGzHuCLSA9tBmrw== integrity sha512-y5LWb0IlbO4e97Zr7c3mlpabcbBtS+ieiZ9iwDooShpFKWXf62zz5pEPdwrLYm+Bxn1fnbwFGzHuCLSA9tBmrw==
@@ -3183,6 +3262,15 @@ sass@1.97.2, sass@^1.97.2:
optionalDependencies: optionalDependencies:
"@parcel/watcher" "^2.4.1" "@parcel/watcher" "^2.4.1"
sass@^1.71.1:
version "1.77.8"
resolved "https://registry.npmjs.org/sass/-/sass-1.77.8.tgz"
integrity sha512-4UHg6prsrycW20fqLGPShtEvo/WyHRVRHwOP4DzkUrObWoWI05QBSfzU71TVB7PFaL104TwNaHpjlWXAZbQiNQ==
dependencies:
chokidar ">=3.0.0 <4.0.0"
immutable "^4.0.0"
source-map-js ">=0.6.2 <2.0.0"
scheduler@^0.23.2: scheduler@^0.23.2:
version "0.23.2" version "0.23.2"
resolved "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz" resolved "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz"
@@ -3200,7 +3288,12 @@ semver@^6.3.1:
resolved "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz" resolved "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz"
integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==
semver@^7.7.1, semver@^7.7.3: semver@^7.6.0:
version "7.7.2"
resolved "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz"
integrity sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==
semver@^7.7.1:
version "7.7.3" version "7.7.3"
resolved "https://registry.yarnpkg.com/semver/-/semver-7.7.3.tgz#4b5f4143d007633a8dc671cd0a6ef9147b8bb946" resolved "https://registry.yarnpkg.com/semver/-/semver-7.7.3.tgz#4b5f4143d007633a8dc671cd0a6ef9147b8bb946"
integrity sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q== integrity sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==
@@ -3402,10 +3495,10 @@ supports-preserve-symlinks-flag@^1.0.0:
resolved "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz" resolved "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz"
integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==
synckit@^0.11.12: synckit@^0.11.7:
version "0.11.12" version "0.11.11"
resolved "https://registry.yarnpkg.com/synckit/-/synckit-0.11.12.tgz#abe74124264fbc00a48011b0d98bdc1cffb64a7b" resolved "https://registry.npmjs.org/synckit/-/synckit-0.11.11.tgz"
integrity sha512-Bh7QjT8/SuKUIfObSXNHNSK6WHo6J1tHCqJsuaFDP7gP0fkzSfTxI8y85JrppZ0h8l0maIgc2tfuZQ6/t3GtnQ== integrity sha512-MeQTA1r0litLUf0Rp/iisCaL8761lKAZHaimlbGK4j0HysC4PLfqygQj9srcs0m2RdtDYnF8UuYyKpbjHYp7Jw==
dependencies: dependencies:
"@pkgr/core" "^0.2.9" "@pkgr/core" "^0.2.9"
@@ -3447,10 +3540,10 @@ tom-select@2.4.3:
"@orchidjs/sifter" "^1.1.0" "@orchidjs/sifter" "^1.1.0"
"@orchidjs/unicode-variants" "^1.1.2" "@orchidjs/unicode-variants" "^1.1.2"
ts-api-utils@^2.4.0: ts-api-utils@^2.1.0:
version "2.4.0" version "2.1.0"
resolved "https://registry.yarnpkg.com/ts-api-utils/-/ts-api-utils-2.4.0.tgz#2690579f96d2790253bdcf1ca35d569ad78f9ad8" resolved "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.1.0.tgz"
integrity sha512-3TaVTaAv2gTiMB35i3FiGJaRfwb3Pyn/j3m/bfAvGe8FB7CF6u+LMYqYlDh7reQf7UNvoTvdfAqHGmPGOSsPmA== integrity sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ==
tsconfig-paths@^3.15.0: tsconfig-paths@^3.15.0:
version "3.15.0" version "3.15.0"

View File

@@ -1,3 +1,3 @@
version: "4.5.1" version: "4.5.0"
edition: "Community" edition: "Community"
published: "2026-01-20" published: "2026-01-06"

View File

@@ -38,81 +38,83 @@
</thead> </thead>
<tbody> <tbody>
{% for script in scripts %} {% for script in scripts %}
{% with last_job=script.get_latest_jobs|first %} {% if script in available_scripts %}
<tr> {% with last_job=script.get_latest_jobs|first %}
<td> <tr>
{% if script.is_executable %} <td>
<a href="{% url 'extras:script' script.pk %}" id="{{ script.module }}.{{ script.class_name }}">{{ script.python_class.name }}</a> {% if script.is_executable %}
<a href="{% url 'extras:script' script.pk %}" id="{{ script.module }}.{{ script.class_name }}">{{ script.python_class.name }}</a>
{% else %}
<a href="{% url 'extras:script_jobs' script.pk %}" id="{{ script.module }}.{{ script.class_name }}">{{ script.python_class.name }}</a>
<span class="text-danger">
<i class="mdi mdi-alert" title="{% trans "Script is no longer present in the source file" %}"></i>
</span>
{% endif %}
</td>
<td>{{ script.python_class.description|markdown|placeholder }}</td>
{% if last_job %}
<td>
<a href="{% url 'extras:script_result' job_pk=last_job.pk %}">{{ last_job.created|isodatetime }}</a>
</td>
<td>
{% badge last_job.get_status_display last_job.get_status_color %}
</td>
{% else %} {% else %}
<a href="{% url 'extras:script_jobs' script.pk %}" id="{{ script.module }}.{{ script.class_name }}">{{ script.python_class.name }}</a> <td class="text-muted">{% trans "Never" %}</td>
<span class="text-danger"> <td>{{ ''|placeholder }}</td>
<i class="mdi mdi-alert" title="{% trans "Script is no longer present in the source file" %}"></i>
</span>
{% endif %} {% endif %}
</td>
<td>{{ script.python_class.description|markdown|placeholder }}</td>
{% if last_job %}
<td> <td>
<a href="{% url 'extras:script_result' job_pk=last_job.pk %}">{{ last_job.created|isodatetime }}</a> {% if request.user|can_run:script and script.is_executable %}
</td> <div class="float-end d-print-none">
<td> <form action="{% url 'extras:script' script.pk %}" method="post">
{% badge last_job.get_status_display last_job.get_status_color %} {% if script.python_class.commit_default %}
</td> <input type="checkbox" name="_commit" hidden checked>
{% else %}
<td class="text-muted">{% trans "Never" %}</td>
<td>{{ ''|placeholder }}</td>
{% endif %}
<td>
{% if request.user|can_run:script and script.is_executable %}
<div class="float-end d-print-none">
<form action="{% url 'extras:script' script.pk %}" method="post">
{% if script.python_class.commit_default %}
<input type="checkbox" name="_commit" hidden checked>
{% endif %}
{% csrf_token %}
<button type="submit" name="_run" class="btn btn-primary{% if embedded %} btn-sm{% endif %}">
{% if last_job %}
<i class="mdi mdi-replay"></i> {% if not embedded %}{% trans "Run Again" %}{% endif %}
{% else %}
<i class="mdi mdi-play"></i> {% if not embedded %}{% trans "Run Script" %}{% endif %}
{% endif %} {% endif %}
</button> {% csrf_token %}
</form> <button type="submit" name="_run" class="btn btn-primary{% if embedded %} btn-sm{% endif %}">
</div> {% if last_job %}
{% endif %} <i class="mdi mdi-replay"></i> {% if not embedded %}{% trans "Run Again" %}{% endif %}
</td> {% else %}
</tr> <i class="mdi mdi-play"></i> {% if not embedded %}{% trans "Run Script" %}{% endif %}
{% if last_job and not embedded %} {% endif %}
{% for test_name, data in last_job.data.tests.items %} </button>
<tr> </form>
<td colspan="4" class="method"> </div>
<span class="ps-3">{{ test_name }}</span> {% endif %}
</td> </td>
<td class="text-end text-nowrap script-stats"> </tr>
<span class="badge text-bg-success">{{ data.success }}</span> {% if last_job and not embedded %}
<span class="badge text-bg-info">{{ data.info }}</span> {% for test_name, data in last_job.data.tests.items %}
<span class="badge text-bg-warning">{{ data.warning }}</span> <tr>
<span class="badge text-bg-danger">{{ data.failure }}</span> <td colspan="4" class="method">
</td> <span class="ps-3">{{ test_name }}</span>
</tr> </td>
{% endfor %} <td class="text-end text-nowrap script-stats">
{% elif last_job and not last_job.data.log and not embedded %} <span class="badge text-bg-success">{{ data.success }}</span>
{# legacy #} <span class="badge text-bg-info">{{ data.info }}</span>
{% for method, stats in last_job.data.items %} <span class="badge text-bg-warning">{{ data.warning }}</span>
<tr> <span class="badge text-bg-danger">{{ data.failure }}</span>
<td colspan="4" class="method"> </td>
<span class="ps-3">{{ method }}</span> </tr>
</td> {% endfor %}
<td class="text-end text-nowrap report-stats"> {% elif last_job and not last_job.data.log and not embedded %}
<span class="badge bg-success">{{ stats.success }}</span> {# legacy #}
<span class="badge bg-info">{{ stats.info }}</span> {% for method, stats in last_job.data.items %}
<span class="badge bg-warning">{{ stats.warning }}</span> <tr>
<span class="badge bg-danger">{{ stats.failure }}</span> <td colspan="4" class="method">
</td> <span class="ps-3">{{ method }}</span>
</tr> </td>
{% endfor %} <td class="text-end text-nowrap report-stats">
{% endif %} <span class="badge bg-success">{{ stats.success }}</span>
{% endwith %} <span class="badge bg-info">{{ stats.info }}</span>
<span class="badge bg-warning">{{ stats.warning }}</span>
<span class="badge bg-danger">{{ stats.failure }}</span>
</td>
</tr>
{% endfor %}
{% endif %}
{% endwith %}
{% endif %}
{% endfor %} {% endfor %}
</tbody> </tbody>
</table> </table>

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -8,7 +8,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: PACKAGE VERSION\n" "Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2026-01-20 05:07+0000\n" "POT-Creation-Date: 2026-01-17 05:02+0000\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n" "Language-Team: LANGUAGE <LL@li.org>\n"
@@ -1279,7 +1279,7 @@ msgid "Term Side"
msgstr "" msgstr ""
#: netbox/circuits/forms/filtersets.py:287 netbox/dcim/forms/bulk_edit.py:1537 #: netbox/circuits/forms/filtersets.py:287 netbox/dcim/forms/bulk_edit.py:1537
#: netbox/extras/forms/model_forms.py:697 netbox/ipam/forms/filtersets.py:149 #: netbox/extras/forms/model_forms.py:696 netbox/ipam/forms/filtersets.py:149
#: netbox/ipam/forms/filtersets.py:627 netbox/ipam/forms/model_forms.py:326 #: netbox/ipam/forms/filtersets.py:627 netbox/ipam/forms/model_forms.py:326
#: netbox/templates/dcim/macaddress.html:25 #: netbox/templates/dcim/macaddress.html:25
#: netbox/templates/extras/configcontext.html:36 #: netbox/templates/extras/configcontext.html:36
@@ -2172,7 +2172,7 @@ msgstr ""
msgid "Sync interval" msgid "Sync interval"
msgstr "" msgstr ""
#: netbox/core/forms/bulk_edit.py:33 netbox/extras/forms/model_forms.py:307 #: netbox/core/forms/bulk_edit.py:33 netbox/extras/forms/model_forms.py:306
#: netbox/templates/extras/savedfilter.html:56 #: netbox/templates/extras/savedfilter.html:56
#: netbox/vpn/forms/filtersets.py:102 netbox/vpn/forms/filtersets.py:132 #: netbox/vpn/forms/filtersets.py:102 netbox/vpn/forms/filtersets.py:132
#: netbox/vpn/forms/filtersets.py:156 netbox/vpn/forms/filtersets.py:175 #: netbox/vpn/forms/filtersets.py:156 netbox/vpn/forms/filtersets.py:175
@@ -2187,10 +2187,10 @@ msgid "Ignore rules"
msgstr "" msgstr ""
#: netbox/core/forms/filtersets.py:30 netbox/core/forms/model_forms.py:100 #: netbox/core/forms/filtersets.py:30 netbox/core/forms/model_forms.py:100
#: netbox/extras/forms/model_forms.py:268 #: netbox/extras/forms/model_forms.py:267
#: netbox/extras/forms/model_forms.py:604 #: netbox/extras/forms/model_forms.py:603
#: netbox/extras/forms/model_forms.py:693 #: netbox/extras/forms/model_forms.py:692
#: netbox/extras/forms/model_forms.py:746 netbox/extras/tables/tables.py:218 #: netbox/extras/forms/model_forms.py:745 netbox/extras/tables/tables.py:218
#: netbox/extras/tables/tables.py:588 netbox/extras/tables/tables.py:618 #: netbox/extras/tables/tables.py:588 netbox/extras/tables/tables.py:618
#: netbox/extras/tables/tables.py:660 netbox/templates/core/datasource.html:31 #: netbox/extras/tables/tables.py:660 netbox/templates/core/datasource.html:31
#: netbox/templates/core/inc/datafile_panel.html:7 #: netbox/templates/core/inc/datafile_panel.html:7
@@ -2290,7 +2290,7 @@ msgid "Before"
msgstr "" msgstr ""
#: netbox/core/forms/filtersets.py:155 netbox/core/tables/change_logging.py:29 #: netbox/core/forms/filtersets.py:155 netbox/core/tables/change_logging.py:29
#: netbox/extras/forms/model_forms.py:477 #: netbox/extras/forms/model_forms.py:476
#: netbox/templates/core/objectchange.html:46 #: netbox/templates/core/objectchange.html:46
#: netbox/templates/extras/eventrule.html:71 #: netbox/templates/extras/eventrule.html:71
msgid "Action" msgid "Action"
@@ -2360,8 +2360,8 @@ msgid "Pagination"
msgstr "" msgstr ""
#: netbox/core/forms/model_forms.py:166 netbox/extras/forms/bulk_edit.py:96 #: netbox/core/forms/model_forms.py:166 netbox/extras/forms/bulk_edit.py:96
#: netbox/extras/forms/filtersets.py:49 netbox/extras/forms/model_forms.py:122 #: netbox/extras/forms/filtersets.py:49 netbox/extras/forms/model_forms.py:121
#: netbox/extras/forms/model_forms.py:135 #: netbox/extras/forms/model_forms.py:134
#: netbox/templates/core/inc/config_data.html:93 #: netbox/templates/core/inc/config_data.html:93
msgid "Validation" msgid "Validation"
msgstr "" msgstr ""
@@ -4176,9 +4176,9 @@ msgid "Power panel (ID)"
msgstr "" msgstr ""
#: netbox/dcim/forms/bulk_create.py:40 netbox/extras/forms/filtersets.py:515 #: netbox/dcim/forms/bulk_create.py:40 netbox/extras/forms/filtersets.py:515
#: netbox/extras/forms/model_forms.py:597 #: netbox/extras/forms/model_forms.py:596
#: netbox/extras/forms/model_forms.py:682 #: netbox/extras/forms/model_forms.py:681
#: netbox/extras/forms/model_forms.py:734 netbox/extras/ui/panels.py:69 #: netbox/extras/forms/model_forms.py:733 netbox/extras/ui/panels.py:69
#: netbox/netbox/forms/bulk_import.py:26 netbox/netbox/forms/mixins.py:113 #: netbox/netbox/forms/bulk_import.py:26 netbox/netbox/forms/mixins.py:113
#: netbox/netbox/tables/columns.py:490 #: netbox/netbox/tables/columns.py:490
#: netbox/templates/circuits/inc/circuit_termination.html:29 #: netbox/templates/circuits/inc/circuit_termination.html:29
@@ -4319,7 +4319,7 @@ msgstr ""
#: netbox/extras/forms/bulk_edit.py:315 netbox/extras/forms/bulk_edit.py:341 #: netbox/extras/forms/bulk_edit.py:315 netbox/extras/forms/bulk_edit.py:341
#: netbox/extras/forms/bulk_import.py:275 netbox/extras/forms/filtersets.py:71 #: netbox/extras/forms/bulk_import.py:275 netbox/extras/forms/filtersets.py:71
#: netbox/extras/forms/filtersets.py:175 netbox/extras/forms/filtersets.py:279 #: netbox/extras/forms/filtersets.py:175 netbox/extras/forms/filtersets.py:279
#: netbox/extras/forms/filtersets.py:315 netbox/extras/forms/model_forms.py:575 #: netbox/extras/forms/filtersets.py:315 netbox/extras/forms/model_forms.py:574
#: netbox/ipam/forms/bulk_edit.py:159 netbox/templates/dcim/moduletype.html:51 #: netbox/ipam/forms/bulk_edit.py:159 netbox/templates/dcim/moduletype.html:51
#: netbox/templates/extras/configcontext.html:17 #: netbox/templates/extras/configcontext.html:17
#: netbox/templates/extras/customlink.html:25 #: netbox/templates/extras/customlink.html:25
@@ -4455,7 +4455,7 @@ msgid "Device Type"
msgstr "" msgstr ""
#: netbox/dcim/forms/bulk_edit.py:540 netbox/dcim/forms/model_forms.py:400 #: netbox/dcim/forms/bulk_edit.py:540 netbox/dcim/forms/model_forms.py:400
#: netbox/dcim/views.py:1578 netbox/extras/forms/model_forms.py:592 #: netbox/dcim/views.py:1578 netbox/extras/forms/model_forms.py:591
msgid "Schema" msgid "Schema"
msgstr "" msgstr ""
@@ -4464,7 +4464,7 @@ msgstr ""
#: netbox/dcim/forms/bulk_import.py:1452 netbox/dcim/forms/filtersets.py:679 #: netbox/dcim/forms/bulk_import.py:1452 netbox/dcim/forms/filtersets.py:679
#: netbox/dcim/forms/filtersets.py:1197 netbox/dcim/forms/model_forms.py:406 #: netbox/dcim/forms/filtersets.py:1197 netbox/dcim/forms/model_forms.py:406
#: netbox/dcim/forms/model_forms.py:419 netbox/dcim/tables/modules.py:42 #: netbox/dcim/forms/model_forms.py:419 netbox/dcim/tables/modules.py:42
#: netbox/extras/forms/filtersets.py:437 netbox/extras/forms/model_forms.py:617 #: netbox/extras/forms/filtersets.py:437 netbox/extras/forms/model_forms.py:616
#: netbox/extras/tables/tables.py:615 netbox/templates/account/base.html:7 #: netbox/extras/tables/tables.py:615 netbox/templates/account/base.html:7
#: netbox/templates/dcim/cable.html:23 netbox/templates/dcim/moduletype.html:27 #: netbox/templates/dcim/cable.html:23 netbox/templates/dcim/moduletype.html:27
#: netbox/templates/extras/configcontext.html:21 #: netbox/templates/extras/configcontext.html:21
@@ -5600,7 +5600,7 @@ msgstr ""
#: netbox/dcim/forms/filtersets.py:1572 netbox/extras/forms/bulk_edit.py:421 #: netbox/dcim/forms/filtersets.py:1572 netbox/extras/forms/bulk_edit.py:421
#: netbox/extras/forms/bulk_import.py:298 netbox/extras/forms/filtersets.py:616 #: netbox/extras/forms/bulk_import.py:298 netbox/extras/forms/filtersets.py:616
#: netbox/extras/forms/model_forms.py:798 netbox/extras/tables/tables.py:743 #: netbox/extras/forms/model_forms.py:794 netbox/extras/tables/tables.py:743
#: netbox/templates/extras/journalentry.html:30 #: netbox/templates/extras/journalentry.html:30
msgid "Kind" msgid "Kind"
msgstr "" msgstr ""
@@ -5745,7 +5745,7 @@ msgid ""
"hyphen." "hyphen."
msgstr "" msgstr ""
#: netbox/dcim/forms/model_forms.py:402 netbox/extras/forms/model_forms.py:594 #: netbox/dcim/forms/model_forms.py:402 netbox/extras/forms/model_forms.py:593
msgid "Enter a valid JSON schema to define supported attributes." msgid "Enter a valid JSON schema to define supported attributes."
msgstr "" msgstr ""
@@ -7610,7 +7610,7 @@ msgid "VMs"
msgstr "" msgstr ""
#: netbox/dcim/tables/devices.py:103 netbox/dcim/tables/devices.py:223 #: netbox/dcim/tables/devices.py:103 netbox/dcim/tables/devices.py:223
#: netbox/extras/forms/model_forms.py:745 #: netbox/extras/forms/model_forms.py:744
#: netbox/templates/dcim/devicerole.html:48 #: netbox/templates/dcim/devicerole.html:48
#: netbox/templates/dcim/platform.html:45 #: netbox/templates/dcim/platform.html:45
#: netbox/templates/extras/configtemplate.html:10 #: netbox/templates/extras/configtemplate.html:10
@@ -7842,7 +7842,7 @@ msgid "Module Types"
msgstr "" msgstr ""
#: netbox/dcim/tables/devicetypes.py:57 netbox/extras/forms/filtersets.py:485 #: netbox/dcim/tables/devicetypes.py:57 netbox/extras/forms/filtersets.py:485
#: netbox/extras/forms/model_forms.py:652 netbox/extras/tables/tables.py:703 #: netbox/extras/forms/model_forms.py:651 netbox/extras/tables/tables.py:703
#: netbox/netbox/navigation/menu.py:78 #: netbox/netbox/navigation/menu.py:78
msgid "Platforms" msgid "Platforms"
msgstr "" msgstr ""
@@ -8000,7 +8000,7 @@ msgid "Space"
msgstr "" msgstr ""
#: netbox/dcim/tables/sites.py:21 netbox/dcim/tables/sites.py:40 #: netbox/dcim/tables/sites.py:21 netbox/dcim/tables/sites.py:40
#: netbox/extras/forms/filtersets.py:465 netbox/extras/forms/model_forms.py:632 #: netbox/extras/forms/filtersets.py:465 netbox/extras/forms/model_forms.py:631
#: netbox/ipam/forms/bulk_edit.py:112 netbox/ipam/forms/model_forms.py:154 #: netbox/ipam/forms/bulk_edit.py:112 netbox/ipam/forms/model_forms.py:154
#: netbox/ipam/tables/asn.py:76 netbox/netbox/navigation/menu.py:15 #: netbox/ipam/tables/asn.py:76 netbox/netbox/navigation/menu.py:15
#: netbox/netbox/navigation/menu.py:19 #: netbox/netbox/navigation/menu.py:19
@@ -8015,10 +8015,6 @@ msgstr ""
msgid "Test case must set peer_termination_type" msgid "Test case must set peer_termination_type"
msgstr "" msgstr ""
#: netbox/dcim/ui/panels.py:34
msgid "{} millimeters"
msgstr ""
#: netbox/dcim/ui/panels.py:53 netbox/dcim/ui/panels.py:96 #: netbox/dcim/ui/panels.py:53 netbox/dcim/ui/panels.py:96
#: netbox/virtualization/forms/filtersets.py:198 #: netbox/virtualization/forms/filtersets.py:198
msgid "Serial number" msgid "Serial number"
@@ -8083,7 +8079,7 @@ msgid "Application Services"
msgstr "" msgstr ""
#: netbox/dcim/views.py:2677 netbox/extras/forms/filtersets.py:427 #: netbox/dcim/views.py:2677 netbox/extras/forms/filtersets.py:427
#: netbox/extras/forms/model_forms.py:692 #: netbox/extras/forms/model_forms.py:691
#: netbox/templates/extras/configcontext.html:10 #: netbox/templates/extras/configcontext.html:10
#: netbox/virtualization/forms/model_forms.py:225 #: netbox/virtualization/forms/model_forms.py:225
#: netbox/virtualization/views.py:399 #: netbox/virtualization/views.py:399
@@ -8319,13 +8315,13 @@ msgstr ""
msgid "White" msgid "White"
msgstr "" msgstr ""
#: netbox/extras/choices.py:249 netbox/extras/forms/model_forms.py:434 #: netbox/extras/choices.py:249 netbox/extras/forms/model_forms.py:433
#: netbox/extras/forms/model_forms.py:511 #: netbox/extras/forms/model_forms.py:510
#: netbox/templates/extras/webhook.html:10 #: netbox/templates/extras/webhook.html:10
msgid "Webhook" msgid "Webhook"
msgstr "" msgstr ""
#: netbox/extras/choices.py:250 netbox/extras/forms/model_forms.py:499 #: netbox/extras/choices.py:250 netbox/extras/forms/model_forms.py:498
#: netbox/templates/extras/script/base.html:29 #: netbox/templates/extras/script/base.html:29
msgid "Script" msgid "Script"
msgstr "" msgstr ""
@@ -8505,7 +8501,7 @@ msgstr ""
msgid "Tenant group (slug)" msgid "Tenant group (slug)"
msgstr "" msgstr ""
#: netbox/extras/filtersets.py:779 netbox/extras/forms/model_forms.py:580 #: netbox/extras/filtersets.py:779 netbox/extras/forms/model_forms.py:579
#: netbox/templates/extras/tag.html:11 #: netbox/templates/extras/tag.html:11
msgid "Tag" msgid "Tag"
msgstr "" msgstr ""
@@ -8562,7 +8558,7 @@ msgid "Validation regex"
msgstr "" msgstr ""
#: netbox/extras/forms/bulk_edit.py:95 netbox/extras/forms/filtersets.py:48 #: netbox/extras/forms/bulk_edit.py:95 netbox/extras/forms/filtersets.py:48
#: netbox/extras/forms/model_forms.py:82 #: netbox/extras/forms/model_forms.py:81
#: netbox/templates/extras/customfield.html:70 #: netbox/templates/extras/customfield.html:70
msgid "Behavior" msgid "Behavior"
msgstr "" msgstr ""
@@ -8627,7 +8623,7 @@ msgid "CA file path"
msgstr "" msgstr ""
#: netbox/extras/forms/bulk_edit.py:289 netbox/extras/forms/bulk_import.py:231 #: netbox/extras/forms/bulk_edit.py:289 netbox/extras/forms/bulk_import.py:231
#: netbox/extras/forms/model_forms.py:458 #: netbox/extras/forms/model_forms.py:457
msgid "Event types" msgid "Event types"
msgstr "" msgstr ""
@@ -8646,12 +8642,12 @@ msgstr ""
#: netbox/extras/forms/bulk_import.py:225 #: netbox/extras/forms/bulk_import.py:225
#: netbox/extras/forms/bulk_import.py:279 netbox/extras/forms/filtersets.py:54 #: netbox/extras/forms/bulk_import.py:279 netbox/extras/forms/filtersets.py:54
#: netbox/extras/forms/filtersets.py:156 netbox/extras/forms/filtersets.py:260 #: netbox/extras/forms/filtersets.py:156 netbox/extras/forms/filtersets.py:260
#: netbox/extras/forms/filtersets.py:296 netbox/extras/forms/model_forms.py:53 #: netbox/extras/forms/filtersets.py:296 netbox/extras/forms/model_forms.py:52
#: netbox/extras/forms/model_forms.py:225 #: netbox/extras/forms/model_forms.py:224
#: netbox/extras/forms/model_forms.py:257 #: netbox/extras/forms/model_forms.py:256
#: netbox/extras/forms/model_forms.py:300 #: netbox/extras/forms/model_forms.py:299
#: netbox/extras/forms/model_forms.py:453 #: netbox/extras/forms/model_forms.py:452
#: netbox/extras/forms/model_forms.py:570 netbox/users/forms/model_forms.py:323 #: netbox/extras/forms/model_forms.py:569 netbox/users/forms/model_forms.py:323
msgid "Object types" msgid "Object types"
msgstr "" msgstr ""
@@ -8669,9 +8665,9 @@ msgid "Field data type (e.g. text, integer, etc.)"
msgstr "" msgstr ""
#: netbox/extras/forms/bulk_import.py:48 netbox/extras/forms/filtersets.py:243 #: netbox/extras/forms/bulk_import.py:48 netbox/extras/forms/filtersets.py:243
#: netbox/extras/forms/filtersets.py:356 netbox/extras/forms/model_forms.py:326 #: netbox/extras/forms/filtersets.py:356 netbox/extras/forms/model_forms.py:325
#: netbox/extras/forms/model_forms.py:385 #: netbox/extras/forms/model_forms.py:384
#: netbox/extras/forms/model_forms.py:422 #: netbox/extras/forms/model_forms.py:421
#: netbox/tenancy/forms/filtersets.py:111 #: netbox/tenancy/forms/filtersets.py:111
msgid "Object type" msgid "Object type"
msgstr "" msgstr ""
@@ -8737,8 +8733,8 @@ msgid ""
msgstr "" msgstr ""
#: netbox/extras/forms/bulk_import.py:195 #: netbox/extras/forms/bulk_import.py:195
#: netbox/extras/forms/model_forms.py:292 #: netbox/extras/forms/model_forms.py:291
#: netbox/extras/forms/model_forms.py:773 #: netbox/extras/forms/model_forms.py:772
msgid "Must specify either local content or a data file" msgid "Must specify either local content or a data file"
msgstr "" msgstr ""
@@ -8783,7 +8779,7 @@ msgid "Comments"
msgstr "" msgstr ""
#: netbox/extras/forms/bulk_import.py:316 #: netbox/extras/forms/bulk_import.py:316
#: netbox/extras/forms/model_forms.py:401 netbox/netbox/navigation/menu.py:414 #: netbox/extras/forms/model_forms.py:400 netbox/netbox/navigation/menu.py:414
#: netbox/templates/extras/notificationgroup.html:41 #: netbox/templates/extras/notificationgroup.html:41
#: netbox/templates/users/group.html:29 netbox/templates/users/owner.html:46 #: netbox/templates/users/group.html:29 netbox/templates/users/owner.html:46
#: netbox/users/forms/filtersets.py:181 netbox/users/forms/model_forms.py:262 #: netbox/users/forms/filtersets.py:181 netbox/users/forms/model_forms.py:262
@@ -8798,7 +8794,7 @@ msgid "User names separated by commas, encased with double quotes"
msgstr "" msgstr ""
#: netbox/extras/forms/bulk_import.py:323 #: netbox/extras/forms/bulk_import.py:323
#: netbox/extras/forms/model_forms.py:396 netbox/netbox/navigation/menu.py:295 #: netbox/extras/forms/model_forms.py:395 netbox/netbox/navigation/menu.py:295
#: netbox/netbox/navigation/menu.py:434 #: netbox/netbox/navigation/menu.py:434
#: netbox/templates/extras/notificationgroup.html:31 #: netbox/templates/extras/notificationgroup.html:31
#: netbox/templates/tenancy/contact.html:21 #: netbox/templates/tenancy/contact.html:21
@@ -8820,7 +8816,7 @@ msgstr ""
msgid "Type Options" msgid "Type Options"
msgstr "" msgstr ""
#: netbox/extras/forms/filtersets.py:59 netbox/extras/forms/model_forms.py:62 #: netbox/extras/forms/filtersets.py:59 netbox/extras/forms/model_forms.py:61
msgid "Related object type" msgid "Related object type"
msgstr "" msgstr ""
@@ -8828,7 +8824,7 @@ msgstr ""
msgid "Field type" msgid "Field type"
msgstr "" msgstr ""
#: netbox/extras/forms/filtersets.py:133 netbox/extras/forms/model_forms.py:163 #: netbox/extras/forms/filtersets.py:133 netbox/extras/forms/model_forms.py:162
#: netbox/extras/tables/tables.py:97 #: netbox/extras/tables/tables.py:97
#: netbox/templates/generic/bulk_import.html:185 #: netbox/templates/generic/bulk_import.html:185
msgid "Choices" msgid "Choices"
@@ -8836,14 +8832,14 @@ msgstr ""
#: netbox/extras/forms/filtersets.py:189 netbox/extras/forms/filtersets.py:406 #: netbox/extras/forms/filtersets.py:189 netbox/extras/forms/filtersets.py:406
#: netbox/extras/forms/filtersets.py:428 netbox/extras/forms/filtersets.py:528 #: netbox/extras/forms/filtersets.py:428 netbox/extras/forms/filtersets.py:528
#: netbox/extras/forms/model_forms.py:687 netbox/templates/core/job.html:69 #: netbox/extras/forms/model_forms.py:686 netbox/templates/core/job.html:69
#: netbox/templates/extras/eventrule.html:84 #: netbox/templates/extras/eventrule.html:84
msgid "Data" msgid "Data"
msgstr "" msgstr ""
#: netbox/extras/forms/filtersets.py:190 netbox/extras/forms/filtersets.py:529 #: netbox/extras/forms/filtersets.py:190 netbox/extras/forms/filtersets.py:529
#: netbox/extras/forms/model_forms.py:270 #: netbox/extras/forms/model_forms.py:269
#: netbox/extras/forms/model_forms.py:748 #: netbox/extras/forms/model_forms.py:747
msgid "Rendering" msgid "Rendering"
msgstr "" msgstr ""
@@ -8871,37 +8867,37 @@ msgstr ""
msgid "Allowed object type" msgid "Allowed object type"
msgstr "" msgstr ""
#: netbox/extras/forms/filtersets.py:455 netbox/extras/forms/model_forms.py:622 #: netbox/extras/forms/filtersets.py:455 netbox/extras/forms/model_forms.py:621
#: netbox/netbox/navigation/menu.py:17 #: netbox/netbox/navigation/menu.py:17
msgid "Regions" msgid "Regions"
msgstr "" msgstr ""
#: netbox/extras/forms/filtersets.py:460 netbox/extras/forms/model_forms.py:627 #: netbox/extras/forms/filtersets.py:460 netbox/extras/forms/model_forms.py:626
msgid "Site groups" msgid "Site groups"
msgstr "" msgstr ""
#: netbox/extras/forms/filtersets.py:470 netbox/extras/forms/model_forms.py:637 #: netbox/extras/forms/filtersets.py:470 netbox/extras/forms/model_forms.py:636
#: netbox/netbox/navigation/menu.py:20 #: netbox/netbox/navigation/menu.py:20
msgid "Locations" msgid "Locations"
msgstr "" msgstr ""
#: netbox/extras/forms/filtersets.py:475 netbox/extras/forms/model_forms.py:642 #: netbox/extras/forms/filtersets.py:475 netbox/extras/forms/model_forms.py:641
msgid "Device types" msgid "Device types"
msgstr "" msgstr ""
#: netbox/extras/forms/filtersets.py:480 netbox/extras/forms/model_forms.py:647 #: netbox/extras/forms/filtersets.py:480 netbox/extras/forms/model_forms.py:646
msgid "Roles" msgid "Roles"
msgstr "" msgstr ""
#: netbox/extras/forms/filtersets.py:490 netbox/extras/forms/model_forms.py:657 #: netbox/extras/forms/filtersets.py:490 netbox/extras/forms/model_forms.py:656
msgid "Cluster types" msgid "Cluster types"
msgstr "" msgstr ""
#: netbox/extras/forms/filtersets.py:495 netbox/extras/forms/model_forms.py:662 #: netbox/extras/forms/filtersets.py:495 netbox/extras/forms/model_forms.py:661
msgid "Cluster groups" msgid "Cluster groups"
msgstr "" msgstr ""
#: netbox/extras/forms/filtersets.py:500 netbox/extras/forms/model_forms.py:667 #: netbox/extras/forms/filtersets.py:500 netbox/extras/forms/model_forms.py:666
#: netbox/netbox/navigation/menu.py:264 netbox/netbox/navigation/menu.py:266 #: netbox/netbox/navigation/menu.py:264 netbox/netbox/navigation/menu.py:266
#: netbox/templates/virtualization/clustertype.html:30 #: netbox/templates/virtualization/clustertype.html:30
#: netbox/virtualization/tables/clusters.py:23 #: netbox/virtualization/tables/clusters.py:23
@@ -8909,179 +8905,183 @@ msgstr ""
msgid "Clusters" msgid "Clusters"
msgstr "" msgstr ""
#: netbox/extras/forms/filtersets.py:505 netbox/extras/forms/model_forms.py:672 #: netbox/extras/forms/filtersets.py:505 netbox/extras/forms/model_forms.py:671
msgid "Tenant groups" msgid "Tenant groups"
msgstr "" msgstr ""
#: netbox/extras/forms/model_forms.py:55 #: netbox/extras/forms/model_forms.py:54
msgid "The type(s) of object that have this custom field" msgid "The type(s) of object that have this custom field"
msgstr "" msgstr ""
#: netbox/extras/forms/model_forms.py:58 #: netbox/extras/forms/model_forms.py:57
msgid "Default value" msgid "Default value"
msgstr "" msgstr ""
#: netbox/extras/forms/model_forms.py:64 #: netbox/extras/forms/model_forms.py:63
msgid "Type of the related object (for object/multi-object fields only)" msgid "Type of the related object (for object/multi-object fields only)"
msgstr "" msgstr ""
#: netbox/extras/forms/model_forms.py:67 #: netbox/extras/forms/model_forms.py:66
#: netbox/templates/extras/customfield.html:60 #: netbox/templates/extras/customfield.html:60
msgid "Related object filter" msgid "Related object filter"
msgstr "" msgstr ""
#: netbox/extras/forms/model_forms.py:69 #: netbox/extras/forms/model_forms.py:68
msgid "Specify query parameters as a JSON object." msgid "Specify query parameters as a JSON object."
msgstr "" msgstr ""
#: netbox/extras/forms/model_forms.py:79 #: netbox/extras/forms/model_forms.py:78
#: netbox/templates/extras/customfield.html:10 #: netbox/templates/extras/customfield.html:10
msgid "Custom Field" msgid "Custom Field"
msgstr "" msgstr ""
#: netbox/extras/forms/model_forms.py:91 #: netbox/extras/forms/model_forms.py:90
msgid "" msgid ""
"The type of data stored in this field. For object/multi-object fields, " "The type of data stored in this field. For object/multi-object fields, "
"select the related object type below." "select the related object type below."
msgstr "" msgstr ""
#: netbox/extras/forms/model_forms.py:94 #: netbox/extras/forms/model_forms.py:93
msgid "" msgid ""
"This will be displayed as help text for the form field. Markdown is " "This will be displayed as help text for the form field. Markdown is "
"supported." "supported."
msgstr "" msgstr ""
#: netbox/extras/forms/model_forms.py:149 #: netbox/extras/forms/model_forms.py:148
msgid "Related Object" msgid "Related Object"
msgstr "" msgstr ""
#: netbox/extras/forms/model_forms.py:176 #: netbox/extras/forms/model_forms.py:175
msgid "" msgid ""
"Enter one choice per line. An optional label may be specified for each " "Enter one choice per line. An optional label may be specified for each "
"choice by appending it with a colon. Example:" "choice by appending it with a colon. Example:"
msgstr "" msgstr ""
#: netbox/extras/forms/model_forms.py:232 #: netbox/extras/forms/model_forms.py:231
#: netbox/templates/extras/customlink.html:10 #: netbox/templates/extras/customlink.html:10
msgid "Custom Link" msgid "Custom Link"
msgstr "" msgstr ""
#: netbox/extras/forms/model_forms.py:234 #: netbox/extras/forms/model_forms.py:233
msgid "Templates" msgid "Templates"
msgstr "" msgstr ""
#: netbox/extras/forms/model_forms.py:246 #: netbox/extras/forms/model_forms.py:245
#, python-brace-format #, python-brace-format
msgid "" msgid ""
"Jinja2 template code for the link text. Reference the object as {example}. " "Jinja2 template code for the link text. Reference the object as {example}. "
"Links which render as empty text will not be displayed." "Links which render as empty text will not be displayed."
msgstr "" msgstr ""
#: netbox/extras/forms/model_forms.py:250 #: netbox/extras/forms/model_forms.py:249
#, python-brace-format #, python-brace-format
msgid "" msgid ""
"Jinja2 template code for the link URL. Reference the object as {example}." "Jinja2 template code for the link URL. Reference the object as {example}."
msgstr "" msgstr ""
#: netbox/extras/forms/model_forms.py:261 #: netbox/extras/forms/model_forms.py:260
#: netbox/extras/forms/model_forms.py:739 #: netbox/extras/forms/model_forms.py:738
msgid "Template code" msgid "Template code"
msgstr "" msgstr ""
#: netbox/extras/forms/model_forms.py:267 #: netbox/extras/forms/model_forms.py:266
#: netbox/templates/extras/exporttemplate.html:12 #: netbox/templates/extras/exporttemplate.html:12
msgid "Export Template" msgid "Export Template"
msgstr "" msgstr ""
#: netbox/extras/forms/model_forms.py:285 #: netbox/extras/forms/model_forms.py:284
#: netbox/extras/forms/model_forms.py:766 #: netbox/extras/forms/model_forms.py:765
msgid "Template content is populated from the remote source selected below." msgid "Template content is populated from the remote source selected below."
msgstr "" msgstr ""
#: netbox/extras/forms/model_forms.py:306 netbox/netbox/forms/mixins.py:92 #: netbox/extras/forms/model_forms.py:305 netbox/netbox/forms/mixins.py:92
#: netbox/templates/extras/savedfilter.html:10 #: netbox/templates/extras/savedfilter.html:10
msgid "Saved Filter" msgid "Saved Filter"
msgstr "" msgstr ""
#: netbox/extras/forms/model_forms.py:332 #: netbox/extras/forms/model_forms.py:331
#: netbox/templates/account/preferences.html:50 #: netbox/templates/account/preferences.html:50
#: netbox/templates/extras/tableconfig.html:62 #: netbox/templates/extras/tableconfig.html:62
msgid "Ordering" msgid "Ordering"
msgstr "" msgstr ""
#: netbox/extras/forms/model_forms.py:334 #: netbox/extras/forms/model_forms.py:333
msgid "" msgid ""
"Enter a comma-separated list of column names. Prepend a name with a hyphen " "Enter a comma-separated list of column names. Prepend a name with a hyphen "
"to reverse the order." "to reverse the order."
msgstr "" msgstr ""
#: netbox/extras/forms/model_forms.py:343 netbox/utilities/forms/forms.py:164 #: netbox/extras/forms/model_forms.py:342 netbox/utilities/forms/forms.py:164
msgid "Available Columns" msgid "Available Columns"
msgstr "" msgstr ""
#: netbox/extras/forms/model_forms.py:350 netbox/utilities/forms/forms.py:172 #: netbox/extras/forms/model_forms.py:349 netbox/utilities/forms/forms.py:172
msgid "Selected Columns" msgid "Selected Columns"
msgstr "" msgstr ""
#: netbox/extras/forms/model_forms.py:415 #: netbox/extras/forms/model_forms.py:414
msgid "A notification group specify at least one user or group." msgid "A notification group specify at least one user or group."
msgstr "" msgstr ""
#: netbox/extras/forms/model_forms.py:437 #: netbox/extras/forms/model_forms.py:436
#: netbox/templates/extras/webhook.html:23 #: netbox/templates/extras/webhook.html:23
msgid "HTTP Request" msgid "HTTP Request"
msgstr "" msgstr ""
#: netbox/extras/forms/model_forms.py:439 #: netbox/extras/forms/model_forms.py:438
#: netbox/templates/extras/webhook.html:44 #: netbox/templates/extras/webhook.html:44
msgid "SSL" msgid "SSL"
msgstr "" msgstr ""
#: netbox/extras/forms/model_forms.py:461 #: netbox/extras/forms/model_forms.py:460
msgid "Action choice" msgid "Action choice"
msgstr "" msgstr ""
#: netbox/extras/forms/model_forms.py:466 #: netbox/extras/forms/model_forms.py:465
msgid "Enter conditions in <a href=\"https://json.org/\">JSON</a> format." msgid "Enter conditions in <a href=\"https://json.org/\">JSON</a> format."
msgstr "" msgstr ""
#: netbox/extras/forms/model_forms.py:470 #: netbox/extras/forms/model_forms.py:469
msgid "" msgid ""
"Enter parameters to pass to the action in <a href=\"https://json.org/" "Enter parameters to pass to the action in <a href=\"https://json.org/"
"\">JSON</a> format." "\">JSON</a> format."
msgstr "" msgstr ""
#: netbox/extras/forms/model_forms.py:475 #: netbox/extras/forms/model_forms.py:474
#: netbox/templates/extras/eventrule.html:10 #: netbox/templates/extras/eventrule.html:10
msgid "Event Rule" msgid "Event Rule"
msgstr "" msgstr ""
#: netbox/extras/forms/model_forms.py:476 #: netbox/extras/forms/model_forms.py:475
msgid "Triggers" msgid "Triggers"
msgstr "" msgstr ""
#: netbox/extras/forms/model_forms.py:523 #: netbox/extras/forms/model_forms.py:522
msgid "Notification group" msgid "Notification group"
msgstr "" msgstr ""
#: netbox/extras/forms/model_forms.py:603 #: netbox/extras/forms/model_forms.py:602
#: netbox/templates/extras/configcontextprofile.html:10 #: netbox/templates/extras/configcontextprofile.html:10
msgid "Config Context Profile" msgid "Config Context Profile"
msgstr "" msgstr ""
#: netbox/extras/forms/model_forms.py:677 netbox/netbox/navigation/menu.py:26 #: netbox/extras/forms/model_forms.py:676 netbox/netbox/navigation/menu.py:26
#: netbox/tenancy/tables/tenants.py:18 #: netbox/tenancy/tables/tenants.py:18
msgid "Tenants" msgid "Tenants"
msgstr "" msgstr ""
#: netbox/extras/forms/model_forms.py:721 #: netbox/extras/forms/model_forms.py:720
msgid "Data is populated from the remote source selected below." msgid "Data is populated from the remote source selected below."
msgstr "" msgstr ""
#: netbox/extras/forms/model_forms.py:727 #: netbox/extras/forms/model_forms.py:726
msgid "Must specify either local data or a data file" msgid "Must specify either local data or a data file"
msgstr "" msgstr ""
#: netbox/extras/forms/model_forms.py:788
msgid "If no name is specified, the file name will be used."
msgstr ""
#: netbox/extras/forms/reports.py:17 netbox/extras/forms/scripts.py:25 #: netbox/extras/forms/reports.py:17 netbox/extras/forms/scripts.py:25
msgid "Schedule at" msgid "Schedule at"
msgstr "" msgstr ""

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -3,10 +3,9 @@ import string
from django.db.models import Q from django.db.models import Q
OBJECTPERMISSION_OBJECT_TYPES = ( OBJECTPERMISSION_OBJECT_TYPES = Q(
(Q(public=True) & ~Q(app_label='core', model='objecttype')) ~Q(app_label__in=['account', 'admin', 'auth', 'contenttypes', 'sessions', 'taggit', 'users']) |
| Q(app_label='core', model__in=['managedfile']) Q(app_label='users', model__in=['objectpermission', 'token', 'group', 'user', 'owner'])
| Q(app_label='extras', model__in=['scriptmodule', 'taggeditem'])
) )
CONSTRAINT_TOKEN_USER = '$user' CONSTRAINT_TOKEN_USER = '$user'

View File

@@ -1,5 +1,4 @@
from django import forms from django import forms
from django.conf import settings
from django.utils.translation import gettext_lazy as _ from django.utils.translation import gettext_lazy as _
from utilities.forms.widgets.apiselect import APISelect, APISelectMultiple from utilities.forms.widgets.apiselect import APISelect, APISelectMultiple
@@ -102,27 +101,21 @@ class FilterModifierWidget(forms.Widget):
if isinstance(self.original_widget, (APISelect, APISelectMultiple)): if isinstance(self.original_widget, (APISelect, APISelectMultiple)):
original_choices = self.original_widget.choices original_choices = self.original_widget.choices
# Only keep selected choices to preserve the current selection in HTML # Only keep selected choices to preserve current selection in HTML
if value: if value:
values = value if isinstance(value, (list, tuple)) else [value] values = value if isinstance(value, (list, tuple)) else [value]
if hasattr(original_choices, 'queryset'): if hasattr(original_choices, 'queryset'):
# Extract valid PKs (exclude special null choice string) queryset = original_choices.queryset
pk_values = [v for v in values if v != settings.FILTERS_NULL_CHOICE_VALUE] selected_objects = queryset.filter(pk__in=values)
# Build minimal choice list with just the selected values
# Build a minimal choice list with just the selected values self.original_widget.choices = [
choices = [] (obj.pk, str(obj)) for obj in selected_objects
if pk_values: ]
selected_objects = original_choices.queryset.filter(pk__in=pk_values)
choices = [(obj.pk, str(obj)) for obj in selected_objects]
# Re-add the "None" option if it was selected via the null choice value
if settings.FILTERS_NULL_CHOICE_VALUE in values:
choices.append((settings.FILTERS_NULL_CHOICE_VALUE, settings.FILTERS_NULL_CHOICE_LABEL))
self.original_widget.choices = choices
else: else:
self.original_widget.choices = [choice for choice in original_choices if choice[0] in values] self.original_widget.choices = [
choice for choice in original_choices if choice[0] in values
]
else: else:
# No selection - render empty select element # No selection - render empty select element
self.original_widget.choices = [] self.original_widget.choices = []

View File

@@ -1,5 +1,4 @@
from django import forms from django import forms
from django.conf import settings
from django.db import models from django.db import models
from django.http import QueryDict from django.http import QueryDict
from django.template import Context from django.template import Context
@@ -15,7 +14,6 @@ from utilities.forms.fields import TagFilterField
from utilities.forms.mixins import FilterModifierMixin from utilities.forms.mixins import FilterModifierMixin
from utilities.forms.widgets import FilterModifierWidget from utilities.forms.widgets import FilterModifierWidget
from utilities.templatetags.helpers import applied_filters from utilities.templatetags.helpers import applied_filters
from tenancy.models import Tenant
# Test model for FilterModifierMixin tests # Test model for FilterModifierMixin tests
@@ -101,51 +99,6 @@ class FilterModifierWidgetTest(TestCase):
self.assertEqual(context['widget']['current_modifier'], 'exact') # Defaults to exact, JS updates from URL self.assertEqual(context['widget']['current_modifier'], 'exact') # Defaults to exact, JS updates from URL
self.assertEqual(context['widget']['current_value'], 'test') self.assertEqual(context['widget']['current_value'], 'test')
def test_get_context_handles_null_selection(self):
"""Widget should preserve the 'null' choice when rendering."""
null_value = settings.FILTERS_NULL_CHOICE_VALUE
null_label = settings.FILTERS_NULL_CHOICE_LABEL
# Simulate a query for objects with no tenant assigned (?tenant_id=null)
query_params = QueryDict(f'tenant_id={null_value}')
form = DeviceFilterForm(query_params)
# Rendering the field triggers FilterModifierWidget.get_context()
try:
html = form['tenant_id'].as_widget()
except ValueError as e:
# ValueError: Field 'id' expected a number but got 'null'
self.fail(f"FilterModifierWidget raised ValueError on 'null' selection: {e}")
# Verify the "None" option is rendered so user selection is preserved in the UI
self.assertIn(f'value="{null_value}"', html)
self.assertIn(null_label, html)
def test_get_context_handles_mixed_selection(self):
"""Widget should preserve both real objects and the 'null' choice together."""
null_value = settings.FILTERS_NULL_CHOICE_VALUE
# Create a tenant to simulate a real object
tenant = Tenant.objects.create(name='Tenant A', slug='tenant-a')
# Simulate a selection containing both a real PK and the null sentinel
query_params = QueryDict('', mutable=True)
query_params.setlist('tenant_id', [str(tenant.pk), null_value])
form = DeviceFilterForm(query_params)
# Rendering the field triggers FilterModifierWidget.get_context()
try:
html = form['tenant_id'].as_widget()
except ValueError as e:
# ValueError: Field 'id' expected a number but got 'null'
self.fail(f"FilterModifierWidget raised ValueError on 'null' selection: {e}")
# Verify both the real object and the null option are present in the output
self.assertIn(f'value="{tenant.pk}"', html)
self.assertIn(f'value="{null_value}"', html)
def test_widget_renders_modifier_dropdown_and_input(self): def test_widget_renders_modifier_dropdown_and_input(self):
"""Widget should render modifier dropdown alongside original input.""" """Widget should render modifier dropdown alongside original input."""
widget = FilterModifierWidget( widget = FilterModifierWidget(

View File

@@ -5,11 +5,9 @@ from django.conf import settings
from django.contrib.auth.mixins import AccessMixin from django.contrib.auth.mixins import AccessMixin
from django.core.exceptions import ImproperlyConfigured from django.core.exceptions import ImproperlyConfigured
from django.db.models import QuerySet from django.db.models import QuerySet
from django.http import HttpResponseForbidden
from django.urls import reverse from django.urls import reverse
from django.urls.exceptions import NoReverseMatch from django.urls.exceptions import NoReverseMatch
from django.utils.translation import gettext_lazy as _ from django.utils.translation import gettext_lazy as _
from rest_framework.exceptions import AuthenticationFailed
from netbox.api.authentication import TokenAuthentication from netbox.api.authentication import TokenAuthentication
from netbox.plugins import PluginConfig from netbox.plugins import PluginConfig
@@ -52,12 +50,10 @@ class TokenConditionalLoginRequiredMixin(ConditionalLoginRequiredMixin):
# Attempt to authenticate the user using a DRF token, if provided # Attempt to authenticate the user using a DRF token, if provided
if settings.LOGIN_REQUIRED and not request.user.is_authenticated: if settings.LOGIN_REQUIRED and not request.user.is_authenticated:
authenticator = TokenAuthentication() authenticator = TokenAuthentication()
try: auth_info = authenticator.authenticate(request)
if (auth_info := authenticator.authenticate(request)) is not None: if auth_info is not None:
request.user = auth_info[0] # User object request.user = auth_info[0] # User object
request.auth = auth_info[1] request.auth = auth_info[1]
except AuthenticationFailed:
return HttpResponseForbidden("Invalid token")
return super().dispatch(request, *args, **kwargs) return super().dispatch(request, *args, **kwargs)

View File

@@ -15,7 +15,7 @@ from vpn import models
if TYPE_CHECKING: if TYPE_CHECKING:
from core.graphql.filters import ContentTypeFilter from core.graphql.filters import ContentTypeFilter
from ipam.graphql.filters import IPAddressFilter, RouteTargetFilter from ipam.graphql.filters import IPAddressFilter, RouteTargetFilter
from netbox.graphql.filter_lookups import BigIntegerLookup, IntegerLookup from netbox.graphql.filter_lookups import IntegerLookup
from .enums import * from .enums import *
__all__ = ( __all__ = (
@@ -75,7 +75,7 @@ class TunnelFilter(TenancyFilterMixin, PrimaryModelFilter):
ipsec_profile: Annotated['IPSecProfileFilter', strawberry.lazy('vpn.graphql.filters')] | None = ( ipsec_profile: Annotated['IPSecProfileFilter', strawberry.lazy('vpn.graphql.filters')] | None = (
strawberry_django.filter_field() strawberry_django.filter_field()
) )
tunnel_id: Annotated['BigIntegerLookup', strawberry.lazy('netbox.graphql.filter_lookups')] | None = ( tunnel_id: Annotated['IntegerLookup', strawberry.lazy('netbox.graphql.filter_lookups')] | None = (
strawberry_django.filter_field() strawberry_django.filter_field()
) )
terminations: Annotated['TunnelTerminationFilter', strawberry.lazy('vpn.graphql.filters')] | None = ( terminations: Annotated['TunnelTerminationFilter', strawberry.lazy('vpn.graphql.filters')] | None = (
@@ -187,7 +187,7 @@ class L2VPNFilter(ContactFilterMixin, TenancyFilterMixin, PrimaryModelFilter):
type: BaseFilterLookup[Annotated['L2VPNTypeEnum', strawberry.lazy('vpn.graphql.enums')]] | None = ( type: BaseFilterLookup[Annotated['L2VPNTypeEnum', strawberry.lazy('vpn.graphql.enums')]] | None = (
strawberry_django.filter_field() strawberry_django.filter_field()
) )
identifier: Annotated['BigIntegerLookup', strawberry.lazy('netbox.graphql.filter_lookups')] | None = ( identifier: Annotated['IntegerLookup', strawberry.lazy('netbox.graphql.filter_lookups')] | None = (
strawberry_django.filter_field() strawberry_django.filter_field()
) )
import_targets: Annotated['RouteTargetFilter', strawberry.lazy('ipam.graphql.filters')] | None = ( import_targets: Annotated['RouteTargetFilter', strawberry.lazy('ipam.graphql.filters')] | None = (

View File

@@ -3,7 +3,7 @@
[project] [project]
name = "netbox" name = "netbox"
version = "4.5.1" version = "4.5.0"
requires-python = ">=3.12" requires-python = ">=3.12"
description = "The premier source of truth powering network automation." description = "The premier source of truth powering network automation."
readme = "README.md" readme = "README.md"

View File

@@ -1,7 +1,7 @@
colorama==0.4.6 colorama==0.4.6
Django==5.2.10 Django==5.2.9
django-cors-headers==4.9.0 django-cors-headers==4.9.0
django-debug-toolbar==6.2.0 django-debug-toolbar==6.1.0
django-filter==25.2 django-filter==25.2
django-graphiql-debug-toolbar==0.2.0 django-graphiql-debug-toolbar==0.2.0
django-htmx==1.27.0 django-htmx==1.27.0
@@ -21,10 +21,10 @@ drf-spectacular-sidecar==2026.1.1
feedparser==6.0.12 feedparser==6.0.12
gunicorn==23.0.0 gunicorn==23.0.0
Jinja2==3.1.6 Jinja2==3.1.6
jsonschema==4.26.0 jsonschema==4.25.1
Markdown==3.10 Markdown==3.10
mkdocs-material==9.7.1 mkdocs-material==9.7.1
mkdocstrings==1.0.1 mkdocstrings==1.0.0
mkdocstrings-python==2.0.1 mkdocstrings-python==2.0.1
netaddr==1.3.0 netaddr==1.3.0
nh3==0.3.2 nh3==0.3.2
@@ -36,8 +36,8 @@ rq==2.6.1
social-auth-app-django==5.7.0 social-auth-app-django==5.7.0
social-auth-core==4.8.3 social-auth-core==4.8.3
sorl-thumbnail==12.11.0 sorl-thumbnail==12.11.0
strawberry-graphql==0.289.2 strawberry-graphql==0.288.2
strawberry-graphql-django==0.74.1 strawberry-graphql-django==0.73.0
svgwrite==1.4.3 svgwrite==1.4.3
tablib==3.9.0 tablib==3.9.0
tzdata==2025.3 tzdata==2025.3