@@ -176,43 +176,63 @@ def clean(self):
176176 error_message = {}
177177 if self .errors .get ("name" ):
178178 return cleaned_data
179+
179180 name = cleaned_data .get ("name" )
180181 acl_type = cleaned_data .get ("type" )
181- device = cleaned_data .get ("device" )
182- virtual_chassis = cleaned_data .get ("virtual_chassis" )
183- virtual_machine = cleaned_data .get ("virtual_machine" )
184182
185183 # Check if more than one host type selected.
186- if (
187- (device and virtual_chassis )
188- or (device and virtual_machine )
189- or (virtual_chassis and virtual_machine )
190- ):
184+ host_types = self .get_host_types ()
185+
186+ # Check if no hosts selected.
187+ self .validate_host_types (host_types )
188+
189+ host_type , host = host_types [0 ]
190+
191+ # Check if duplicate entry.
192+ self .validate_duplicate_entry (name , host_type , host , error_message )
193+ # Check if Access List has no existing rules before change the Access List's type.
194+ self .validate_acl_type_change (acl_type , error_message )
195+
196+ if error_message :
197+ raise forms .ValidationError (error_message )
198+
199+ return cleaned_data
200+
201+ def get_host_types (self ):
202+ """
203+ Get host type assigned to the Access List.
204+ """
205+ device = self .cleaned_data .get ("device" )
206+ virtual_chassis = self .cleaned_data .get ("virtual_chassis" )
207+ virtual_machine = self .cleaned_data .get ("virtual_machine" )
208+ host_types = [
209+ ("device" , device ),
210+ ("virtual_chassis" , virtual_chassis ),
211+ ("virtual_machine" , virtual_machine ),
212+ ]
213+ return [x for x in host_types if x [1 ]]
214+
215+ def validate_host_types (self , host_types ):
216+ """
217+ Check if more than one host type selected.
218+ """
219+ if len (host_types ) > 1 :
191220 raise forms .ValidationError (
192221 "Access Lists must be assigned to one host (either a device, virtual chassis or virtual machine) at a time." ,
193222 )
194223 # Check if no hosts selected.
195- if not device and not virtual_chassis and not virtual_machine :
224+ if not host_types :
196225 raise forms .ValidationError (
197226 "Access Lists must be assigned to a device, virtual chassis or virtual machine." ,
198227 )
199228
200- if device :
201- host_type = "device"
202- existing_acls = AccessList .objects .filter (name = name , device = device ).exists ()
203- elif virtual_machine :
204- host_type = "virtual_machine"
205- existing_acls = AccessList .objects .filter (
206- name = name ,
207- virtual_machine = virtual_machine ,
208- ).exists ()
209- else :
210- host_type = "virtual_chassis"
211- existing_acls = AccessList .objects .filter (
212- name = name ,
213- virtual_chassis = virtual_chassis ,
214- ).exists ()
215-
229+ def validate_duplicate_entry (self , name , host_type , host , error_message ):
230+ """
231+ Check if duplicate entry. (Because of GFK.)
232+ """
233+ existing_acls = AccessList .objects .filter (
234+ name = name , ** {host_type : host }
235+ ).exists ()
216236 # Check if duplicate entry.
217237 if (
218238 "name" in self .changed_data or host_type in self .changed_data
@@ -224,7 +244,11 @@ def clean(self):
224244 host_type : [error_same_acl_name ],
225245 "name" : [error_same_acl_name ],
226246 }
227- # Check if Access List has no existing rules before change the Access List's type.
247+
248+ def validate_acl_type_change (self , acl_type , error_message ):
249+ """
250+ Check if Access List has no existing rules before change the Access List's type.
251+ """
228252 if self .instance .pk and (
229253 (
230254 acl_type == ACLTypeChoices .TYPE_EXTENDED
@@ -242,8 +266,6 @@ def clean(self):
242266 if error_message :
243267 raise forms .ValidationError (error_message )
244268
245- return cleaned_data
246-
247269 def save (self , * args , ** kwargs ):
248270 """
249271 Set assigned object
@@ -412,19 +434,19 @@ def clean(self):
412434 assigned_object_type : [error_acl_not_assigned_to_host ],
413435 host_type : [error_acl_not_assigned_to_host ],
414436 }
415- # Check for duplicate entry.
416- if ACLInterfaceAssignment .objects .filter (
417- access_list = access_list ,
418- assigned_object_id = assigned_object_id ,
419- assigned_object_type = assigned_object_type_id ,
420- direction = direction ,
421- ).exists ():
422- error_duplicate_entry = "An ACL with this name is already associated to this interface & direction."
423- error_message |= {
424- "access_list" : [error_duplicate_entry ],
425- "direction" : [error_duplicate_entry ],
426- assigned_object_type : [error_duplicate_entry ],
427- }
437+ ## Check for duplicate entry.
438+ # if ACLInterfaceAssignment.objects.filter(
439+ # access_list=access_list,
440+ # assigned_object_id=assigned_object_id,
441+ # assigned_object_type=assigned_object_type_id,
442+ # direction=direction,
443+ # ).exists():
444+ # error_duplicate_entry = "An ACL with this name is already associated to this interface & direction."
445+ # error_message |= {
446+ # "access_list": [error_duplicate_entry],
447+ # "direction": [error_duplicate_entry],
448+ # assigned_object_type: [error_duplicate_entry],
449+ # }
428450 # Check that the interface does not have an existing ACL applied in the direction already.
429451 if ACLInterfaceAssignment .objects .filter (
430452 assigned_object_id = assigned_object_id ,
@@ -454,17 +476,15 @@ def save(self, *args, **kwargs):
454476
455477
456478class BaseACLRuleForm (NetBoxModelForm ):
457- """
458- GUI form to add or edit Access List Rules to be inherited by other classes
459- """
479+ """GUI form to add or edit Access List Rules to be inherited by other classes"""
460480
461481 access_list = DynamicModelChoiceField (
462482 queryset = AccessList .objects .all (),
463483 query_params = {
464484 "type" : ACLTypeChoices .TYPE_STANDARD ,
465485 },
466486 help_text = mark_safe (
467- "<b>*Note:</b> This field will only display Standard ACLs." ,
487+ "<b>*Note:</b> This field will only display Standard ACLs."
468488 ),
469489 label = "Access List" ,
470490 )
@@ -481,9 +501,7 @@ class BaseACLRuleForm(NetBoxModelForm):
481501 )
482502
483503 class Meta :
484- """
485- Defines the Model and fields to be used by the form.
486- """
504+ """Defines the Model and fields to be used by the form."""
487505
488506 model = ACLStandardRule
489507 fields = (
@@ -496,11 +514,14 @@ class Meta:
496514 "description" ,
497515 )
498516 help_texts = {
499- "index" : HELP_TEXT_ACL_RULE_INDEX ,
500517 "action" : HELP_TEXT_ACL_ACTION ,
518+ "destination_ports" : HELP_TEXT_ACL_RULE_LOGIC ,
519+ "index" : HELP_TEXT_ACL_RULE_INDEX ,
520+ "protocol" : HELP_TEXT_ACL_RULE_LOGIC ,
501521 "remark" : mark_safe (
502- "<b>*Note:</b> CANNOT be set if source prefix OR action is set." ,
522+ "<b>*Note:</b> CANNOT be set if action is not set to remark."
503523 ),
524+ "source_ports" : HELP_TEXT_ACL_RULE_LOGIC ,
504525 }
505526
506527 def clean (self ):
@@ -519,7 +540,6 @@ def clean(self):
519540 raise forms .ValidationError (error_message )
520541 return cleaned_data
521542
522-
523543 def _extracted_from_clean_20 (self , cleaned_data , error_message , rule_type ):
524544 """
525545 Validates form inputs before submitting:
@@ -537,13 +557,13 @@ def _extracted_from_clean_20(self, cleaned_data, error_message, rule_type):
537557 # Check if action set to remark, but source_prefix set.
538558 if cleaned_data .get ("source_prefix" ):
539559 error_message ["source_prefix" ] = [
540- ERROR_MESSAGE_ACTION_REMARK_SOURCE_PREFIX_SET ,
560+ ERROR_MESSAGE_ACTION_REMARK_SOURCE_PREFIX_SET
541561 ]
542562 if rule_type == "extended" :
543563 # Check if action set to remark, but source_ports set.
544564 if cleaned_data .get ("source_ports" ):
545565 error_message ["source_ports" ] = [
546- "Action is set to remark, Source Ports CANNOT be set." ,
566+ "Action is set to remark, Source Ports CANNOT be set."
547567 ]
548568 # Check if action set to remark, but destination_prefix set.
549569 if cleaned_data .get ("destination_prefix" ):
@@ -553,12 +573,12 @@ def _extracted_from_clean_20(self, cleaned_data, error_message, rule_type):
553573 # Check if action set to remark, but destination_ports set.
554574 if cleaned_data .get ("destination_ports" ):
555575 error_message ["destination_ports" ] = [
556- "Action is set to remark, Destination Ports CANNOT be set." ,
576+ "Action is set to remark, Destination Ports CANNOT be set."
557577 ]
558578 # Check if action set to remark, but protocol set.
559579 if cleaned_data .get ("protocol" ):
560580 error_message ["protocol" ] = [
561- "Action is set to remark, Protocol CANNOT be set." ,
581+ "Action is set to remark, Protocol CANNOT be set."
562582 ]
563583
564584
@@ -579,9 +599,7 @@ class ACLExtendedRuleForm(BaseACLRuleForm):
579599
580600 access_list = DynamicModelChoiceField (
581601 queryset = AccessList .objects .all (),
582- query_params = {
583- "type" : ACLTypeChoices .TYPE_EXTENDED ,
584- },
602+ query_params = {"type" : ACLTypeChoices .TYPE_EXTENDED },
585603 help_text = mark_safe (
586604 "<b>*Note:</b> This field will only display Extended ACLs." ,
587605 ),
@@ -597,15 +615,13 @@ class ACLExtendedRuleForm(BaseACLRuleForm):
597615 fieldsets = BaseACLRuleForm .fieldsets [:- 1 ] + (
598616 (
599617 "Rule Definition" ,
600- BaseACLRuleForm .fieldsets [- 1 ][1 ] + ("source_ports" , "destination_prefix" , "destination_ports" , "protocol" ),
618+ BaseACLRuleForm .fieldsets [- 1 ][1 ]
619+ + ("source_ports" , "destination_prefix" , "destination_ports" , "protocol" ),
601620 ),
602621 )
603622
604-
605623 class Meta :
606- """
607- Defines the Model and fields to be used by the form.
608- """
624+ """Defines the Model and fields to be used by the form."""
609625
610626 model = ACLExtendedRule
611627 fields = (
@@ -621,13 +637,3 @@ class Meta:
621637 "tags" ,
622638 "description" ,
623639 )
624- help_texts = {
625- "action" : HELP_TEXT_ACL_ACTION ,
626- "destination_ports" : HELP_TEXT_ACL_RULE_LOGIC ,
627- "index" : HELP_TEXT_ACL_RULE_INDEX ,
628- "protocol" : HELP_TEXT_ACL_RULE_LOGIC ,
629- "remark" : mark_safe (
630- "<b>*Note:</b> CANNOT be set if action is not set to remark." ,
631- ),
632- "source_ports" : HELP_TEXT_ACL_RULE_LOGIC ,
633- }
0 commit comments