10711 Add Scope to WirelessLAN

This commit is contained in:
Arthur Hanson 2024-10-28 11:43:30 -07:00
parent 4d01069f25
commit 06c8a92423
8 changed files with 81 additions and 14 deletions

View File

@ -43,3 +43,7 @@ The security cipher used to apply wireless authentication. Options include:
### Pre-Shared Key
The security key configured on each client to grant access to the secured wireless LAN. This applies only to certain authentication types.
### Scope
The [region](../dcim/region.md), [site](../dcim/site.md), [site group](../dcim/sitegroup.md) or [location](../dcim/location.md) with which this wireless LAN is associated.

View File

@ -34,12 +34,14 @@ class WirelessLANSerializer(NetBoxModelSerializer):
tenant = TenantSerializer(nested=True, required=False, allow_null=True)
auth_type = ChoiceField(choices=WirelessAuthTypeChoices, required=False, allow_blank=True)
auth_cipher = ChoiceField(choices=WirelessAuthCipherChoices, required=False, allow_blank=True)
scope_id = serializers.IntegerField(allow_null=True, required=False, default=None)
scope = serializers.SerializerMethodField(read_only=True)
class Meta:
model = WirelessLAN
fields = [
'id', 'url', 'display_url', 'display', 'ssid', 'description', 'group', 'status', 'vlan', 'tenant',
'auth_type', 'auth_cipher', 'auth_psk', 'description', 'comments', 'tags', 'custom_fields',
'id', 'url', 'display_url', 'display', 'ssid', 'description', 'group', 'status', 'vlan', 'scope_type', 'scope_id',
'tenant', 'auth_type', 'auth_cipher', 'auth_psk', 'description', 'comments', 'tags', 'custom_fields',
'created', 'last_updated',
]
brief_fields = ('id', 'url', 'display', 'ssid', 'description')

View File

