diff --git a/netbox_access_lists/forms.py b/netbox_access_lists/forms.py index cb18e37..1c969f7 100644 --- a/netbox_access_lists/forms.py +++ b/netbox_access_lists/forms.py @@ -1,5 +1,6 @@ from django import forms from django.core.exceptions import ValidationError +from django.utils.safestring import mark_safe from extras.models import Tag from ipam.models import Prefix @@ -8,6 +9,8 @@ from utilities.forms import CommentField, DynamicModelChoiceField, DynamicModelM from .models import AccessList, AccessListExtendedRule, AccessListActionChoices, AccessListProtocolChoices, AccessListTypeChoices, AccessListStandardRule +acl_rule_logic_help = mark_safe('*Note: CANNOT be set if remark is set.') + class AccessListForm(NetBoxModelForm): comments = CommentField() tags = DynamicModelMultipleChoiceField( @@ -15,9 +18,18 @@ class AccessListForm(NetBoxModelForm): required=False ) + fieldsets = [ + ('Access-List Details', ('name', 'device', 'type', 'default_action', 'tags')), + ] + class Meta: model = AccessList fields = ('name', 'device', 'type', 'default_action', 'comments', 'tags') + help_texts = { + 'default_action': 'The default behavior of the ACL.', + 'name': 'The name uniqueness per device is case insensitive.', + 'type': 'Sets the type of the ACL & its rules.', + } def clean(self): cleaned_data = super().clean() @@ -26,7 +38,7 @@ class AccessListForm(NetBoxModelForm): name = cleaned_data.get('name') device = cleaned_data.get('device') if ('name' in self.changed_data or 'device' in self.changed_data) and AccessList.objects.filter(name__iexact=name, device=device).exists(): - raise forms.ValidationError('An Access-List with this name is already associated to this device.') + raise forms.ValidationError('An ACL with this name (case insensitive) is already associated to this device.') return cleaned_data class AccessListFilterForm(NetBoxModelFilterSetForm): @@ -34,7 +46,7 @@ class AccessListFilterForm(NetBoxModelFilterSetForm): type = forms.MultipleChoiceField( choices=AccessListTypeChoices, required=False, - widget=StaticSelectMultiple() + widget=StaticSelectMultiple(), ) default_action = forms.MultipleChoiceField( choices=AccessListActionChoices, @@ -43,29 +55,46 @@ class AccessListFilterForm(NetBoxModelFilterSetForm): ) tag = TagFilterField(model) + fieldsets = ( + (None, ('q', 'tag')), + ('ACL Details', ('type', 'default_action')), + ) + class AccessListStandardRuleForm(NetBoxModelForm): access_list = DynamicModelChoiceField( queryset=AccessList.objects.all(), query_params={ 'type': 'standard' - } + }, + help_text=mark_safe('*Note: This field will only display Standard ACLs.'), + ) + source_prefix = DynamicModelChoiceField( + queryset=Prefix.objects.all(), + required=False, + help_text=acl_rule_logic_help, ) tags = DynamicModelMultipleChoiceField( queryset=Tag.objects.all(), required=False ) - source_prefix = DynamicModelChoiceField( - queryset=Prefix.objects.all(), - required=False - ) + fieldsets = ( + ('Access-List Details', ('access_list', 'index', 'tags')), + ('Rule Logic', ('remark', 'action', 'source_prefix')), + ) class Meta: model = AccessListStandardRule fields = ( - 'access_list', 'index', 'remark', 'action', 'tags', 'source_prefix', + 'access_list', 'index', 'remark', 'action', 'source_prefix', + 'tags', ) + help_texts = { + 'action': acl_rule_logic_help, + 'index': 'Determines the order of the rule in the ACL processing.', + 'remark': mark_safe('*Note: CANNOT be set if source prefix OR action is set.'), + } def clean(self): cleaned_data = super().clean() @@ -86,23 +115,29 @@ class AccessListStandardRuleFilterForm(NetBoxModelFilterSetForm): required=False, widget=StaticSelectMultiple() ) - index = forms.IntegerField( - required=False - ) tag = TagFilterField(model) + source_prefix = forms.ModelMultipleChoiceField( + queryset=Prefix.objects.all(), + required=False, + widget=StaticSelectMultiple() + ) action = forms.MultipleChoiceField( choices=AccessListActionChoices, required=False, widget=StaticSelectMultiple() ) - + fieldsets = ( + (None, ('q', 'tag')), + ('Rule Details', ('access_list', 'action', 'source_prefix',)), + ) class AccessListExtendedRuleForm(NetBoxModelForm): access_list = DynamicModelChoiceField( queryset=AccessList.objects.all(), query_params={ 'type': 'extended' - } + }, + help_text=mark_safe('*Note: This field will only display Extended ACLs.'), ) tags = DynamicModelMultipleChoiceField( queryset=Tag.objects.all(), @@ -110,20 +145,34 @@ class AccessListExtendedRuleForm(NetBoxModelForm): ) source_prefix = DynamicModelChoiceField( queryset=Prefix.objects.all(), - required=False + required=False, + help_text=acl_rule_logic_help, ) destination_prefix = DynamicModelChoiceField( queryset=Prefix.objects.all(), - required=False + required=False, + help_text=acl_rule_logic_help, + ) + fieldsets = ( + ('Access-List Details', ('access_list', 'index', 'tags')), + ('Rule Details', ('remark', 'action', 'source_prefix', 'source_ports', 'destination_prefix', 'destination_ports', 'protocol',)), ) - class Meta: model = AccessListExtendedRule fields = ( - 'access_list', 'index', 'remark', 'action', 'tags', 'source_prefix', - 'source_ports', 'destination_prefix', 'destination_ports', 'protocol' + 'access_list', 'index', 'remark', 'action', 'source_prefix', + 'source_ports', 'destination_prefix', 'destination_ports', 'protocol', + 'tags' ) + help_texts = { + 'action': acl_rule_logic_help, + 'destination_ports': acl_rule_logic_help, + 'index': 'Determines the order of the rule in the ACL processing.', + 'protocol': acl_rule_logic_help, + 'remark': mark_safe('*Note: CANNOT be set if a prefix, port, OR action is set.'), + 'source_ports': acl_rule_logic_help, + } def clean(self): cleaned_data = super().clean() @@ -161,8 +210,23 @@ class AccessListExtendedRuleFilterForm(NetBoxModelFilterSetForm): required=False, widget=StaticSelectMultiple() ) + source_prefix = forms.ModelMultipleChoiceField( + queryset=Prefix.objects.all(), + required=False, + widget=StaticSelectMultiple() + ) + desintation_prefix = forms.ModelMultipleChoiceField( + queryset=Prefix.objects.all(), + required=False, + widget=StaticSelectMultiple() + ) protocol = forms.MultipleChoiceField( choices=AccessListProtocolChoices, required=False, widget=StaticSelectMultiple() ) + + fieldsets = ( + (None, ('q', 'tag')), + ('Rule Details', ('access_list', 'action', 'source_prefix', 'desintation_prefix', 'protocol')), + )