Compare commits

..

5 Commits

Author SHA1 Message Date
Jeremy Stretch
6211a21423 Draft v4.5 release notes 2025-12-08 16:50:10 -05:00
Jeremy Stretch
cc935dbfab Closes #20926: Rename and clean up GraphQL filters (#20935)
Some checks are pending
CI / build (20.x, 3.12) (push) Waiting to run
CI / build (20.x, 3.13) (push) Waiting to run
CodeQL / Analyze (${{ matrix.language }}) (none, actions) (push) Waiting to run
CodeQL / Analyze (${{ matrix.language }}) (none, javascript-typescript) (push) Waiting to run
CodeQL / Analyze (${{ matrix.language }}) (none, python) (push) Waiting to run
2025-12-08 13:40:43 -06:00
bctiemann
3483d979d4 Merge pull request #20943 from netbox-community/20936-api-auth-check
Some checks are pending
CI / build (20.x, 3.12) (push) Waiting to run
CI / build (20.x, 3.13) (push) Waiting to run
CodeQL / Analyze (${{ matrix.language }}) (none, actions) (push) Waiting to run
CodeQL / Analyze (${{ matrix.language }}) (none, javascript-typescript) (push) Waiting to run
CodeQL / Analyze (${{ matrix.language }}) (none, python) (push) Waiting to run
Closes #20936: Add a REST API endpoint to validate authentication credentials
2025-12-07 16:03:55 -05:00
Jeremy Stretch
ca43adf692 Closes #20936: Add a REST API endpoint to validate authentication credentials 2025-12-07 13:59:37 -05:00
Jason Novinger
7eefb07554 Closes #7604: Add filter modifier dropdowns for advanced lookup operators (#20747)
Some checks failed
CI / build (20.x, 3.12) (push) Has been cancelled
CI / build (20.x, 3.13) (push) Has been cancelled
CodeQL / Analyze (${{ matrix.language }}) (none, actions) (push) Has been cancelled
CodeQL / Analyze (${{ matrix.language }}) (none, javascript-typescript) (push) Has been cancelled
CodeQL / Analyze (${{ matrix.language }}) (none, python) (push) Has been cancelled
* Fixes #7604: Add filter modifier dropdowns for advanced lookup operators

Implements dynamic filter modifier UI that allows users to select lookup operators
(exact, contains, starts with, regex, negation, empty/not empty) directly in filter
forms without manual URL parameter editing.

Supports filters for all scalar types and strings, as well as some
related object filters. Explicitly does not support filters on fields
that use APIWidget. That has been broken out in to follow up work.

**Backend:**
- FilterModifierWidget: Wraps form widgets with lookup modifier dropdown
- FilterModifierMixin: Auto-enhances filterset fields with appropriate lookups
- Extended lookup support: Adds negation (n), regex, iregex, empty_true/false lookups
- Field-type-aware: CharField gets text lookups, IntegerField gets comparison operators, etc.

**Frontend:**
- TypeScript handler syncs modifier dropdown with URL parameters
- Dynamically updates form field names (serial → serial__ic) on modifier change
- Flexible-width modifier dropdowns with semantic CSS classes

* Remove extraneous TS comments

* Fix import order

* Fix CircuitFilterForm inheritance

* Enable filter form modifiers on DCIM models

* Enable filter form modifiers on Tenancy models

* Enable filter form modifiers on Wireless models

* Enable filter form modifiers on IPAM models

* Enable filter form modifiers on VPN models

* Enable filter form modifiers on Virtualization models

* Enable filter form modifiers on Circuit models

* Enable filter form modifiers on Users models

* Enable filter form modifiers on Core models

* Enable filter form modifiers on Extras models

* Add ChoiceField support to FilterModifierMixin

Enable filter modifiers for single-choice ChoiceFields in addition to the
existing MultipleChoiceField support. ChoiceFields can now display modifier
dropdowns with "Is", "Is Not", "Is Empty", and "Is Not Empty" options when
the corresponding FilterSet defines those lookups.

The mixin correctly verifies lookup availability against the FilterSet, so
modifiers only appear when multiple lookup options are actually supported.
Currently most FilterSets only define 'exact' for single-choice fields, but
this change enables future FilterSet enhancements to expose additional
lookups for ChoiceFields.

* Address PR feedback: Replace global filterset mappings with registry

* Address PR feedback: Move FilterModifierMixin into base filter form classes

Incorporates FilterModifierMixin into NetBoxModelFilterSetForm and FilterForm,
making filter modifiers automatic for all filter forms throughout the application.

* Fix filter modifier form submission bug with 'action' field collision

Forms with a field named "action" (e.g., ObjectChangeFilterForm) were causing
the form.action property to be shadowed by the field element, resulting in
[object HTMLSelectElement] appearing in the URL path.

Use form.getAttribute('action') instead of form.action to reliably retrieve
the form's action URL without collision from form fields.

Fixes form submission on /core/changelog/ and any other forms with an 'action'
field using filter modifiers.

* Address PR feedback: Move FORM_FIELD_LOOKUPS to module-level constant

Extracts the field type to lookup mappings from FilterModifierMixin class
attribute to a module-level constant for better reusability.

* Address PR feedback: Refactor and consolidate field filtering logic

Consolidated field enhancement logic in FilterModifierMixin by:
- Creating QueryField marker type (CharField subclass) for search fields
- Updating FilterForm and NetBoxModelFilterSetForm to use QueryField for 'q'
- Moving all skip logic into _get_lookup_choices() to return empty list for
  fields that shouldn't be enhanced
- Removing separate _should_skip_field() method
- Removing unused field_name parameter from _get_lookup_choices()
- Replacing hardcoded field name check ('q') with type-based detection

* Address PR feedback: Refactor applied_filters to use FORM_FIELD_LOOKUPS

* Address PR feedback: Rename FilterModifierWidget parameter to widget

* Fix registry pattern to use model identifiers as keys

Changed filterset registration to use model identifiers ('{app_label}.{model_name}')
as registry keys instead of form classes, matching NetBox's pattern for search indexes.

* Address PR feedback: refactor brittle test for APISelect useage

Now checks if widget is actually APISelect, rather than trying to infer
from the class name.

* Refactor register_filterset to be more generic and simple

* Remove unneeded imports left from earlier registry work

* Update app registry for new `filtersets` store

* Remove unused star import, leftover from earlier work

* Enables filter modifiers on APISelect based fields

* Support filter modifiers for ChoiceField

* Include MODIFIER_EMPTY_FALSE/_TRUE in __all__

Co-authored-by: Jeremy Stretch <jstretch@netboxlabs.com>

* Fix filterset registration for doubly-registered models

* Removed explicit checks against QueryField and [Null]BooleanField

I did add them to FORM_FIELD_LOOKUPS, though, to underscore that they
were considered and are intentially empty for future devs.

* Switch to sentence case for filter pill text

* Fix applied_filters template tag to use field-type-specific lookup labelsresolves

E.g. resolves gt="after" for dates vs "greater than" for numbers