@ -2,6 +2,7 @@ import django_filters
from django.db.models import Q
from dcim.choices import LinkStatusChoices
from dcim.filtersets import ScopedFilterSet
from dcim.models import Interface
from ipam.models import VLAN
from netbox.filtersets import OrganizationalModelFilterSet, NetBoxModelFilterSet
@ -43,7 +44,7 @@ class WirelessLANGroupFilterSet(OrganizationalModelFilterSet):
fields = ('id', 'name', 'slug', 'description')
class WirelessLANFilterSet(NetBoxModelFilterSet, TenancyFilterSet):
class WirelessLANFilterSet(NetBoxModelFilterSet, ScopedFilterSet, TenancyFilterSet):
group_id = TreeNodeMultipleChoiceFilter(
queryset=WirelessLANGroup.objects.all(),
field_name='group',
@ -74,7 +75,7 @@ class WirelessLANFilterSet(NetBoxModelFilterSet, TenancyFilterSet):
class Meta:
model = WirelessLAN
fields = ('id', 'ssid', 'auth_psk', 'description')
fields = ('id', 'ssid', 'auth_psk', 'scope_id', 'description')
def search(self, queryset, name, value):
if not value.strip():

View File

@ -1,16 +1,19 @@
from django import forms
from django.contrib.contenttypes.models import ContentType
from django.utils.translation import gettext_lazy as _
from dcim.choices import LinkStatusChoices
from dcim.models import Site
from ipam.models import VLAN
from netbox.choices import *
from netbox.forms import NetBoxModelBulkEditForm
from tenancy.models import Tenant
from utilities.forms import add_blank_choice
from utilities.forms.fields import CommentField, DynamicModelChoiceField
from utilities.forms.fields import CommentField, ContentTypeChoiceField, DynamicModelChoiceField
from utilities.forms.rendering import FieldSet
from utilities.forms.widgets import HTMXSelect
from wireless.choices import *
from wireless.constants import SSID_MAX_LENGTH
from wireless.constants import WIRELESSLAN_SCOPE_TYPES, SSID_MAX_LENGTH
from wireless.models import *
__all__ = (
@ -79,6 +82,19 @@ class WirelessLANBulkEditForm(NetBoxModelBulkEditForm):
required=False,
label=_('Pre-shared key')
)
scope_type = ContentTypeChoiceField(
queryset=ContentType.objects.filter(model__in=WIRELESSLAN_SCOPE_TYPES),
widget=HTMXSelect(method='post', attrs={'hx-select': '#form_fields'}),
required=False,
label=_('Scope type')
)
scope = DynamicModelChoiceField(
label=_('Scope'),
queryset=Site.objects.none(), # Initial queryset
required=False,
disabled=True,
selector=True
)
description = forms.CharField(
label=_('Description'),
max_length=200,
@ -89,10 +105,11 @@ class WirelessLANBulkEditForm(NetBoxModelBulkEditForm):
model = WirelessLAN
fieldsets = (
FieldSet('group', 'ssid', 'status', 'vlan', 'tenant', 'description'),
FieldSet('scope_type', 'scope', name=_('Scope')),
FieldSet('auth_type', 'auth_cipher', 'auth_psk', name=_('Authentication')),
)
nullable_fields = (
'ssid', 'group', 'vlan', 'tenant', 'description', 'auth_type', 'auth_cipher', 'auth_psk', 'comments',
'ssid', 'group', 'vlan', 'tenant', 'description', 'auth_type', 'auth_cipher', 'auth_psk', 'scope', 'comments',
)

View File

@ -1,3 +1,4 @@
from django.contrib.contenttypes.models import ContentType
from django.utils.translation import gettext_lazy as _
from dcim.choices import LinkStatusChoices
@ -6,8 +7,9 @@ from ipam.models import VLAN
from netbox.choices import *
from netbox.forms import NetBoxModelImportForm
from tenancy.models import Tenant
from utilities.forms.fields import CSVChoiceField, CSVModelChoiceField, SlugField
from utilities.forms.fields import CSVChoiceField, CSVContentTypeField, CSVModelChoiceField, SlugField
from wireless.choices import *
from wireless.constants import WIRELESSLAN_SCOPE_TYPES
from wireless.models import *
__all__ = (
@ -71,13 +73,21 @@ class WirelessLANImportForm(NetBoxModelImportForm):
required=False,
help_text=_('Authentication cipher')
)
scope_type = CSVContentTypeField(
queryset=ContentType.objects.filter(model__in=WIRELESSLAN_SCOPE_TYPES),
required=False,
label=_('Scope type (app & model)')
)
class Meta:
model = WirelessLAN
fields = (
'ssid', 'group', 'status', 'vlan', 'tenant', 'auth_type', 'auth_cipher', 'auth_psk', 'description',
'comments', 'tags',
'ssid', 'group', 'status', 'vlan', 'tenant', 'auth_type', 'auth_cipher', 'auth_psk', 'scope_type', 'scope_id',
'description', 'comments', 'tags',
)
labels = {
'scope_id': 'Scope ID',
}
class WirelessLinkImportForm(NetBoxModelImportForm):

View File

@ -1,3 +1,4 @@
from django.contrib.contenttypes.models import ContentType
from django.forms import PasswordInput
from django.utils.translation import gettext_lazy as _
@ -5,8 +6,10 @@ from dcim.models import Device, Interface, Location, Site
from ipam.models import VLAN
from netbox.forms import NetBoxModelForm
from tenancy.forms import TenancyForm
from utilities.forms.fields import CommentField, DynamicModelChoiceField, SlugField
from utilities.forms.fields import CommentField, ContentTypeChoiceField, DynamicModelChoiceField, SlugField
from utilities.forms.rendering import FieldSet, InlineFields
from utilities.forms.widgets import HTMXSelect
from wireless.constants import WIRELESSLAN_SCOPE_TYPES
from wireless.models import *
__all__ = (
@ -47,10 +50,24 @@ class WirelessLANForm(TenancyForm, NetBoxModelForm):
selector=True,
label=_('VLAN')
)
scope_type = ContentTypeChoiceField(
queryset=ContentType.objects.filter(model__in=WIRELESSLAN_SCOPE_TYPES),
widget=HTMXSelect(),
required=False,
label=_('Scope type')
)
scope = DynamicModelChoiceField(
label=_('Scope'),
queryset=Site.objects.none(), # Initial queryset
required=False,
disabled=True,
selector=True
)
comments = CommentField()
fieldsets = (
FieldSet('ssid', 'group', 'vlan', 'status', 'description', 'tags', name=_('Wireless LAN')),
FieldSet('scope_type', 'scope', name=_('Scope')),
FieldSet('tenant_group', 'tenant', name=_('Tenancy')),
FieldSet('auth_type', 'auth_cipher', 'auth_psk', name=_('Authentication')),
)
@ -59,7 +76,7 @@ class WirelessLANForm(TenancyForm, NetBoxModelForm):
model = WirelessLAN
fields = [
'ssid', 'group', 'status', 'vlan', 'tenant_group', 'tenant', 'auth_type', 'auth_cipher', 'auth_psk',
'description', 'comments', 'tags',
'scope_type', 'description', 'comments', 'tags',
]
widgets = {
'auth_psk': PasswordInput(

View File

@ -1,4 +1,4 @@
from typing import Annotated, List
from typing import Annotated, List, Union
import strawberry
import strawberry_django
@ -38,6 +38,15 @@ class WirelessLANType(NetBoxObjectType):
interfaces: List[Annotated["InterfaceType", strawberry.lazy('dcim.graphql.types')]]
@strawberry_django.field
def scope(self) -> Annotated[Union[
Annotated["LocationType", strawberry.lazy('dcim.graphql.types')],
Annotated["RegionType", strawberry.lazy('dcim.graphql.types')],
Annotated["SiteGroupType", strawberry.lazy('dcim.graphql.types')],
Annotated["SiteType", strawberry.lazy('dcim.graphql.types')],
], strawberry.union("WirelessLANScopeType")] | None:
return self.scope
@strawberry_django.type(
models.WirelessLink,

View File

@ -51,6 +51,13 @@ class WirelessLANTable(TenancyColumnsMixin, NetBoxTable):
status = columns.ChoiceFieldColumn(
verbose_name=_('Status'),
)
scope_type = columns.ContentTypeColumn(
verbose_name=_('Scope Type'),
)
scope = tables.Column(
verbose_name=_('Scope'),
linkify=True
)
interface_count = tables.Column(
verbose_name=_('Interfaces')
)
@ -65,7 +72,7 @@ class WirelessLANTable(TenancyColumnsMixin, NetBoxTable):
model = WirelessLAN
fields = (
'pk', 'ssid', 'group', 'status', 'tenant', 'tenant_group', 'vlan', 'interface_count', 'auth_type',
'auth_cipher', 'auth_psk', 'description', 'comments', 'tags', 'created', 'last_updated',
'auth_cipher', 'auth_psk', 'scope', 'scope_type', 'description', 'comments', 'tags', 'created', 'last_updated',
)
default_columns = ('pk', 'ssid', 'group', 'status', 'description', 'vlan', 'auth_type', 'interface_count')