* Verifies that filter pills for exact matches (no lookup
Add test for exact lookup filter pill rendering

* Add guard for FilterModifierWidget with no lookups

* Remove comparison symbols from numeric filter labels

* Match complete tags in widget rendering test assertions

* Check all expected lookups in field enhancement tests

* Move register_filterset to netbox.plugins.registration

* Require registered filterset for filter modifier enhancements

Updates FilterModifierMixin to only enhance form fields when the
associated model has a registered filterset. This provides plugin
safety by ensuring unregistered plugin filtersets fall back to
simple filters without lookup modifiers.

Test changes:
- Create TestModel and TestFilterSet using BaseFilterSet for
automatic lookup generation
- Import dcim.filtersets to ensure Device filterset registration
- Adjust tag field expectations to match actual Device filterset
(has exact/n but not empty lookups)

* Attempt to resolve static conflicts

* Move register_filterset() back to utilities.filtersets

* Add register_filterset() to plugins documentation for filtersets

* Reorder import statements

---------

Co-authored-by: Jeremy Stretch <jstretch@netboxlabs.com>
2025-12-05 15:13:37 -05:00
25 changed files with 406 additions and 293 deletions

View File

@@ -325,14 +325,14 @@ class CircuitTypeType(OrganizationalObjectType):
### Change filters.py
Strawberry currently doesn't directly support django-filter, so an explicit filters.py file will need to be created. NetBox includes a new `autotype_decorator` used to automatically wrap FilterSets to reduce the required code to a minimum.
Filter classes should inherit from `netbox.graphql.filters.BaseModelFilter`.
```python title="New"
import strawberry
import strawberry_django
from circuits import filtersets, models
from netbox.graphql.filter_mixins import autotype_decorator, BaseFilterMixin
from netbox.graphql.filters import BaseModelFilter
__all__ = (
'CircuitFilter',
@@ -340,8 +340,7 @@ __all__ = (
@strawberry_django.filter(models.Circuit, lookups=True)
@autotype_decorator(filtersets.CircuitFilterSet)
class CircuitFilter(BaseFilterMixin):
class CircuitFilter(BaseModelFilter):
pass
```

View File

@@ -0,0 +1,111 @@
## v4.5.0 (FUTURE)
### Breaking Changes
* Python 3.10 and 3.11 are no longer supported. NetBox now requires Python 3.12 or later.
* GraphQL API queries which filter by object IDs or enums must now specify a filter lookup similar to other fields. (For example, `id: 123` becomes `id: {exact: 123 }`.)
* Rendering a device or virtual machine configuration is now restricted to users with the `render_config` permission for the applicable object type.
* Retrieval of API token plaintexts is no longer supported. The `ALLOW_TOKEN_RETRIEVAL` config parameter has been removed.
* The owner of an API token can no longer be changed once it has been created.
* Config contexts now apply to all child platforms of a parent platform.
* The `/api/extras/object-types/` REST API endpoint has been removed. (Use `/api/core/object-types/` instead.)
* The `/api/dcim/cable-terminations/` REST API endpoint is now read-only. Cable terminations must be set on cables directly.
* The UI view dedicated to swaping A/Z circuit terminations has been removed.
* Webhooks no longer specify a `model` in payload data. (Reference `object_type` instead, which includes the parent app label.)
* The obsolete module `core.models.contenttypes` has been removed (replaced in v4.4 by `core.models.object_types`).
* The `load_yaml()` and `load_json()` utility methods have been removed from the base class for custom scripts.
* The experimental HTMX navigation feature has been removed.
* The obsolete field `is_staff` has been removed from the `User` model.
### New Features
#### Lookup Modifiers in Filter Forms ([#7604](https://github.com/netbox-community/netbox/issues/7604))
#### Improved API Authentication Tokens ([#20210](https://github.com/netbox-community/netbox/issues/20210))
#### Object Ownership ([#20304](https://github.com/netbox-community/netbox/issues/20304))
#### Advanced Port Mappings ([#20564](https://github.com/netbox-community/netbox/issues/20564))
#### Cable Profiles ([#20788](https://github.com/netbox-community/netbox/issues/20788))
### Enhancements
* [#16681](https://github.com/netbox-community/netbox/issues/16681) - Introduce a `render_config` permission, which is noq required to render a device or virtual machine configuration
* [#18658](https://github.com/netbox-community/netbox/issues/18658) - Add a `start_on_boot` choice field for virtual machines
* [#19095](https://github.com/netbox-community/netbox/issues/19095) - Add support for Python 3.13 and 3.14
* [#19338](https://github.com/netbox-community/netbox/issues/19338) - Enable filter lookups for object IDs and enums in GraphQL API queries
* [#19523](https://github.com/netbox-community/netbox/issues/19523) - Cache the number of instances for device, module, and rack types, and enable filtering by these counts
* [#20417](https://github.com/netbox-community/netbox/issues/20417) - Add an optional `color` field for device type power outlets
* [#20476](https://github.com/netbox-community/netbox/issues/20476) - Once provisioned, the owner of an API token cannot be changed
* [#20492](https://github.com/netbox-community/netbox/issues/20492) - Completely disabled the means to retrieve legacy API token plaintexts (removed the `ALLOW_TOKEN_RETRIEVAL` config parameter)
* [#20639](https://github.com/netbox-community/netbox/issues/20639) - Apply config contexts to devices/VMs assigned any child platform of the parent platform
* [#20834](https://github.com/netbox-community/netbox/issues/20834) - Add an `enabled` boolean field to API tokens
* [#20917](https://github.com/netbox-community/netbox/issues/20917) - Include usage reference on API token views
* [#20925](https://github.com/netbox-community/netbox/issues/20925) - Add optional `comments` field to all subclasses of `OrganizationalModel`
* [#20936](https://github.com/netbox-community/netbox/issues/20936) - Introduce the `/api/authentication-check/` REST API endpoint for validating authentication tokens
### Plugins
* [#13182](https://github.com/netbox-community/netbox/issues/13182) - Added `PrimaryModel`, `OrganizationalModel`, and `NestedGroupModel` to the plugins API, as well as their respective base classes for various resources
### Other Changes
* [#16137](https://github.com/netbox-community/netbox/issues/16137) - Remove the obsolete boolean field `is_staff` from the `User` model
* [#17571](https://github.com/netbox-community/netbox/issues/17571) - Remove the experimental HTMX navigation feature
* [#17936](https://github.com/netbox-community/netbox/issues/17936) - Introduce a dedicated `GFKSerializerField` for representing generic foreign keys in API serializers
* [#19889](https://github.com/netbox-community/netbox/issues/19889) - Drop support for Python 3.10 and 3.11
* [#19898](https://github.com/netbox-community/netbox/issues/19898) - Remove the obsolete REST API endpoint `/api/extras/object-types/`
* [#20088](https://github.com/netbox-community/netbox/issues/20088) - Remove the non-deterministic `model` key from webhook payload data
* [#20095](https://github.com/netbox-community/netbox/issues/20095) - Remove the obsolete module `core.models.contenttypes`
* [#20096](https://github.com/netbox-community/netbox/issues/20096) - Remove the `load_yaml()` and `load_json()` utility methods from the `BaseScript` class
* [#20204](https://github.com/netbox-community/netbox/issues/20204) - Started migrating object views from custom HTML templates to declarative layouts
* [#20617](https://github.com/netbox-community/netbox/issues/20617) - Introduce `BaseModel` as the global base class for models
* [#20683](https://github.com/netbox-community/netbox/issues/20683) - Remove the UI view dedicated to swaping A/Z circuit terminations
* [#20926](https://github.com/netbox-community/netbox/issues/20926) - Standardize naming of GraphQL filters
### REST API Changes
* Most objects now include an optional `owner` foreign key field.
* The `/api/dcim/cable-terminations` endpoint is now read-only.
* Introduced the `/api/authentication-check/` endpoint.
* `circuits.CircuitGroup`
* Add optional `comments` field
* `circuits.CircuitType`
* Add optional `comments` field
* `circuits.VirtualCircuitType`
* Add optional `comments` field
* `dcim.Cable`
* Add the optional `profile` choice field
* `dcim.InventoryItemRole`
* Add optional `comments` field
* `dcim.Manufacturer`
* Add optional `comments` field
* `dcim.ModuleType`
* Add read-only `module_count` integer field
* `dcim.PowerOutletTemplate`
* Add optional `color` field
* `dcim.RackRole`
* Add optional `comments` field
* `dcim.RackType`
* Add read-only `rack_count` integer field
* `ipam.ASNRange`
* Add optional `comments` field
* `ipam.RIR`
* Add optional `comments` field
* `ipam.Role`
* Add optional `comments` field
* `ipam.VLANGroup`
* Add optional `comments` field
* `tenancy.ContactRole`
* Add optional `comments` field
* `users.Token`
* Add `enabled` boolean field
* `virtualization.ClusterGroup`
* Add optional `comments` field
* `virtualization.ClusterType`
* Add optional `comments` field
* `virtualization.VirtualMachine`
* Add optional `start_on_boot` choice field
* `vpn.TunnelGroup`
* Add optional `comments` field

View File

@@ -3,17 +3,18 @@ from typing import Annotated, TYPE_CHECKING
import strawberry
import strawberry_django
from netbox.graphql.filter_mixins import OrganizationalModelFilterMixin
from strawberry_django import BaseFilterLookup
if TYPE_CHECKING:
from netbox.graphql.enums import ColorEnum
__all__ = (
'BaseCircuitTypeFilterMixin',
'CircuitTypeFilterMixin',
)
@dataclass
class BaseCircuitTypeFilterMixin(OrganizationalModelFilterMixin):
color: Annotated['ColorEnum', strawberry.lazy('netbox.graphql.enums')] | None = strawberry_django.filter_field()
class CircuitTypeFilterMixin:
color: BaseFilterLookup[Annotated['ColorEnum', strawberry.lazy('netbox.graphql.enums')]] | None = (
strawberry_django.filter_field()
)

View File

@@ -7,17 +7,12 @@ from strawberry.scalars import ID
from strawberry_django import BaseFilterLookup, FilterLookup, DateFilterLookup
from circuits import models
from core.graphql.filter_mixins import BaseObjectTypeFilterMixin, ChangeLogFilterMixin
from circuits.graphql.filter_mixins import CircuitTypeFilterMixin
from dcim.graphql.filter_mixins import CabledObjectModelFilterMixin
from extras.graphql.filter_mixins import CustomFieldsFilterMixin, TagsFilterMixin
from netbox.graphql.filter_mixins import (
DistanceFilterMixin,
ImageAttachmentFilterMixin,
OrganizationalModelFilterMixin,
PrimaryModelFilterMixin,
)
from netbox.graphql.filter_mixins import DistanceFilterMixin, ImageAttachmentFilterMixin
from netbox.graphql.filters import ChangeLoggedModelFilter, OrganizationalModelFilter, PrimaryModelFilter
from tenancy.graphql.filter_mixins import ContactFilterMixin, TenancyFilterMixin
from .filter_mixins import BaseCircuitTypeFilterMixin
if TYPE_CHECKING:
from core.graphql.filters import ContentTypeFilter
@@ -43,10 +38,9 @@ __all__ = (
@strawberry_django.filter_type(models.CircuitTermination, lookups=True)
class CircuitTerminationFilter(
BaseObjectTypeFilterMixin,
CustomFieldsFilterMixin,
TagsFilterMixin,
ChangeLogFilterMixin,
ChangeLoggedModelFilter,
CabledObjectModelFilterMixin,
):
circuit: Annotated['CircuitFilter', strawberry.lazy('circuits.graphql.filters')] | None = (
@@ -95,7 +89,7 @@ class CircuitFilter(
ImageAttachmentFilterMixin,
DistanceFilterMixin,
TenancyFilterMixin,
PrimaryModelFilterMixin
PrimaryModelFilter
):
cid: FilterLookup[str] | None = strawberry_django.filter_field()
provider: Annotated['ProviderFilter', strawberry.lazy('circuits.graphql.filters')] | None = (
@@ -124,19 +118,17 @@ class CircuitFilter(
@strawberry_django.filter_type(models.CircuitType, lookups=True)
class CircuitTypeFilter(BaseCircuitTypeFilterMixin):
class CircuitTypeFilter(CircuitTypeFilterMixin, OrganizationalModelFilter):
pass
@strawberry_django.filter_type(models.CircuitGroup, lookups=True)
class CircuitGroupFilter(TenancyFilterMixin, OrganizationalModelFilterMixin):
class CircuitGroupFilter(TenancyFilterMixin, OrganizationalModelFilter):
pass
@strawberry_django.filter_type(models.CircuitGroupAssignment, lookups=True)
class CircuitGroupAssignmentFilter(
BaseObjectTypeFilterMixin, CustomFieldsFilterMixin, TagsFilterMixin, ChangeLogFilterMixin
):
class CircuitGroupAssignmentFilter(CustomFieldsFilterMixin, TagsFilterMixin, ChangeLoggedModelFilter):
member_type: Annotated['ContentTypeFilter', strawberry.lazy('core.graphql.filters')] | None = (
strawberry_django.filter_field()
)
@@ -151,7 +143,7 @@ class CircuitGroupAssignmentFilter(
@strawberry_django.filter_type(models.Provider, lookups=True)
class ProviderFilter(ContactFilterMixin, PrimaryModelFilterMixin):
class ProviderFilter(ContactFilterMixin, PrimaryModelFilter):
name: FilterLookup[str] | None = strawberry_django.filter_field()
slug: FilterLookup[str] | None = strawberry_django.filter_field()
asns: Annotated['ASNFilter', strawberry.lazy('ipam.graphql.filters')] | None = strawberry_django.filter_field()
@@ -161,7 +153,7 @@ class ProviderFilter(ContactFilterMixin, PrimaryModelFilterMixin):
@strawberry_django.filter_type(models.ProviderAccount, lookups=True)
class ProviderAccountFilter(ContactFilterMixin, PrimaryModelFilterMixin):
class ProviderAccountFilter(ContactFilterMixin, PrimaryModelFilter):
provider: Annotated['ProviderFilter', strawberry.lazy('circuits.graphql.filters')] | None = (
strawberry_django.filter_field()
)
@@ -171,7 +163,7 @@ class ProviderAccountFilter(ContactFilterMixin, PrimaryModelFilterMixin):
@strawberry_django.filter_type(models.ProviderNetwork, lookups=True)
class ProviderNetworkFilter(PrimaryModelFilterMixin):
class ProviderNetworkFilter(PrimaryModelFilter):
name: FilterLookup[str] | None = strawberry_django.filter_field()
provider: Annotated['ProviderFilter', strawberry.lazy('circuits.graphql.filters')] | None = (
strawberry_django.filter_field()
@@ -181,12 +173,12 @@ class ProviderNetworkFilter(PrimaryModelFilterMixin):
@strawberry_django.filter_type(models.VirtualCircuitType, lookups=True)
class VirtualCircuitTypeFilter(BaseCircuitTypeFilterMixin):
class VirtualCircuitTypeFilter(CircuitTypeFilterMixin, OrganizationalModelFilter):
pass
@strawberry_django.filter_type(models.VirtualCircuit, lookups=True)
class VirtualCircuitFilter(TenancyFilterMixin, PrimaryModelFilterMixin):
class VirtualCircuitFilter(TenancyFilterMixin, PrimaryModelFilter):
cid: FilterLookup[str] | None = strawberry_django.filter_field()
provider_network: Annotated['ProviderNetworkFilter', strawberry.lazy('circuits.graphql.filters')] | None = (
strawberry_django.filter_field()
@@ -209,9 +201,7 @@ class VirtualCircuitFilter(TenancyFilterMixin, PrimaryModelFilterMixin):
@strawberry_django.filter_type(models.VirtualCircuitTermination, lookups=True)
class VirtualCircuitTerminationFilter(
BaseObjectTypeFilterMixin, CustomFieldsFilterMixin, TagsFilterMixin, ChangeLogFilterMixin
):
class VirtualCircuitTerminationFilter(CustomFieldsFilterMixin, TagsFilterMixin, ChangeLoggedModelFilter):
virtual_circuit: Annotated['VirtualCircuitFilter', strawberry.lazy('circuits.graphql.filters')] | None = (
strawberry_django.filter_field()
)

View File

@@ -4,31 +4,18 @@ from typing import Annotated, TYPE_CHECKING
import strawberry
import strawberry_django
from strawberry import ID
from strawberry_django import FilterLookup, DatetimeFilterLookup
from strawberry_django import DatetimeFilterLookup
if TYPE_CHECKING:
from .filters import *
__all__ = (
'BaseFilterMixin',
'BaseObjectTypeFilterMixin',
'ChangeLogFilterMixin',
'ChangeLoggingMixin',
)
# @strawberry.input
class BaseFilterMixin: ...
@dataclass
class BaseObjectTypeFilterMixin(BaseFilterMixin):
id: FilterLookup[ID] | None = strawberry_django.filter_field()
@dataclass
class ChangeLogFilterMixin(BaseFilterMixin):
id: FilterLookup[ID] | None = strawberry_django.filter_field()
class ChangeLoggingMixin:
# TODO: "changelog" is not a valid field name; needs to be updated for ObjectChange
changelog: Annotated['ObjectChangeFilter', strawberry.lazy('core.graphql.filters')] | None = (
strawberry_django.filter_field()

View File

@@ -8,8 +8,7 @@ from strawberry.scalars import ID
from strawberry_django import BaseFilterLookup, DatetimeFilterLookup, FilterLookup
from core import models
from core.graphql.filter_mixins import BaseFilterMixin
from netbox.graphql.filter_mixins import PrimaryModelFilterMixin
from netbox.graphql.filters import BaseModelFilter, PrimaryModelFilter
from .enums import *
if TYPE_CHECKING:
@@ -25,8 +24,7 @@ __all__ = (
@strawberry_django.filter_type(models.DataFile, lookups=True)
class DataFileFilter(BaseFilterMixin):
id: FilterLookup[ID] | None = strawberry_django.filter_field()
class DataFileFilter(BaseModelFilter):
created: DatetimeFilterLookup[datetime] | None = strawberry_django.filter_field()
last_updated: DatetimeFilterLookup[datetime] | None = strawberry_django.filter_field()
source: Annotated['DataSourceFilter', strawberry.lazy('core.graphql.filters')] | None = (
@@ -41,7 +39,7 @@ class DataFileFilter(BaseFilterMixin):
@strawberry_django.filter_type(models.DataSource, lookups=True)
class DataSourceFilter(PrimaryModelFilterMixin):
class DataSourceFilter(PrimaryModelFilter):
name: FilterLookup[str] | None = strawberry_django.filter_field()
type: FilterLookup[str] | None = strawberry_django.filter_field()
source_url: FilterLookup[str] | None = strawberry_django.filter_field()
@@ -60,8 +58,7 @@ class DataSourceFilter(PrimaryModelFilterMixin):
@strawberry_django.filter_type(models.ObjectChange, lookups=True)
class ObjectChangeFilter(BaseFilterMixin):
id: FilterLookup[ID] | None = strawberry_django.filter_field()
class ObjectChangeFilter(BaseModelFilter):
time: DatetimeFilterLookup[datetime] | None = strawberry_django.filter_field()
user: Annotated['UserFilter', strawberry.lazy('users.graphql.filters')] | None = strawberry_django.filter_field()
user_name: FilterLookup[str] | None = strawberry_django.filter_field()
@@ -88,7 +85,6 @@ class ObjectChangeFilter(BaseFilterMixin):
@strawberry_django.filter_type(DjangoContentType, lookups=True)
class ContentTypeFilter(BaseFilterMixin):
id: FilterLookup[ID] | None = strawberry_django.filter_field()
class ContentTypeFilter(BaseModelFilter):
app_label: FilterLookup[str] | None = strawberry_django.filter_field()
model: FilterLookup[str] | None = strawberry_django.filter_field()

View File

@@ -6,9 +6,7 @@ import strawberry_django
from strawberry import ID
from strawberry_django import BaseFilterLookup, FilterLookup
from core.graphql.filter_mixins import BaseFilterMixin, ChangeLogFilterMixin
from core.graphql.filters import ContentTypeFilter
from netbox.graphql.filter_mixins import NetBoxModelFilterMixin, PrimaryModelFilterMixin, WeightFilterMixin
from .enums import *
if TYPE_CHECKING:
@@ -22,16 +20,16 @@ __all__ = (
'ComponentModelFilterMixin',
'ComponentTemplateFilterMixin',
'InterfaceBaseFilterMixin',
'ModularComponentModelFilterMixin',
'ModularComponentFilterMixin',
'ModularComponentTemplateFilterMixin',
'RackBaseFilterMixin',
'RackFilterMixin',
'RenderConfigFilterMixin',
'ScopedFilterMixin',
)
@dataclass
class ScopedFilterMixin(BaseFilterMixin):
class ScopedFilterMixin:
scope_type: Annotated['ContentTypeFilter', strawberry.lazy('core.graphql.filters')] | None = (
strawberry_django.filter_field()
)
@@ -39,7 +37,7 @@ class ScopedFilterMixin(BaseFilterMixin):
@dataclass
class ComponentModelFilterMixin(NetBoxModelFilterMixin):
class ComponentModelFilterMixin:
device: Annotated['DeviceFilter', strawberry.lazy('dcim.graphql.filters')] | None = strawberry_django.filter_field()
device_id: ID | None = strawberry_django.filter_field()
name: FilterLookup[str] | None = strawberry_django.filter_field()
@@ -48,7 +46,7 @@ class ComponentModelFilterMixin(NetBoxModelFilterMixin):
@dataclass
class ModularComponentModelFilterMixin(ComponentModelFilterMixin):
class ModularComponentFilterMixin(ComponentModelFilterMixin):
module: Annotated['ModuleFilter', strawberry.lazy('dcim.graphql.filters')] | None = strawberry_django.filter_field()
module_id: ID | None = strawberry_django.filter_field()
inventory_items: Annotated['InventoryItemFilter', strawberry.lazy('dcim.graphql.filters')] | None = (
@@ -57,7 +55,7 @@ class ModularComponentModelFilterMixin(ComponentModelFilterMixin):
@dataclass
class CabledObjectModelFilterMixin(BaseFilterMixin):
class CabledObjectModelFilterMixin:
cable: Annotated['CableFilter', strawberry.lazy('dcim.graphql.filters')] | None = strawberry_django.filter_field()
cable_id: ID | None = strawberry_django.filter_field()
cable_end: (
@@ -67,7 +65,7 @@ class CabledObjectModelFilterMixin(BaseFilterMixin):
@dataclass
class ComponentTemplateFilterMixin(ChangeLogFilterMixin):
class ComponentTemplateFilterMixin:
device_type: Annotated['DeviceTypeFilter', strawberry.lazy('dcim.graphql.filters')] | None = (
strawberry_django.filter_field()
)
@@ -85,7 +83,7 @@ class ModularComponentTemplateFilterMixin(ComponentTemplateFilterMixin):
@dataclass
class RenderConfigFilterMixin(BaseFilterMixin):
class RenderConfigFilterMixin:
config_template: Annotated['ConfigTemplateFilter', strawberry.lazy('extras.graphql.filters')] | None = (
strawberry_django.filter_field()
)
@@ -93,7 +91,7 @@ class RenderConfigFilterMixin(BaseFilterMixin):
@dataclass
class InterfaceBaseFilterMixin(BaseFilterMixin):
class InterfaceBaseFilterMixin:
enabled: FilterLookup[bool] | None = strawberry_django.filter_field()
mtu: Annotated['IntegerLookup', strawberry.lazy('netbox.graphql.filter_lookups')] | None = (
strawberry_django.filter_field()
@@ -124,7 +122,7 @@ class InterfaceBaseFilterMixin(BaseFilterMixin):
@dataclass
class RackBaseFilterMixin(WeightFilterMixin, PrimaryModelFilterMixin):
class RackFilterMixin:
width: BaseFilterLookup[Annotated['RackWidthEnum', strawberry.lazy('dcim.graphql.enums')]] | None = (
strawberry_django.filter_field()
)

View File

@@ -6,29 +6,24 @@ import strawberry_django
from strawberry.scalars import ID
from strawberry_django import BaseFilterLookup, ComparisonFilterLookup, FilterLookup
from core.graphql.filter_mixins import ChangeLogFilterMixin
from dcim import models
from dcim.constants import *
from dcim.graphql.enums import InterfaceKindEnum
from dcim.graphql.filter_mixins import (
ComponentModelFilterMixin, ComponentTemplateFilterMixin, ModularComponentFilterMixin,
ModularComponentTemplateFilterMixin, RackFilterMixin,
)
from extras.graphql.filter_mixins import ConfigContextFilterMixin
from netbox.graphql.filter_mixins import (
PrimaryModelFilterMixin,
OrganizationalModelFilterMixin,
NestedGroupModelFilterMixin,
ImageAttachmentFilterMixin,
WeightFilterMixin,
from netbox.graphql.filter_mixins import ImageAttachmentFilterMixin, WeightFilterMixin
from netbox.graphql.filters import (
ChangeLoggedModelFilter, NestedGroupModelFilter, OrganizationalModelFilter, PrimaryModelFilter, NetBoxModelFilter,
)
from tenancy.graphql.filter_mixins import ContactFilterMixin, TenancyFilterMixin
from virtualization.models import VMInterface
from .filter_mixins import (
CabledObjectModelFilterMixin,
ComponentModelFilterMixin,
ComponentTemplateFilterMixin,
InterfaceBaseFilterMixin,
ModularComponentModelFilterMixin,
ModularComponentTemplateFilterMixin,
RackBaseFilterMixin,
RenderConfigFilterMixin,
)
@@ -96,7 +91,7 @@ __all__ = (
@strawberry_django.filter_type(models.Cable, lookups=True)
class CableFilter(PrimaryModelFilterMixin, TenancyFilterMixin):
class CableFilter(TenancyFilterMixin, PrimaryModelFilter):
type: BaseFilterLookup[Annotated['CableTypeEnum', strawberry.lazy('dcim.graphql.enums')]] | None = (
strawberry_django.filter_field()
)
@@ -119,7 +114,7 @@ class CableFilter(PrimaryModelFilterMixin, TenancyFilterMixin):
@strawberry_django.filter_type(models.CableTermination, lookups=True)
class CableTerminationFilter(ChangeLogFilterMixin):
class CableTerminationFilter(ChangeLoggedModelFilter):
cable: Annotated['CableFilter', strawberry.lazy('dcim.graphql.filters')] | None = strawberry_django.filter_field()
cable_id: ID | None = strawberry_django.filter_field()
cable_end: BaseFilterLookup[Annotated['CableEndEnum', strawberry.lazy('dcim.graphql.enums')]] | None = (
@@ -132,7 +127,7 @@ class CableTerminationFilter(ChangeLogFilterMixin):
@strawberry_django.filter_type(models.ConsolePort, lookups=True)
class ConsolePortFilter(ModularComponentModelFilterMixin, CabledObjectModelFilterMixin):
class ConsolePortFilter(ModularComponentFilterMixin, CabledObjectModelFilterMixin, NetBoxModelFilter):
type: BaseFilterLookup[Annotated['ConsolePortTypeEnum', strawberry.lazy('dcim.graphql.enums')]] | None = (
strawberry_django.filter_field()
)
@@ -142,14 +137,14 @@ class ConsolePortFilter(ModularComponentModelFilterMixin, CabledObjectModelFilte
@strawberry_django.filter_type(models.ConsolePortTemplate, lookups=True)
class ConsolePortTemplateFilter(ModularComponentTemplateFilterMixin):
class ConsolePortTemplateFilter(ModularComponentTemplateFilterMixin, ChangeLoggedModelFilter):
type: BaseFilterLookup[Annotated['ConsolePortTypeEnum', strawberry.lazy('dcim.graphql.enums')]] | None = (
strawberry_django.filter_field()
)
@strawberry_django.filter_type(models.ConsoleServerPort, lookups=True)
class ConsoleServerPortFilter(ModularComponentModelFilterMixin, CabledObjectModelFilterMixin):
class ConsoleServerPortFilter(ModularComponentFilterMixin, CabledObjectModelFilterMixin, NetBoxModelFilter):
type: BaseFilterLookup[Annotated['ConsolePortTypeEnum', strawberry.lazy('dcim.graphql.enums')]] | None = (
strawberry_django.filter_field()
)
@@ -159,7 +154,7 @@ class ConsoleServerPortFilter(ModularComponentModelFilterMixin, CabledObjectMode
@strawberry_django.filter_type(models.ConsoleServerPortTemplate, lookups=True)
class ConsoleServerPortTemplateFilter(ModularComponentTemplateFilterMixin):
class ConsoleServerPortTemplateFilter(ModularComponentTemplateFilterMixin, ChangeLoggedModelFilter):
type: BaseFilterLookup[Annotated['ConsolePortTypeEnum', strawberry.lazy('dcim.graphql.enums')]] | None = (
strawberry_django.filter_field()
)
@@ -172,7 +167,7 @@ class DeviceFilter(
ImageAttachmentFilterMixin,
RenderConfigFilterMixin,
ConfigContextFilterMixin,
PrimaryModelFilterMixin,
PrimaryModelFilter,
):
device_type: Annotated['DeviceTypeFilter', strawberry.lazy('dcim.graphql.filters')] | None = (
strawberry_django.filter_field()
@@ -285,7 +280,7 @@ class DeviceFilter(
@strawberry_django.filter_type(models.DeviceBay, lookups=True)
class DeviceBayFilter(ComponentModelFilterMixin):
class DeviceBayFilter(ComponentModelFilterMixin, NetBoxModelFilter):
installed_device: Annotated['DeviceFilter', strawberry.lazy('dcim.graphql.filters')] | None = (
strawberry_django.filter_field()
)
@@ -293,12 +288,12 @@ class DeviceBayFilter(ComponentModelFilterMixin):
@strawberry_django.filter_type(models.DeviceBayTemplate, lookups=True)
class DeviceBayTemplateFilter(ComponentTemplateFilterMixin):
class DeviceBayTemplateFilter(ComponentTemplateFilterMixin, ChangeLoggedModelFilter):
pass
@strawberry_django.filter_type(models.InventoryItemTemplate, lookups=True)
class InventoryItemTemplateFilter(ComponentTemplateFilterMixin):
class InventoryItemTemplateFilter(ComponentTemplateFilterMixin, ChangeLoggedModelFilter):
parent: Annotated['InventoryItemTemplateFilter', strawberry.lazy('dcim.graphql.filters')] | None = (
strawberry_django.filter_field()
)
@@ -318,7 +313,7 @@ class InventoryItemTemplateFilter(ComponentTemplateFilterMixin):
@strawberry_django.filter_type(models.DeviceRole, lookups=True)
class DeviceRoleFilter(OrganizationalModelFilterMixin, RenderConfigFilterMixin):
class DeviceRoleFilter(RenderConfigFilterMixin, OrganizationalModelFilter):
color: BaseFilterLookup[Annotated['ColorEnum', strawberry.lazy('netbox.graphql.enums')]] | None = (
strawberry_django.filter_field()
)
@@ -326,7 +321,7 @@ class DeviceRoleFilter(OrganizationalModelFilterMixin, RenderConfigFilterMixin):
@strawberry_django.filter_type(models.DeviceType, lookups=True)
class DeviceTypeFilter(ImageAttachmentFilterMixin, PrimaryModelFilterMixin, WeightFilterMixin):
class DeviceTypeFilter(ImageAttachmentFilterMixin, WeightFilterMixin, PrimaryModelFilter):
manufacturer: Annotated['ManufacturerFilter', strawberry.lazy('dcim.graphql.filters')] | None = (
strawberry_django.filter_field()
)
@@ -402,7 +397,7 @@ class DeviceTypeFilter(ImageAttachmentFilterMixin, PrimaryModelFilterMixin, Weig
@strawberry_django.filter_type(models.FrontPort, lookups=True)
class FrontPortFilter(ModularComponentModelFilterMixin, CabledObjectModelFilterMixin):
class FrontPortFilter(ModularComponentFilterMixin, CabledObjectModelFilterMixin, NetBoxModelFilter):
type: BaseFilterLookup[Annotated['PortTypeEnum', strawberry.lazy('dcim.graphql.enums')]] | None = (
strawberry_django.filter_field()
)
@@ -419,7 +414,7 @@ class FrontPortFilter(ModularComponentModelFilterMixin, CabledObjectModelFilterM
@strawberry_django.filter_type(models.FrontPortTemplate, lookups=True)
class FrontPortTemplateFilter(ModularComponentTemplateFilterMixin):
class FrontPortTemplateFilter(ModularComponentTemplateFilterMixin, ChangeLoggedModelFilter):
type: BaseFilterLookup[Annotated['PortTypeEnum', strawberry.lazy('dcim.graphql.enums')]] | None = (
strawberry_django.filter_field()
)
@@ -436,7 +431,7 @@ class FrontPortTemplateFilter(ModularComponentTemplateFilterMixin):
@strawberry_django.filter_type(models.MACAddress, lookups=True)
class MACAddressFilter(PrimaryModelFilterMixin):
class MACAddressFilter(PrimaryModelFilter):
mac_address: FilterLookup[str] | None = strawberry_django.filter_field()
assigned_object_type: Annotated['ContentTypeFilter', strawberry.lazy('core.graphql.filters')] | None = (
strawberry_django.filter_field()
@@ -463,7 +458,12 @@ class MACAddressFilter(PrimaryModelFilterMixin):
@strawberry_django.filter_type(models.Interface, lookups=True)
class InterfaceFilter(ModularComponentModelFilterMixin, InterfaceBaseFilterMixin, CabledObjectModelFilterMixin):
class InterfaceFilter(
ModularComponentFilterMixin,
InterfaceBaseFilterMixin,
CabledObjectModelFilterMixin,
NetBoxModelFilter
):
vcdcs: Annotated['VirtualDeviceContextFilter', strawberry.lazy('dcim.graphql.filters')] | None = (
strawberry_django.filter_field()
)
@@ -553,7 +553,7 @@ class InterfaceFilter(ModularComponentModelFilterMixin, InterfaceBaseFilterMixin
@strawberry_django.filter_type(models.InterfaceTemplate, lookups=True)
class InterfaceTemplateFilter(ModularComponentTemplateFilterMixin):
class InterfaceTemplateFilter(ModularComponentTemplateFilterMixin, ChangeLoggedModelFilter):
type: BaseFilterLookup[Annotated['InterfaceTypeEnum', strawberry.lazy('dcim.graphql.enums')]] | None = (
strawberry_django.filter_field()
)
@@ -575,7 +575,7 @@ class InterfaceTemplateFilter(ModularComponentTemplateFilterMixin):
@strawberry_django.filter_type(models.InventoryItem, lookups=True)
class InventoryItemFilter(ComponentModelFilterMixin):
class InventoryItemFilter(ComponentModelFilterMixin, NetBoxModelFilter):
parent: Annotated['InventoryItemFilter', strawberry.lazy('dcim.graphql.filters')] | None = (
strawberry_django.filter_field()
)
@@ -602,14 +602,14 @@ class InventoryItemFilter(ComponentModelFilterMixin):
@strawberry_django.filter_type(models.InventoryItemRole, lookups=True)
class InventoryItemRoleFilter(OrganizationalModelFilterMixin):
class InventoryItemRoleFilter(OrganizationalModelFilter):
color: BaseFilterLookup[Annotated['ColorEnum', strawberry.lazy('netbox.graphql.enums')]] | None = (
strawberry_django.filter_field()
)
@strawberry_django.filter_type(models.Location, lookups=True)
class LocationFilter(ContactFilterMixin, ImageAttachmentFilterMixin, TenancyFilterMixin, NestedGroupModelFilterMixin):
class LocationFilter(ContactFilterMixin, ImageAttachmentFilterMixin, TenancyFilterMixin, NestedGroupModelFilter):
site: Annotated['SiteFilter', strawberry.lazy('dcim.graphql.filters')] | None = strawberry_django.filter_field()
site_id: ID | None = strawberry_django.filter_field()
status: BaseFilterLookup[Annotated['LocationStatusEnum', strawberry.lazy('dcim.graphql.enums')]] | None = (
@@ -625,12 +625,12 @@ class LocationFilter(ContactFilterMixin, ImageAttachmentFilterMixin, TenancyFilt
@strawberry_django.filter_type(models.Manufacturer, lookups=True)
class ManufacturerFilter(ContactFilterMixin, OrganizationalModelFilterMixin):
class ManufacturerFilter(ContactFilterMixin, OrganizationalModelFilter):
pass
@strawberry_django.filter_type(models.Module, lookups=True)
class ModuleFilter(PrimaryModelFilterMixin, ConfigContextFilterMixin):
class ModuleFilter(ConfigContextFilterMixin, PrimaryModelFilter):
device: Annotated['DeviceFilter', strawberry.lazy('dcim.graphql.filters')] | None = strawberry_django.filter_field()
device_id: ID | None = strawberry_django.filter_field()
module_bay: Annotated['ModuleBayFilter', strawberry.lazy('dcim.graphql.filters')] | None = (
@@ -679,7 +679,7 @@ class ModuleFilter(PrimaryModelFilterMixin, ConfigContextFilterMixin):
@strawberry_django.filter_type(models.ModuleBay, lookups=True)
class ModuleBayFilter(ModularComponentModelFilterMixin):
class ModuleBayFilter(ModularComponentFilterMixin, NetBoxModelFilter):
parent: Annotated['ModuleBayFilter', strawberry.lazy('dcim.graphql.filters')] | None = (
strawberry_django.filter_field()
)
@@ -688,17 +688,17 @@ class ModuleBayFilter(ModularComponentModelFilterMixin):
@strawberry_django.filter_type(models.ModuleBayTemplate, lookups=True)
class ModuleBayTemplateFilter(ModularComponentTemplateFilterMixin):
class ModuleBayTemplateFilter(ModularComponentTemplateFilterMixin, ChangeLoggedModelFilter):
position: FilterLookup[str] | None = strawberry_django.filter_field()
@strawberry_django.filter_type(models.ModuleTypeProfile, lookups=True)
class ModuleTypeProfileFilter(PrimaryModelFilterMixin):
class ModuleTypeProfileFilter(PrimaryModelFilter):
name: FilterLookup[str] | None = strawberry_django.filter_field()
@strawberry_django.filter_type(models.ModuleType, lookups=True)
class ModuleTypeFilter(ImageAttachmentFilterMixin, PrimaryModelFilterMixin, WeightFilterMixin):
class ModuleTypeFilter(ImageAttachmentFilterMixin, WeightFilterMixin, PrimaryModelFilter):
manufacturer: Annotated['ManufacturerFilter', strawberry.lazy('dcim.graphql.filters')] | None = (
strawberry_django.filter_field()
)
@@ -749,7 +749,7 @@ class ModuleTypeFilter(ImageAttachmentFilterMixin, PrimaryModelFilterMixin, Weig
@strawberry_django.filter_type(models.Platform, lookups=True)
class PlatformFilter(OrganizationalModelFilterMixin):
class PlatformFilter(OrganizationalModelFilter):
manufacturer: Annotated['ManufacturerFilter', strawberry.lazy('dcim.graphql.filters')] | None = (
strawberry_django.filter_field()
)
@@ -761,7 +761,7 @@ class PlatformFilter(OrganizationalModelFilterMixin):
@strawberry_django.filter_type(models.PowerFeed, lookups=True)
class PowerFeedFilter(CabledObjectModelFilterMixin, TenancyFilterMixin, PrimaryModelFilterMixin):
class PowerFeedFilter(CabledObjectModelFilterMixin, TenancyFilterMixin, PrimaryModelFilter):
power_panel: Annotated['PowerPanelFilter', strawberry.lazy('dcim.graphql.filters')] | None = (
strawberry_django.filter_field()
)
@@ -796,7 +796,7 @@ class PowerFeedFilter(CabledObjectModelFilterMixin, TenancyFilterMixin, PrimaryM
@strawberry_django.filter_type(models.PowerOutlet, lookups=True)
class PowerOutletFilter(ModularComponentModelFilterMixin, CabledObjectModelFilterMixin):
class PowerOutletFilter(ModularComponentFilterMixin, CabledObjectModelFilterMixin, NetBoxModelFilter):
type: BaseFilterLookup[Annotated['PowerOutletTypeEnum', strawberry.lazy('dcim.graphql.enums')]] | None = (
strawberry_django.filter_field()
)
@@ -816,7 +816,7 @@ class PowerOutletFilter(ModularComponentModelFilterMixin, CabledObjectModelFilte
@strawberry_django.filter_type(models.PowerOutletTemplate, lookups=True)
class PowerOutletTemplateFilter(ModularComponentModelFilterMixin):
class PowerOutletTemplateFilter(ModularComponentTemplateFilterMixin, ChangeLoggedModelFilter):
type: BaseFilterLookup[Annotated['PowerOutletTypeEnum', strawberry.lazy('dcim.graphql.enums')]] | None = (
strawberry_django.filter_field()
)
@@ -830,7 +830,7 @@ class PowerOutletTemplateFilter(ModularComponentModelFilterMixin):
@strawberry_django.filter_type(models.PowerPanel, lookups=True)
class PowerPanelFilter(ContactFilterMixin, ImageAttachmentFilterMixin, PrimaryModelFilterMixin):
class PowerPanelFilter(ContactFilterMixin, ImageAttachmentFilterMixin, PrimaryModelFilter):
site: Annotated['SiteFilter', strawberry.lazy('dcim.graphql.filters')] | None = strawberry_django.filter_field()
site_id: ID | None = strawberry_django.filter_field()
location: Annotated['LocationFilter', strawberry.lazy('dcim.graphql.filters')] | None = (
@@ -843,7 +843,7 @@ class PowerPanelFilter(ContactFilterMixin, ImageAttachmentFilterMixin, PrimaryMo
@strawberry_django.filter_type(models.PowerPort, lookups=True)
class PowerPortFilter(ModularComponentModelFilterMixin, CabledObjectModelFilterMixin):
class PowerPortFilter(ModularComponentFilterMixin, CabledObjectModelFilterMixin, NetBoxModelFilter):
type: BaseFilterLookup[Annotated['PowerPortTypeEnum', strawberry.lazy('dcim.graphql.enums')]] | None = (
strawberry_django.filter_field()
)
@@ -856,7 +856,7 @@ class PowerPortFilter(ModularComponentModelFilterMixin, CabledObjectModelFilterM
@strawberry_django.filter_type(models.PowerPortTemplate, lookups=True)
class PowerPortTemplateFilter(ModularComponentTemplateFilterMixin):
class PowerPortTemplateFilter(ModularComponentTemplateFilterMixin, ChangeLoggedModelFilter):
type: BaseFilterLookup[Annotated['PowerPortTypeEnum', strawberry.lazy('dcim.graphql.enums')]] | None = (
strawberry_django.filter_field()
)
@@ -869,7 +869,7 @@ class PowerPortTemplateFilter(ModularComponentTemplateFilterMixin):
@strawberry_django.filter_type(models.RackType, lookups=True)
class RackTypeFilter(RackBaseFilterMixin):
class RackTypeFilter(RackFilterMixin, WeightFilterMixin, PrimaryModelFilter):
form_factor: BaseFilterLookup[Annotated['RackFormFactorEnum', strawberry.lazy('dcim.graphql.enums')]] | None = (
strawberry_django.filter_field()
)
@@ -884,7 +884,14 @@ class RackTypeFilter(RackBaseFilterMixin):
@strawberry_django.filter_type(models.Rack, lookups=True)
class RackFilter(ContactFilterMixin, ImageAttachmentFilterMixin, TenancyFilterMixin, RackBaseFilterMixin):
class RackFilter(
ContactFilterMixin,
ImageAttachmentFilterMixin,
TenancyFilterMixin,
WeightFilterMixin,
RackFilterMixin,
PrimaryModelFilter
):
form_factor: BaseFilterLookup[Annotated['RackFormFactorEnum', strawberry.lazy('dcim.graphql.enums')]] | None = (
strawberry_django.filter_field()
)
@@ -918,7 +925,7 @@ class RackFilter(ContactFilterMixin, ImageAttachmentFilterMixin, TenancyFilterMi
@strawberry_django.filter_type(models.RackReservation, lookups=True)
class RackReservationFilter(TenancyFilterMixin, PrimaryModelFilterMixin):
class RackReservationFilter(TenancyFilterMixin, PrimaryModelFilter):
rack: Annotated['RackFilter', strawberry.lazy('dcim.graphql.filters')] | None = strawberry_django.filter_field()
rack_id: ID | None = strawberry_django.filter_field()
units: Annotated['IntegerArrayLookup', strawberry.lazy('netbox.graphql.filter_lookups')] | None = (
@@ -933,14 +940,14 @@ class RackReservationFilter(TenancyFilterMixin, PrimaryModelFilterMixin):
@strawberry_django.filter_type(models.RackRole, lookups=True)
class RackRoleFilter(OrganizationalModelFilterMixin):
class RackRoleFilter(OrganizationalModelFilter):
color: BaseFilterLookup[Annotated['ColorEnum', strawberry.lazy('netbox.graphql.enums')]] | None = (
strawberry_django.filter_field()
)
@strawberry_django.filter_type(models.RearPort, lookups=True)
class RearPortFilter(ModularComponentModelFilterMixin, CabledObjectModelFilterMixin):
class RearPortFilter(ModularComponentFilterMixin, CabledObjectModelFilterMixin, NetBoxModelFilter):
type: BaseFilterLookup[Annotated['PortTypeEnum', strawberry.lazy('dcim.graphql.enums')]] | None = (
strawberry_django.filter_field()
)
@@ -953,7 +960,7 @@ class RearPortFilter(ModularComponentModelFilterMixin, CabledObjectModelFilterMi
@strawberry_django.filter_type(models.RearPortTemplate, lookups=True)
class RearPortTemplateFilter(ModularComponentTemplateFilterMixin):
class RearPortTemplateFilter(ModularComponentTemplateFilterMixin, ChangeLoggedModelFilter):
type: BaseFilterLookup[Annotated['PortTypeEnum', strawberry.lazy('dcim.graphql.enums')]] | None = (
strawberry_django.filter_field()
)
@@ -966,7 +973,7 @@ class RearPortTemplateFilter(ModularComponentTemplateFilterMixin):
@strawberry_django.filter_type(models.Region, lookups=True)
class RegionFilter(ContactFilterMixin, NestedGroupModelFilterMixin):
class RegionFilter(ContactFilterMixin, NestedGroupModelFilter):
prefixes: Annotated['PrefixFilter', strawberry.lazy('ipam.graphql.filters')] | None = (
strawberry_django.filter_field()
)
@@ -976,7 +983,7 @@ class RegionFilter(ContactFilterMixin, NestedGroupModelFilterMixin):
@strawberry_django.filter_type(models.Site, lookups=True)
class SiteFilter(ContactFilterMixin, ImageAttachmentFilterMixin, TenancyFilterMixin, PrimaryModelFilterMixin):
class SiteFilter(ContactFilterMixin, ImageAttachmentFilterMixin, TenancyFilterMixin, PrimaryModelFilter):
name: FilterLookup[str] | None = strawberry_django.filter_field()
slug: FilterLookup[str] | None = strawberry_django.filter_field()
status: BaseFilterLookup[Annotated['SiteStatusEnum', strawberry.lazy('dcim.graphql.enums')]] | None = (
@@ -1012,7 +1019,7 @@ class SiteFilter(ContactFilterMixin, ImageAttachmentFilterMixin, TenancyFilterMi
@strawberry_django.filter_type(models.SiteGroup, lookups=True)
class SiteGroupFilter(ContactFilterMixin, NestedGroupModelFilterMixin):
class SiteGroupFilter(ContactFilterMixin, NestedGroupModelFilter):
prefixes: Annotated['PrefixFilter', strawberry.lazy('ipam.graphql.filters')] | None = (
strawberry_django.filter_field()
)
@@ -1022,7 +1029,7 @@ class SiteGroupFilter(ContactFilterMixin, NestedGroupModelFilterMixin):
@strawberry_django.filter_type(models.VirtualChassis, lookups=True)
class VirtualChassisFilter(PrimaryModelFilterMixin):
class VirtualChassisFilter(PrimaryModelFilter):
master: Annotated['DeviceFilter', strawberry.lazy('dcim.graphql.filters')] | None = strawberry_django.filter_field()
master_id: ID | None = strawberry_django.filter_field()
name: FilterLookup[str] | None = strawberry_django.filter_field()
@@ -1034,7 +1041,7 @@ class VirtualChassisFilter(PrimaryModelFilterMixin):
@strawberry_django.filter_type(models.VirtualDeviceContext, lookups=True)
class VirtualDeviceContextFilter(TenancyFilterMixin, PrimaryModelFilterMixin):
class VirtualDeviceContextFilter(TenancyFilterMixin, PrimaryModelFilter):
device: Annotated['DeviceFilter', strawberry.lazy('dcim.graphql.filters')] | None = strawberry_django.filter_field()
device_id: ID | None = strawberry_django.filter_field()
name: FilterLookup[str] | None = strawberry_django.filter_field()

View File

@@ -3,9 +3,6 @@ from typing import Annotated, TYPE_CHECKING
import strawberry
import strawberry_django
from strawberry_django import FilterLookup
from core.graphql.filter_mixins import BaseFilterMixin
if TYPE_CHECKING:
from netbox.graphql.filter_lookups import JSONFilter
@@ -16,37 +13,30 @@ __all__ = (
'JournalEntriesFilterMixin',
'TagsFilterMixin',
'ConfigContextFilterMixin',
'TagBaseFilterMixin',
)
@dataclass
class CustomFieldsFilterMixin(BaseFilterMixin):
class CustomFieldsFilterMixin:
custom_field_data: Annotated['JSONFilter', strawberry.lazy('netbox.graphql.filter_lookups')] | None = (
strawberry_django.filter_field()
)
@dataclass
class JournalEntriesFilterMixin(BaseFilterMixin):
class JournalEntriesFilterMixin:
journal_entries: Annotated['JournalEntryFilter', strawberry.lazy('extras.graphql.filters')] | None = (
strawberry_django.filter_field()
)
@dataclass
class TagsFilterMixin(BaseFilterMixin):
class TagsFilterMixin:
tags: Annotated['TagFilter', strawberry.lazy('extras.graphql.filters')] | None = strawberry_django.filter_field()
@dataclass
class ConfigContextFilterMixin(BaseFilterMixin):
class ConfigContextFilterMixin:
local_context_data: Annotated['JSONFilter', strawberry.lazy('netbox.graphql.filter_lookups')] | None = (
strawberry_django.filter_field()
)
@dataclass
class TagBaseFilterMixin(BaseFilterMixin):
name: FilterLookup[str] | None = strawberry_django.filter_field()
slug: FilterLookup[str] | None = strawberry_django.filter_field()

View File

@@ -5,10 +5,10 @@ import strawberry_django
from strawberry.scalars import ID
from strawberry_django import BaseFilterLookup, FilterLookup
from core.graphql.filter_mixins import BaseObjectTypeFilterMixin, ChangeLogFilterMixin
from extras import models
from extras.graphql.filter_mixins import TagBaseFilterMixin, CustomFieldsFilterMixin, TagsFilterMixin
from netbox.graphql.filter_mixins import PrimaryModelFilterMixin, SyncedDataFilterMixin
from extras.graphql.filter_mixins import CustomFieldsFilterMixin, TagsFilterMixin
from netbox.graphql.filter_mixins import SyncedDataFilterMixin
from netbox.graphql.filters import ChangeLoggedModelFilter, PrimaryModelFilter
if TYPE_CHECKING:
from core.graphql.filters import ContentTypeFilter
@@ -42,7 +42,7 @@ __all__ = (
@strawberry_django.filter_type(models.ConfigContext, lookups=True)
class ConfigContextFilter(BaseObjectTypeFilterMixin, SyncedDataFilterMixin, ChangeLogFilterMixin):
class ConfigContextFilter(SyncedDataFilterMixin, ChangeLoggedModelFilter):
name: FilterLookup[str] | None = strawberry_django.filter_field()
weight: Annotated['IntegerLookup', strawberry.lazy('netbox.graphql.filter_lookups')] | None = (
strawberry_django.filter_field()
@@ -99,14 +99,14 @@ class ConfigContextFilter(BaseObjectTypeFilterMixin, SyncedDataFilterMixin, Chan
@strawberry_django.filter_type(models.ConfigContextProfile, lookups=True)
class ConfigContextProfileFilter(SyncedDataFilterMixin, PrimaryModelFilterMixin):
class ConfigContextProfileFilter(SyncedDataFilterMixin, PrimaryModelFilter):
name: FilterLookup[str] = strawberry_django.filter_field()
description: FilterLookup[str] = strawberry_django.filter_field()
tags: Annotated['TagFilter', strawberry.lazy('extras.graphql.filters')] | None = strawberry_django.filter_field()
@strawberry_django.filter_type(models.ConfigTemplate, lookups=True)
class ConfigTemplateFilter(BaseObjectTypeFilterMixin, SyncedDataFilterMixin, ChangeLogFilterMixin):
class ConfigTemplateFilter(SyncedDataFilterMixin, ChangeLoggedModelFilter):
name: FilterLookup[str] | None = strawberry_django.filter_field()
description: FilterLookup[str] | None = strawberry_django.filter_field()
template_code: FilterLookup[str] | None = strawberry_django.filter_field()
@@ -120,7 +120,7 @@ class ConfigTemplateFilter(BaseObjectTypeFilterMixin, SyncedDataFilterMixin, Cha
@strawberry_django.filter_type(models.CustomField, lookups=True)
class CustomFieldFilter(BaseObjectTypeFilterMixin, ChangeLogFilterMixin):
class CustomFieldFilter(ChangeLoggedModelFilter):
type: BaseFilterLookup[Annotated['CustomFieldTypeEnum', strawberry.lazy('extras.graphql.enums')]] | None = (
strawberry_django.filter_field()
)
@@ -179,7 +179,7 @@ class CustomFieldFilter(BaseObjectTypeFilterMixin, ChangeLogFilterMixin):
@strawberry_django.filter_type(models.CustomFieldChoiceSet, lookups=True)
class CustomFieldChoiceSetFilter(BaseObjectTypeFilterMixin, ChangeLogFilterMixin):
class CustomFieldChoiceSetFilter(ChangeLoggedModelFilter):
name: FilterLookup[str] | None = strawberry_django.filter_field()
description: FilterLookup[str] | None = strawberry_django.filter_field()
base_choices: (
@@ -194,7 +194,7 @@ class CustomFieldChoiceSetFilter(BaseObjectTypeFilterMixin, ChangeLogFilterMixin
@strawberry_django.filter_type(models.CustomLink, lookups=True)
class CustomLinkFilter(BaseObjectTypeFilterMixin, ChangeLogFilterMixin):
class CustomLinkFilter(ChangeLoggedModelFilter):
name: FilterLookup[str] | None = strawberry_django.filter_field()
enabled: FilterLookup[bool] | None = strawberry_django.filter_field()
link_text: FilterLookup[str] | None = strawberry_django.filter_field()
@@ -212,7 +212,7 @@ class CustomLinkFilter(BaseObjectTypeFilterMixin, ChangeLogFilterMixin):
@strawberry_django.filter_type(models.ExportTemplate, lookups=True)
class ExportTemplateFilter(BaseObjectTypeFilterMixin, SyncedDataFilterMixin, ChangeLogFilterMixin):
class ExportTemplateFilter(SyncedDataFilterMixin, ChangeLoggedModelFilter):
name: FilterLookup[str] | None = strawberry_django.filter_field()
description: FilterLookup[str] | None = strawberry_django.filter_field()
template_code: FilterLookup[str] | None = strawberry_django.filter_field()
@@ -226,7 +226,7 @@ class ExportTemplateFilter(BaseObjectTypeFilterMixin, SyncedDataFilterMixin, Cha
@strawberry_django.filter_type(models.ImageAttachment, lookups=True)
class ImageAttachmentFilter(BaseObjectTypeFilterMixin, ChangeLogFilterMixin):
class ImageAttachmentFilter(ChangeLoggedModelFilter):
object_type: Annotated['ContentTypeFilter', strawberry.lazy('core.graphql.filters')] | None = (
strawberry_django.filter_field()
)
@@ -241,7 +241,7 @@ class ImageAttachmentFilter(BaseObjectTypeFilterMixin, ChangeLogFilterMixin):
@strawberry_django.filter_type(models.JournalEntry, lookups=True)
class JournalEntryFilter(BaseObjectTypeFilterMixin, CustomFieldsFilterMixin, TagsFilterMixin, ChangeLogFilterMixin):
class JournalEntryFilter(CustomFieldsFilterMixin, TagsFilterMixin, ChangeLoggedModelFilter):
assigned_object_type: Annotated['ContentTypeFilter', strawberry.lazy('core.graphql.filters')] | None = (
strawberry_django.filter_field()
)
@@ -257,7 +257,7 @@ class JournalEntryFilter(BaseObjectTypeFilterMixin, CustomFieldsFilterMixin, Tag
@strawberry_django.filter_type(models.NotificationGroup, lookups=True)
class NotificationGroupFilter(BaseObjectTypeFilterMixin, ChangeLogFilterMixin):
class NotificationGroupFilter(ChangeLoggedModelFilter):
name: FilterLookup[str] | None = strawberry_django.filter_field()
description: FilterLookup[str] | None = strawberry_django.filter_field()
groups: Annotated['GroupFilter', strawberry.lazy('users.graphql.filters')] | None = strawberry_django.filter_field()
@@ -265,7 +265,7 @@ class NotificationGroupFilter(BaseObjectTypeFilterMixin, ChangeLogFilterMixin):
@strawberry_django.filter_type(models.SavedFilter, lookups=True)
class SavedFilterFilter(BaseObjectTypeFilterMixin, ChangeLogFilterMixin):
class SavedFilterFilter(ChangeLoggedModelFilter):
name: FilterLookup[str] | None = strawberry_django.filter_field()
slug: FilterLookup[str] | None = strawberry_django.filter_field()
description: FilterLookup[str] | None = strawberry_django.filter_field()
@@ -282,7 +282,7 @@ class SavedFilterFilter(BaseObjectTypeFilterMixin, ChangeLogFilterMixin):
@strawberry_django.filter_type(models.TableConfig, lookups=True)
class TableConfigFilter(BaseObjectTypeFilterMixin, ChangeLogFilterMixin):
class TableConfigFilter(ChangeLoggedModelFilter):
name: FilterLookup[str] | None = strawberry_django.filter_field()
description: FilterLookup[str] | None = strawberry_django.filter_field()
user: Annotated['UserFilter', strawberry.lazy('users.graphql.filters')] | None = strawberry_django.filter_field()
@@ -295,7 +295,9 @@ class TableConfigFilter(BaseObjectTypeFilterMixin, ChangeLogFilterMixin):
@strawberry_django.filter_type(models.Tag, lookups=True)
class TagFilter(BaseObjectTypeFilterMixin, ChangeLogFilterMixin, TagBaseFilterMixin):
class TagFilter(ChangeLoggedModelFilter):
name: FilterLookup[str] | None = strawberry_django.filter_field()
slug: FilterLookup[str] | None = strawberry_django.filter_field()
color: BaseFilterLookup[Annotated['ColorEnum', strawberry.lazy('netbox.graphql.enums')]] | None = (
strawberry_django.filter_field()
)
@@ -303,7 +305,7 @@ class TagFilter(BaseObjectTypeFilterMixin, ChangeLogFilterMixin, TagBaseFilterMi
@strawberry_django.filter_type(models.Webhook, lookups=True)
class WebhookFilter(BaseObjectTypeFilterMixin, CustomFieldsFilterMixin, TagsFilterMixin, ChangeLogFilterMixin):
class WebhookFilter(CustomFieldsFilterMixin, TagsFilterMixin, ChangeLoggedModelFilter):
name: FilterLookup[str] | None = strawberry_django.filter_field()
description: FilterLookup[str] | None = strawberry_django.filter_field()
payload_url: FilterLookup[str] | None = strawberry_django.filter_field()
@@ -324,7 +326,7 @@ class WebhookFilter(BaseObjectTypeFilterMixin, CustomFieldsFilterMixin, TagsFilt
@strawberry_django.filter_type(models.EventRule, lookups=True)
class EventRuleFilter(BaseObjectTypeFilterMixin, CustomFieldsFilterMixin, TagsFilterMixin, ChangeLogFilterMixin):
class EventRuleFilter(CustomFieldsFilterMixin, TagsFilterMixin, ChangeLoggedModelFilter):
name: FilterLookup[str] | None = strawberry_django.filter_field()
description: FilterLookup[str] | None = strawberry_django.filter_field()
event_types: Annotated['StringArrayLookup', strawberry.lazy('netbox.graphql.filter_lookups')] | None = (

View File

@@ -3,21 +3,20 @@ from typing import Annotated, TYPE_CHECKING
import strawberry
import strawberry_django
from core.graphql.filter_mixins import BaseFilterMixin
from strawberry_django import BaseFilterLookup
if TYPE_CHECKING:
from netbox.graphql.filter_lookups import IntegerLookup
from .enums import *
__all__ = (
'ServiceBaseFilterMixin',
'ServiceFilterMixin',
)
@dataclass
class ServiceBaseFilterMixin(BaseFilterMixin):
protocol: Annotated['ServiceProtocolEnum', strawberry.lazy('ipam.graphql.enums')] | None = (
class ServiceFilterMixin:
protocol: BaseFilterLookup[Annotated['ServiceProtocolEnum', strawberry.lazy('ipam.graphql.enums')]] | None = (
strawberry_django.filter_field()
)
ports: Annotated['IntegerLookup', strawberry.lazy('netbox.graphql.filter_lookups')] | None = (

View File

@@ -9,12 +9,13 @@ from netaddr.core import AddrFormatError
from strawberry.scalars import ID
from strawberry_django import BaseFilterLookup, FilterLookup, DateFilterLookup
from core.graphql.filter_mixins import BaseObjectTypeFilterMixin, ChangeLogFilterMixin
from dcim.graphql.filter_mixins import ScopedFilterMixin
from dcim.models import Device
from ipam import models
from ipam.graphql.filter_mixins import ServiceBaseFilterMixin
from netbox.graphql.filter_mixins import NetBoxModelFilterMixin, OrganizationalModelFilterMixin, PrimaryModelFilterMixin
from ipam.graphql.filter_mixins import ServiceFilterMixin
from netbox.graphql.filters import (
ChangeLoggedModelFilter, NetBoxModelFilter, OrganizationalModelFilter, PrimaryModelFilter,
)
from tenancy.graphql.filter_mixins import ContactFilterMixin, TenancyFilterMixin
from virtualization.models import VMInterface
@@ -49,7 +50,7 @@ __all__ = (
@strawberry_django.filter_type(models.ASN, lookups=True)
class ASNFilter(TenancyFilterMixin, PrimaryModelFilterMixin):
class ASNFilter(TenancyFilterMixin, PrimaryModelFilter):
rir: Annotated['RIRFilter', strawberry.lazy('ipam.graphql.filters')] | None = strawberry_django.filter_field()
rir_id: ID | None = strawberry_django.filter_field()
asn: Annotated['IntegerLookup', strawberry.lazy('netbox.graphql.filter_lookups')] | None = (
@@ -64,7 +65,7 @@ class ASNFilter(TenancyFilterMixin, PrimaryModelFilterMixin):
@strawberry_django.filter_type(models.ASNRange, lookups=True)
class ASNRangeFilter(TenancyFilterMixin, OrganizationalModelFilterMixin):
class ASNRangeFilter(TenancyFilterMixin, OrganizationalModelFilter):
name: 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()
@@ -78,7 +79,7 @@ class ASNRangeFilter(TenancyFilterMixin, OrganizationalModelFilterMixin):
@strawberry_django.filter_type(models.Aggregate, lookups=True)
class AggregateFilter(ContactFilterMixin, TenancyFilterMixin, PrimaryModelFilterMixin):
class AggregateFilter(ContactFilterMixin, TenancyFilterMixin, PrimaryModelFilter):
prefix: FilterLookup[str] | 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()
@@ -111,7 +112,7 @@ class AggregateFilter(ContactFilterMixin, TenancyFilterMixin, PrimaryModelFilter
@strawberry_django.filter_type(models.FHRPGroup, lookups=True)
class FHRPGroupFilter(PrimaryModelFilterMixin):
class FHRPGroupFilter(PrimaryModelFilter):
group_id: Annotated['IntegerLookup', strawberry.lazy('netbox.graphql.filter_lookups')] | None = (
strawberry_django.filter_field()
)
@@ -129,7 +130,7 @@ class FHRPGroupFilter(PrimaryModelFilterMixin):
@strawberry_django.filter_type(models.FHRPGroupAssignment, lookups=True)
class FHRPGroupAssignmentFilter(BaseObjectTypeFilterMixin, ChangeLogFilterMixin):
class FHRPGroupAssignmentFilter(ChangeLoggedModelFilter):
interface_type: Annotated['ContentTypeFilter', strawberry.lazy('core.graphql.filters')] | None = (
strawberry_django.filter_field()
)
@@ -168,7 +169,7 @@ class FHRPGroupAssignmentFilter(BaseObjectTypeFilterMixin, ChangeLogFilterMixin)
@strawberry_django.filter_type(models.IPAddress, lookups=True)
class IPAddressFilter(ContactFilterMixin, TenancyFilterMixin, PrimaryModelFilterMixin):
class IPAddressFilter(ContactFilterMixin, TenancyFilterMixin, PrimaryModelFilter):
address: FilterLookup[str] | None = strawberry_django.filter_field()
vrf: Annotated['VRFFilter', strawberry.lazy('ipam.graphql.filters')] | None = strawberry_django.filter_field()
vrf_id: ID | None = strawberry_django.filter_field()
@@ -219,7 +220,7 @@ class IPAddressFilter(ContactFilterMixin, TenancyFilterMixin, PrimaryModelFilter
@strawberry_django.filter_type(models.IPRange, lookups=True)
class IPRangeFilter(ContactFilterMixin, TenancyFilterMixin, PrimaryModelFilterMixin):
class IPRangeFilter(ContactFilterMixin, TenancyFilterMixin, PrimaryModelFilter):
start_address: FilterLookup[str] | None = strawberry_django.filter_field()
end_address: FilterLookup[str] | None = strawberry_django.filter_field()
size: Annotated['IntegerLookup', strawberry.lazy('netbox.graphql.filter_lookups')] | None = (
@@ -273,7 +274,7 @@ class IPRangeFilter(ContactFilterMixin, TenancyFilterMixin, PrimaryModelFilterMi
@strawberry_django.filter_type(models.Prefix, lookups=True)
class PrefixFilter(ContactFilterMixin, ScopedFilterMixin, TenancyFilterMixin, PrimaryModelFilterMixin):
class PrefixFilter(ContactFilterMixin, ScopedFilterMixin, TenancyFilterMixin, PrimaryModelFilter):
prefix: FilterLookup[str] | None = strawberry_django.filter_field()
vrf: Annotated['VRFFilter', strawberry.lazy('ipam.graphql.filters')] | None = strawberry_django.filter_field()
vrf_id: ID | None = strawberry_django.filter_field()
@@ -310,19 +311,19 @@ class PrefixFilter(ContactFilterMixin, ScopedFilterMixin, TenancyFilterMixin, Pr
@strawberry_django.filter_type(models.RIR, lookups=True)
class RIRFilter(OrganizationalModelFilterMixin):
class RIRFilter(OrganizationalModelFilter):
is_private: FilterLookup[bool] | None = strawberry_django.filter_field()
@strawberry_django.filter_type(models.Role, lookups=True)
class RoleFilter(OrganizationalModelFilterMixin):
class RoleFilter(OrganizationalModelFilter):
weight: Annotated['IntegerLookup', strawberry.lazy('netbox.graphql.filter_lookups')] | None = (
strawberry_django.filter_field()
)
@strawberry_django.filter_type(models.RouteTarget, lookups=True)
class RouteTargetFilter(TenancyFilterMixin, PrimaryModelFilterMixin):
class RouteTargetFilter(TenancyFilterMixin, PrimaryModelFilter):
name: FilterLookup[str] | None = strawberry_django.filter_field()
importing_vrfs: Annotated['VRFFilter', strawberry.lazy('ipam.graphql.filters')] | None = (
strawberry_django.filter_field()
@@ -339,7 +340,7 @@ class RouteTargetFilter(TenancyFilterMixin, PrimaryModelFilterMixin):
@strawberry_django.filter_type(models.Service, lookups=True)
class ServiceFilter(ContactFilterMixin, ServiceBaseFilterMixin, PrimaryModelFilterMixin):
class ServiceFilter(ContactFilterMixin, ServiceFilterMixin, PrimaryModelFilter):
name: FilterLookup[str] | None = strawberry_django.filter_field()
ip_addresses: Annotated['IPAddressFilter', strawberry.lazy('ipam.graphql.filters')] | None = (
strawberry_django.filter_field()
@@ -351,12 +352,12 @@ class ServiceFilter(ContactFilterMixin, ServiceBaseFilterMixin, PrimaryModelFilt
@strawberry_django.filter_type(models.ServiceTemplate, lookups=True)
class ServiceTemplateFilter(ServiceBaseFilterMixin, PrimaryModelFilterMixin):
class ServiceTemplateFilter(ServiceFilterMixin, PrimaryModelFilter):
name: FilterLookup[str] | None = strawberry_django.filter_field()
@strawberry_django.filter_type(models.VLAN, lookups=True)
class VLANFilter(TenancyFilterMixin, PrimaryModelFilterMixin):
class VLANFilter(TenancyFilterMixin, PrimaryModelFilter):
site: Annotated['SiteFilter', strawberry.lazy('dcim.graphql.filters')] | None = strawberry_django.filter_field()
site_id: ID | None = strawberry_django.filter_field()
group: Annotated['VLANGroupFilter', strawberry.lazy('ipam.graphql.filters')] | None = (
@@ -388,19 +389,19 @@ class VLANFilter(TenancyFilterMixin, PrimaryModelFilterMixin):
@strawberry_django.filter_type(models.VLANGroup, lookups=True)
class VLANGroupFilter(ScopedFilterMixin, OrganizationalModelFilterMixin):
class VLANGroupFilter(ScopedFilterMixin, OrganizationalModelFilter):
vid_ranges: Annotated['IntegerRangeArrayLookup', strawberry.lazy('netbox.graphql.filter_lookups')] | None = (
strawberry_django.filter_field()
)
@strawberry_django.filter_type(models.VLANTranslationPolicy, lookups=True)
class VLANTranslationPolicyFilter(PrimaryModelFilterMixin):
class VLANTranslationPolicyFilter(PrimaryModelFilter):
name: FilterLookup[str] | None = strawberry_django.filter_field()
@strawberry_django.filter_type(models.VLANTranslationRule, lookups=True)
class VLANTranslationRuleFilter(NetBoxModelFilterMixin):
class VLANTranslationRuleFilter(NetBoxModelFilter):
policy: Annotated['VLANTranslationPolicyFilter', strawberry.lazy('ipam.graphql.filters')] | None = (
strawberry_django.filter_field()
)
@@ -415,7 +416,7 @@ class VLANTranslationRuleFilter(NetBoxModelFilterMixin):
@strawberry_django.filter_type(models.VRF, lookups=True)
class VRFFilter(TenancyFilterMixin, PrimaryModelFilterMixin):
class VRFFilter(TenancyFilterMixin, PrimaryModelFilter):
name: FilterLookup[str] | None = strawberry_django.filter_field()
rd: FilterLookup[str] | None = strawberry_django.filter_field()
enforce_unique: FilterLookup[bool] | None = strawberry_django.filter_field()

View File

@@ -5,6 +5,7 @@ from django.conf import settings
from django_rq.queues import get_connection
from drf_spectacular.types import OpenApiTypes
from drf_spectacular.utils import extend_schema
from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response
from rest_framework.reverse import reverse
from rest_framework.views import APIView
@@ -12,6 +13,7 @@ from rq.worker import Worker
from netbox.api.authentication import IsAuthenticatedOrLoginNotRequired
from netbox.plugins.utils import get_installed_plugins
from users.api.serializers import UserSerializer
from utilities.apps import get_installed_apps
@@ -62,3 +64,15 @@ class StatusView(APIView):
'python-version': platform.python_version(),
'rq-workers-running': Worker.count(get_connection('default')),
})
class AuthenticationCheckView(APIView):
"""
Return the user making the request, if authenticated successfully.
"""
permission_classes = [IsAuthenticated]
@extend_schema(responses={200: OpenApiTypes.OBJECT})
def get(self, request):
serializer = UserSerializer(request.user, context={'request': request})
return Response(serializer.data)

View File

@@ -4,19 +4,11 @@ from typing import TypeVar, TYPE_CHECKING, Annotated
import strawberry
import strawberry_django
from strawberry import ID
from strawberry_django import BaseFilterLookup, FilterLookup, DatetimeFilterLookup
from core.graphql.filter_mixins import BaseFilterMixin, BaseObjectTypeFilterMixin, ChangeLogFilterMixin
from extras.graphql.filter_mixins import CustomFieldsFilterMixin, JournalEntriesFilterMixin, TagsFilterMixin
__all__ = (
'DistanceFilterMixin',
'ImageAttachmentFilterMixin',
'NestedGroupModelFilterMixin',
'NetBoxModelFilterMixin',
'OrganizationalModelFilterMixin',
'PrimaryModelFilterMixin',
'SyncedDataFilterMixin',
'WeightFilterMixin',
)
@@ -30,51 +22,15 @@ if TYPE_CHECKING:
from extras.graphql.filters import *
class NetBoxModelFilterMixin(
ChangeLogFilterMixin,
CustomFieldsFilterMixin,
JournalEntriesFilterMixin,
TagsFilterMixin,
BaseObjectTypeFilterMixin,
):
pass
@dataclass
class NestedGroupModelFilterMixin(NetBoxModelFilterMixin):
name: FilterLookup[str] | None = strawberry_django.filter_field()
slug: FilterLookup[str] | None = strawberry_django.filter_field()
description: FilterLookup[str] | None = strawberry_django.filter_field()
parent_id: ID | None = strawberry_django.filter_field()
@dataclass
class OrganizationalModelFilterMixin(
ChangeLogFilterMixin,
CustomFieldsFilterMixin,
TagsFilterMixin,
BaseObjectTypeFilterMixin,
):
name: FilterLookup[str] | None = strawberry_django.filter_field()
slug: FilterLookup[str] | None = strawberry_django.filter_field()
description: FilterLookup[str] | None = strawberry_django.filter_field()
@dataclass
class PrimaryModelFilterMixin(NetBoxModelFilterMixin):
description: FilterLookup[str] | None = strawberry_django.filter_field()
comments: FilterLookup[str] | None = strawberry_django.filter_field()
@dataclass
class ImageAttachmentFilterMixin(BaseFilterMixin):
class ImageAttachmentFilterMixin:
images: Annotated['ImageAttachmentFilter', strawberry.lazy('extras.graphql.filters')] | None = (
strawberry_django.filter_field()
)
@dataclass
class WeightFilterMixin(BaseFilterMixin):
class WeightFilterMixin:
weight: FilterLookup[float] | None = strawberry_django.filter_field()
weight_unit: BaseFilterLookup[Annotated['WeightUnitEnum', strawberry.lazy('netbox.graphql.enums')]] | None = (
strawberry_django.filter_field()
@@ -82,7 +38,7 @@ class WeightFilterMixin(BaseFilterMixin):
@dataclass
class SyncedDataFilterMixin(BaseFilterMixin):
class SyncedDataFilterMixin:
data_source: Annotated['DataSourceFilter', strawberry.lazy('core.graphql.filters')] | None = (
strawberry_django.filter_field()
)
@@ -97,7 +53,7 @@ class SyncedDataFilterMixin(BaseFilterMixin):
@dataclass
class DistanceFilterMixin(BaseFilterMixin):
class DistanceFilterMixin:
distance: FilterLookup[float] | None = strawberry_django.filter_field()
distance_unit: BaseFilterLookup[Annotated['DistanceUnitEnum', strawberry.lazy('netbox.graphql.enums')]] | None = (
strawberry_django.filter_field()

View File

@@ -0,0 +1,61 @@
from dataclasses import dataclass
from typing import TYPE_CHECKING
import strawberry_django
from strawberry import ID
from strawberry_django import FilterLookup
from core.graphql.filter_mixins import ChangeLoggingMixin
from extras.graphql.filter_mixins import CustomFieldsFilterMixin, JournalEntriesFilterMixin, TagsFilterMixin
if TYPE_CHECKING:
from .filters import *
__all__ = (
'BaseModelFilter',
'ChangeLoggedModelFilter',
'NestedGroupModelFilter',
'NetBoxModelFilter',
'OrganizationalModelFilter',
'PrimaryModelFilter',
)
@dataclass
class BaseModelFilter:
id: FilterLookup[ID] | None = strawberry_django.filter_field()
class ChangeLoggedModelFilter(ChangeLoggingMixin, BaseModelFilter):
pass
class NetBoxModelFilter(
CustomFieldsFilterMixin,
JournalEntriesFilterMixin,
TagsFilterMixin,
ChangeLoggingMixin,
BaseModelFilter
):
pass
@dataclass
class NestedGroupModelFilter(NetBoxModelFilter):
name: FilterLookup[str] | None = strawberry_django.filter_field()
slug: FilterLookup[str] | None = strawberry_django.filter_field()
description: FilterLookup[str] | None = strawberry_django.filter_field()
parent_id: ID | None = strawberry_django.filter_field()
@dataclass
class OrganizationalModelFilter(NetBoxModelFilter):
name: FilterLookup[str] | None = strawberry_django.filter_field()
slug: FilterLookup[str] | None = strawberry_django.filter_field()
description: FilterLookup[str] | None = strawberry_django.filter_field()
@dataclass
class PrimaryModelFilter(NetBoxModelFilter):
description: FilterLookup[str] | None = strawberry_django.filter_field()
comments: FilterLookup[str] | None = strawberry_django.filter_field()

View File

@@ -32,6 +32,18 @@ class AppTest(APITestCase):
self.assertEqual(response.status_code, 200)
def test_authentication_check(self):
url = reverse('api-authentication-check')
# Test an unauthenticated request
response = self.client.get(f'{url}')
self.assertEqual(response.status_code, 403)
# Test an authenticated request
response = self.client.get(f'{url}', **self.header)
self.assertEqual(response.status_code, 200)
self.assertEqual(response.data['id'], self.user.pk)
class OptionalLimitOffsetPaginationTest(TestCase):

View File

@@ -5,7 +5,7 @@ from django.views.decorators.cache import cache_page
from drf_spectacular.views import SpectacularAPIView, SpectacularRedocView, SpectacularSwaggerView
from account.views import LoginView, LogoutView
from netbox.api.views import APIRootView, StatusView
from netbox.api.views import APIRootView, AuthenticationCheckView, StatusView
from netbox.graphql.schema import schema
from netbox.graphql.views import NetBoxGraphQLView
from netbox.plugins.urls import plugin_patterns, plugin_api_patterns
@@ -53,6 +53,7 @@ _patterns = [
path('api/vpn/', include('vpn.api.urls')),
path('api/wireless/', include('wireless.api.urls')),
path('api/status/', StatusView.as_view(), name='api-status'),
path('api/authentication-check/', AuthenticationCheckView.as_view(), name='api-authentication-check'),
# REST API schema
path(

View File

@@ -5,8 +5,6 @@ import strawberry
import strawberry_django
from strawberry import ID
from core.graphql.filter_mixins import BaseFilterMixin
if TYPE_CHECKING:
from netbox.graphql.filter_lookups import TreeNodeFilter
from .filters import ContactAssignmentFilter, TenantFilter, TenantGroupFilter
@@ -18,14 +16,14 @@ __all__ = (
@dataclass
class ContactFilterMixin(BaseFilterMixin):
class ContactFilterMixin:
contacts: Annotated['ContactAssignmentFilter', strawberry.lazy('tenancy.graphql.filters')] | None = (
strawberry_django.filter_field()
)
@dataclass
class TenancyFilterMixin(BaseFilterMixin):
class TenancyFilterMixin:
tenant: Annotated['TenantFilter', strawberry.lazy('tenancy.graphql.filters')] | None = (
strawberry_django.filter_field()
)

View File

@@ -5,12 +5,9 @@ import strawberry_django
from strawberry.scalars import ID
from strawberry_django import BaseFilterLookup, FilterLookup
from core.graphql.filter_mixins import ChangeLogFilterMixin
from extras.graphql.filter_mixins import CustomFieldsFilterMixin, TagsFilterMixin
from netbox.graphql.filter_mixins import (
NestedGroupModelFilterMixin,
OrganizationalModelFilterMixin,
PrimaryModelFilterMixin,
from netbox.graphql.filters import (
ChangeLoggedModelFilter, NestedGroupModelFilter, OrganizationalModelFilter, PrimaryModelFilter,
)
from tenancy import models
from .filter_mixins import ContactFilterMixin
@@ -57,7 +54,7 @@ __all__ = (
@strawberry_django.filter_type(models.Tenant, lookups=True)
class TenantFilter(PrimaryModelFilterMixin, ContactFilterMixin):
class TenantFilter(ContactFilterMixin, PrimaryModelFilter):
name: FilterLookup[str] | None = strawberry_django.filter_field()
slug: FilterLookup[str] | None = strawberry_django.filter_field()
group: Annotated['TenantGroupFilter', strawberry.lazy('tenancy.graphql.filters')] | None = (
@@ -136,7 +133,7 @@ class TenantFilter(PrimaryModelFilterMixin, ContactFilterMixin):
@strawberry_django.filter_type(models.TenantGroup, lookups=True)
class TenantGroupFilter(OrganizationalModelFilterMixin):
class TenantGroupFilter(OrganizationalModelFilter):
parent: Annotated['TenantGroupFilter', strawberry.lazy('tenancy.graphql.filters')] | None = (
strawberry_django.filter_field()
)
@@ -150,7 +147,7 @@ class TenantGroupFilter(OrganizationalModelFilterMixin):
@strawberry_django.filter_type(models.Contact, lookups=True)
class ContactFilter(PrimaryModelFilterMixin):
class ContactFilter(PrimaryModelFilter):
name: FilterLookup[str] | None = strawberry_django.filter_field()
title: FilterLookup[str] | None = strawberry_django.filter_field()
phone: FilterLookup[str] | None = strawberry_django.filter_field()
@@ -166,19 +163,19 @@ class ContactFilter(PrimaryModelFilterMixin):
@strawberry_django.filter_type(models.ContactRole, lookups=True)
class ContactRoleFilter(OrganizationalModelFilterMixin):
class ContactRoleFilter(OrganizationalModelFilter):
pass
@strawberry_django.filter_type(models.ContactGroup, lookups=True)
class ContactGroupFilter(NestedGroupModelFilterMixin):
class ContactGroupFilter(NestedGroupModelFilter):
parent: Annotated['ContactGroupFilter', strawberry.lazy('tenancy.graphql.filters')] | None = (
strawberry_django.filter_field()
)
@strawberry_django.filter_type(models.ContactAssignment, lookups=True)
class ContactAssignmentFilter(CustomFieldsFilterMixin, TagsFilterMixin, ChangeLogFilterMixin):
class ContactAssignmentFilter(CustomFieldsFilterMixin, TagsFilterMixin, ChangeLoggedModelFilter):
object_type: Annotated['ContentTypeFilter', strawberry.lazy('core.graphql.filters')] | None = (
strawberry_django.filter_field()
)

View File

@@ -5,7 +5,7 @@ import strawberry
import strawberry_django
from strawberry_django import DatetimeFilterLookup, FilterLookup
from core.graphql.filter_mixins import BaseObjectTypeFilterMixin
from netbox.graphql.filters import BaseModelFilter
from users import models
__all__ = (
@@ -17,13 +17,13 @@ __all__ = (
@strawberry_django.filter_type(models.Group, lookups=True)
class GroupFilter(BaseObjectTypeFilterMixin):
class GroupFilter(BaseModelFilter):
name: FilterLookup[str] | None = strawberry_django.filter_field()
description: FilterLookup[str] | None = strawberry_django.filter_field()
@strawberry_django.filter_type(models.User, lookups=True)
class UserFilter(BaseObjectTypeFilterMixin):
class UserFilter(BaseModelFilter):
username: FilterLookup[str] | None = strawberry_django.filter_field()
first_name: FilterLookup[str] | None = strawberry_django.filter_field()
last_name: FilterLookup[str] | None = strawberry_django.filter_field()
@@ -36,7 +36,7 @@ class UserFilter(BaseObjectTypeFilterMixin):
@strawberry_django.filter_type(models.Owner, lookups=True)
class OwnerFilter(BaseObjectTypeFilterMixin):
class OwnerFilter(BaseModelFilter):
name: FilterLookup[str] | None = strawberry_django.filter_field()
description: FilterLookup[str] | None = strawberry_django.filter_field()
group: Annotated['OwnerGroupFilter', strawberry.lazy('users.graphql.filters')] | None = (
@@ -49,6 +49,6 @@ class OwnerFilter(BaseObjectTypeFilterMixin):
@strawberry_django.filter_type(models.OwnerGroup, lookups=True)
class OwnerGroupFilter(BaseObjectTypeFilterMixin):
class OwnerGroupFilter(BaseModelFilter):
name: FilterLookup[str] | None = strawberry_django.filter_field()
description: FilterLookup[str] | None = strawberry_django.filter_field()

View File

@@ -3,11 +3,9 @@ from typing import Annotated, TYPE_CHECKING
import strawberry
import strawberry_django
from strawberry import ID
from strawberry.scalars import ID
from strawberry_django import FilterLookup
from netbox.graphql.filter_mixins import NetBoxModelFilterMixin
if TYPE_CHECKING:
from .filters import VirtualMachineFilter
@@ -17,7 +15,7 @@ __all__ = (
@dataclass
class VMComponentFilterMixin(NetBoxModelFilterMixin):
class VMComponentFilterMixin:
virtual_machine: Annotated['VirtualMachineFilter', strawberry.lazy('virtualization.graphql.filters')] | None = (
strawberry_django.filter_field()
)

View File

@@ -7,11 +7,8 @@ from strawberry_django import BaseFilterLookup, FilterLookup
from dcim.graphql.filter_mixins import InterfaceBaseFilterMixin, RenderConfigFilterMixin, ScopedFilterMixin
from extras.graphql.filter_mixins import ConfigContextFilterMixin
from netbox.graphql.filter_mixins import (
ImageAttachmentFilterMixin,
OrganizationalModelFilterMixin,
PrimaryModelFilterMixin,
)
from netbox.graphql.filter_mixins import ImageAttachmentFilterMixin
from netbox.graphql.filters import NetBoxModelFilter, OrganizationalModelFilter, PrimaryModelFilter
from tenancy.graphql.filter_mixins import ContactFilterMixin, TenancyFilterMixin
from virtualization import models
from virtualization.graphql.filter_mixins import VMComponentFilterMixin
@@ -40,7 +37,7 @@ __all__ = (
@strawberry_django.filter_type(models.Cluster, lookups=True)
class ClusterFilter(ContactFilterMixin, ScopedFilterMixin, TenancyFilterMixin, PrimaryModelFilterMixin):
class ClusterFilter(ContactFilterMixin, ScopedFilterMixin, TenancyFilterMixin, PrimaryModelFilter):
name: FilterLookup[str] | None = strawberry_django.filter_field()
type: Annotated['ClusterTypeFilter', strawberry.lazy('virtualization.graphql.filters')] | None = (
strawberry_django.filter_field()
@@ -59,14 +56,14 @@ class ClusterFilter(ContactFilterMixin, ScopedFilterMixin, TenancyFilterMixin, P
@strawberry_django.filter_type(models.ClusterGroup, lookups=True)
class ClusterGroupFilter(ContactFilterMixin, OrganizationalModelFilterMixin):
class ClusterGroupFilter(ContactFilterMixin, OrganizationalModelFilter):
vlan_groups: Annotated['VLANGroupFilter', strawberry.lazy('ipam.graphql.filters')] | None = (
strawberry_django.filter_field()
)
@strawberry_django.filter_type(models.ClusterType, lookups=True)
class ClusterTypeFilter(OrganizationalModelFilterMixin):
class ClusterTypeFilter(OrganizationalModelFilter):
pass
@@ -77,7 +74,7 @@ class VirtualMachineFilter(
RenderConfigFilterMixin,
ConfigContextFilterMixin,
TenancyFilterMixin,
PrimaryModelFilterMixin,
PrimaryModelFilter,
):
name: FilterLookup[str] | None = strawberry_django.filter_field()
site: Annotated['SiteFilter', strawberry.lazy('dcim.graphql.filters')] | None = strawberry_django.filter_field()
@@ -138,7 +135,7 @@ class VirtualMachineFilter(
@strawberry_django.filter_type(models.VMInterface, lookups=True)
class VMInterfaceFilter(VMComponentFilterMixin, InterfaceBaseFilterMixin):
class VMInterfaceFilter(InterfaceBaseFilterMixin, VMComponentFilterMixin, NetBoxModelFilter):
ip_addresses: Annotated['IPAddressFilter', strawberry.lazy('ipam.graphql.filters')] | None = (
strawberry_django.filter_field()
)
@@ -163,7 +160,7 @@ class VMInterfaceFilter(VMComponentFilterMixin, InterfaceBaseFilterMixin):
@strawberry_django.filter_type(models.VirtualDisk, lookups=True)
class VirtualDiskFilter(VMComponentFilterMixin):
class VirtualDiskFilter(VMComponentFilterMixin, NetBoxModelFilter):
size: Annotated['IntegerLookup', strawberry.lazy('netbox.graphql.filter_lookups')] | None = (
strawberry_django.filter_field()
)

View File

@@ -5,9 +5,10 @@ import strawberry_django
from strawberry.scalars import ID
from strawberry_django import BaseFilterLookup, FilterLookup
from core.graphql.filter_mixins import BaseObjectTypeFilterMixin, ChangeLogFilterMixin
from extras.graphql.filter_mixins import CustomFieldsFilterMixin, TagsFilterMixin
from netbox.graphql.filter_mixins import NetBoxModelFilterMixin, OrganizationalModelFilterMixin, PrimaryModelFilterMixin
from netbox.graphql.filters import (
ChangeLoggedModelFilter, NetBoxModelFilter, OrganizationalModelFilter, PrimaryModelFilter,
)
from tenancy.graphql.filter_mixins import ContactFilterMixin, TenancyFilterMixin
from vpn import models
@@ -32,14 +33,12 @@ __all__ = (
@strawberry_django.filter_type(models.TunnelGroup, lookups=True)
class TunnelGroupFilter(OrganizationalModelFilterMixin):
class TunnelGroupFilter(OrganizationalModelFilter):
pass
@strawberry_django.filter_type(models.TunnelTermination, lookups=True)
class TunnelTerminationFilter(
BaseObjectTypeFilterMixin, CustomFieldsFilterMixin, TagsFilterMixin, ChangeLogFilterMixin
):
class TunnelTerminationFilter(CustomFieldsFilterMixin, TagsFilterMixin, ChangeLoggedModelFilter):
tunnel: Annotated['TunnelFilter', strawberry.lazy('vpn.graphql.filters')] | None = strawberry_django.filter_field()
tunnel_id: ID | None = strawberry_django.filter_field()
role: BaseFilterLookup[Annotated['TunnelTerminationRoleEnum', strawberry.lazy('vpn.graphql.enums')]] | None = (
@@ -59,7 +58,7 @@ class TunnelTerminationFilter(
@strawberry_django.filter_type(models.Tunnel, lookups=True)
class TunnelFilter(TenancyFilterMixin, PrimaryModelFilterMixin):
class TunnelFilter(TenancyFilterMixin, PrimaryModelFilter):
name: FilterLookup[str] | None = strawberry_django.filter_field()
status: BaseFilterLookup[Annotated['TunnelStatusEnum', strawberry.lazy('vpn.graphql.enums')]] | None = (
strawberry_django.filter_field()
@@ -85,7 +84,7 @@ class TunnelFilter(TenancyFilterMixin, PrimaryModelFilterMixin):
@strawberry_django.filter_type(models.IKEProposal, lookups=True)
class IKEProposalFilter(PrimaryModelFilterMixin):
class IKEProposalFilter(PrimaryModelFilter):
name: FilterLookup[str] | None = strawberry_django.filter_field()
authentication_method: (
BaseFilterLookup[Annotated['AuthenticationMethodEnum', strawberry.lazy('vpn.graphql.enums')]] | None
@@ -114,7 +113,7 @@ class IKEProposalFilter(PrimaryModelFilterMixin):
@strawberry_django.filter_type(models.IKEPolicy, lookups=True)
class IKEPolicyFilter(PrimaryModelFilterMixin):
class IKEPolicyFilter(PrimaryModelFilter):
name: FilterLookup[str] | None = strawberry_django.filter_field()
version: BaseFilterLookup[Annotated['IKEVersionEnum', strawberry.lazy('vpn.graphql.enums')]] | None = (
strawberry_django.filter_field()
@@ -129,7 +128,7 @@ class IKEPolicyFilter(PrimaryModelFilterMixin):
@strawberry_django.filter_type(models.IPSecProposal, lookups=True)
class IPSecProposalFilter(PrimaryModelFilterMixin):
class IPSecProposalFilter(PrimaryModelFilter):
name: FilterLookup[str] | None = strawberry_django.filter_field()
encryption_algorithm: (
BaseFilterLookup[Annotated['EncryptionAlgorithmEnum', strawberry.lazy('vpn.graphql.enums')]] | None
@@ -155,7 +154,7 @@ class IPSecProposalFilter(PrimaryModelFilterMixin):
@strawberry_django.filter_type(models.IPSecPolicy, lookups=True)
class IPSecPolicyFilter(PrimaryModelFilterMixin):
class IPSecPolicyFilter(PrimaryModelFilter):
name: FilterLookup[str] | None = strawberry_django.filter_field()
proposals: Annotated['IPSecProposalFilter', strawberry.lazy('vpn.graphql.filters')] | None = (
strawberry_django.filter_field()
@@ -166,7 +165,7 @@ class IPSecPolicyFilter(PrimaryModelFilterMixin):
@strawberry_django.filter_type(models.IPSecProfile, lookups=True)
class IPSecProfileFilter(PrimaryModelFilterMixin):
class IPSecProfileFilter(PrimaryModelFilter):
name: FilterLookup[str] | None = strawberry_django.filter_field()
mode: BaseFilterLookup[Annotated['IPSecModeEnum', strawberry.lazy('vpn.graphql.enums')]] | None = (
strawberry_django.filter_field()
@@ -182,7 +181,7 @@ class IPSecProfileFilter(PrimaryModelFilterMixin):
@strawberry_django.filter_type(models.L2VPN, lookups=True)
class L2VPNFilter(ContactFilterMixin, TenancyFilterMixin, PrimaryModelFilterMixin):
class L2VPNFilter(ContactFilterMixin, TenancyFilterMixin, PrimaryModelFilter):
name: FilterLookup[str] | None = strawberry_django.filter_field()
slug: FilterLookup[str] | None = strawberry_django.filter_field()
type: BaseFilterLookup[Annotated['L2VPNTypeEnum', strawberry.lazy('vpn.graphql.enums')]] | None = (
@@ -206,7 +205,7 @@ class L2VPNFilter(ContactFilterMixin, TenancyFilterMixin, PrimaryModelFilterMixi
@strawberry_django.filter_type(models.L2VPNTermination, lookups=True)
class L2VPNTerminationFilter(NetBoxModelFilterMixin):
class L2VPNTerminationFilter(NetBoxModelFilter):
l2vpn: Annotated['L2VPNFilter', strawberry.lazy('vpn.graphql.filters')] | None = strawberry_django.filter_field()
l2vpn_id: ID | None = strawberry_django.filter_field()
assigned_object_type: Annotated['ContentTypeFilter', strawberry.lazy('core.graphql.filters')] | None = (

View File

@@ -5,18 +5,16 @@ import strawberry
import strawberry_django
from strawberry_django import FilterLookup
from core.graphql.filter_mixins import BaseFilterMixin
if TYPE_CHECKING:
from .enums import *
__all__ = (
'WirelessAuthenticationBaseFilterMixin',
'WirelessAuthenticationFilterMixin',
)
@dataclass
class WirelessAuthenticationBaseFilterMixin(BaseFilterMixin):
class WirelessAuthenticationFilterMixin:
auth_type: Annotated['WirelessAuthTypeEnum', strawberry.lazy('wireless.graphql.enums')] | None = (
strawberry_django.filter_field()
)

View File

@@ -6,10 +6,11 @@ from strawberry.scalars import ID
from strawberry_django import BaseFilterLookup, FilterLookup
from dcim.graphql.filter_mixins import ScopedFilterMixin
from netbox.graphql.filter_mixins import DistanceFilterMixin, PrimaryModelFilterMixin, NestedGroupModelFilterMixin
from netbox.graphql.filter_mixins import DistanceFilterMixin
from netbox.graphql.filters import PrimaryModelFilter, NestedGroupModelFilter
from tenancy.graphql.filter_mixins import TenancyFilterMixin
from wireless import models
from .filter_mixins import WirelessAuthenticationBaseFilterMixin
from .filter_mixins import WirelessAuthenticationFilterMixin
if TYPE_CHECKING:
from dcim.graphql.filters import InterfaceFilter
@@ -24,16 +25,16 @@ __all__ = (
@strawberry_django.filter_type(models.WirelessLANGroup, lookups=True)
class WirelessLANGroupFilter(NestedGroupModelFilterMixin):
class WirelessLANGroupFilter(NestedGroupModelFilter):
pass
@strawberry_django.filter_type(models.WirelessLAN, lookups=True)
class WirelessLANFilter(
WirelessAuthenticationBaseFilterMixin,
WirelessAuthenticationFilterMixin,
ScopedFilterMixin,
TenancyFilterMixin,
PrimaryModelFilterMixin
PrimaryModelFilter
):
ssid: FilterLookup[str] | None = strawberry_django.filter_field()
status: BaseFilterLookup[Annotated['WirelessLANStatusEnum', strawberry.lazy('wireless.graphql.enums')]] | None = (
@@ -49,10 +50,10 @@ class WirelessLANFilter(
@strawberry_django.filter_type(models.WirelessLink, lookups=True)
class WirelessLinkFilter(
WirelessAuthenticationBaseFilterMixin,
WirelessAuthenticationFilterMixin,
DistanceFilterMixin,
TenancyFilterMixin,
PrimaryModelFilterMixin
PrimaryModelFilter
):
interface_a: Annotated['InterfaceFilter', strawberry.lazy('dcim.graphql.filters')] | None = (
strawberry_django.filter_field()