Skip to content

Commit b122a82

Browse files
committed
refactor(models): Centralize ACL rule validation
Moves ACL rule validation logic from forms to model methods to ensure consistent enforcement across all usages. This improves maintainability and eliminates redundant validation code.
1 parent fa218f8 commit b122a82

File tree

2 files changed

+87
-78
lines changed

2 files changed

+87
-78
lines changed

netbox_acls/forms/models.py

Lines changed: 0 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -43,13 +43,6 @@
4343
# Sets a standard help_text value to be used by the various classes for acl index
4444
help_text_acl_rule_index = "Determines the order of the rule in the ACL processing. AKA Sequence Number."
4545

46-
# Sets a standard error message for ACL rules with an action of remark, but no remark set.
47-
error_message_no_remark = "Action is set to remark, you MUST add a remark."
48-
# Sets a standard error message for ACL rules with an action of remark, but no source_prefix is set.
49-
error_message_action_remark_source_prefix_set = "Action is set to remark, Source Prefix CANNOT be set."
50-
# Sets a standard error message for ACL rules with an action not set to remark, but no remark is set.
51-
error_message_remark_without_action_remark = "CANNOT set remark unless action is set to remark."
52-
5346

5447
class AccessListForm(NetBoxModelForm):
5548
"""
@@ -545,35 +538,6 @@ class Meta:
545538
),
546539
}
547540

548-
def clean(self):
549-
"""
550-
Validates form inputs before submitting:
551-
- Check if action set to remark, but no remark set.
552-
- Check if action set to remark, but source_prefix set.
553-
- Check remark set, but action not set to remark.
554-
"""
555-
super().clean()
556-
cleaned_data = self.cleaned_data
557-
error_message = {}
558-
559-
action = cleaned_data.get("action")
560-
remark = cleaned_data.get("remark")
561-
source_prefix = cleaned_data.get("source_prefix")
562-
563-
if action == "remark":
564-
# Check if action set to remark, but no remark set.
565-
if not remark:
566-
error_message["remark"] = [error_message_no_remark]
567-
# Check if action set to remark, but source_prefix set.
568-
if source_prefix:
569-
error_message["source_prefix"] = [error_message_action_remark_source_prefix_set]
570-
# Check remark set, but action not set to remark.
571-
elif remark:
572-
error_message["remark"] = [error_message_remark_without_action_remark]
573-
574-
if error_message:
575-
raise ValidationError(error_message)
576-
577541

578542
class ACLExtendedRuleForm(NetBoxModelForm):
579543
"""
@@ -651,45 +615,3 @@ class Meta:
651615
),
652616
"source_ports": help_text_acl_rule_logic,
653617
}
654-
655-
def clean(self):
656-
"""
657-
Validates form inputs before submitting:
658-
- Check if action set to remark, but no remark set.
659-
- Check if action set to remark, but source_prefix set.
660-
- Check if action set to remark, but source_ports set.
661-
- Check if action set to remark, but destination_prefix set.
662-
- Check if action set to remark, but destination_ports set.
663-
- Check if action set to remark, but protocol set.
664-
- Check remark set, but action not set to remark.
665-
"""
666-
super().clean()
667-
cleaned_data = self.cleaned_data
668-
error_message = {}
669-
670-
action = cleaned_data.get("action")
671-
remark = cleaned_data.get("remark")
672-
source_prefix = cleaned_data.get("source_prefix")
673-
source_ports = cleaned_data.get("source_ports")
674-
destination_prefix = cleaned_data.get("destination_prefix")
675-
destination_ports = cleaned_data.get("destination_ports")
676-
protocol = cleaned_data.get("protocol")
677-
678-
if action == "remark":
679-
if not remark:
680-
error_message["remark"] = [error_message_no_remark]
681-
if source_prefix:
682-
error_message["source_prefix"] = [error_message_action_remark_source_prefix_set]
683-
if source_ports:
684-
error_message["source_ports"] = ["Action is set to remark, Source Ports CANNOT be set."]
685-
if destination_prefix:
686-
error_message["destination_prefix"] = ["Action is set to remark, Destination Prefix CANNOT be set."]
687-
if destination_ports:
688-
error_message["destination_ports"] = ["Action is set to remark, Destination Ports CANNOT be set."]
689-
if protocol:
690-
error_message["protocol"] = ["Action is set to remark, Protocol CANNOT be set."]
691-
elif remark:
692-
error_message["remark"] = [error_message_remark_without_action_remark]
693-
694-
if error_message:
695-
raise ValidationError(error_message)

netbox_acls/models/access_list_rules.py

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
"""
44

55
from django.contrib.postgres.fields import ArrayField
6+
from django.core.exceptions import ValidationError
67
from django.db import models
78
from django.urls import reverse
89
from django.utils.translation import gettext_lazy as _
@@ -17,6 +18,29 @@
1718
"ACLExtendedRule",
1819
)
1920

21+
# Error message when the action is 'remark', but no remark is provided.
22+
ERROR_MESSAGE_NO_REMARK = _("When the action is 'remark', a remark is required.")
23+
24+
# Error message when the action is 'remark', but the source_prefix is set.
25+
ERROR_MESSAGE_ACTION_REMARK_SOURCE_PREFIX_SET = _("When the action is 'remark', the Source Prefix must not be set.")
26+
27+
# Error message when the action is 'remark', but the source_ports are set.
28+
ERROR_MESSAGE_ACTION_REMARK_SOURCE_PORTS_SET = _("When the action is 'remark', Source Ports must not be set.")
29+
30+
# Error message when the action is 'remark', but the destination_prefix is set.
31+
ERROR_MESSAGE_ACTION_REMARK_DESTINATION_PREFIX_SET = _(
32+
"When the action is 'remark', the Destination Prefix must not be set."
33+
)
34+
35+
# Error message when the action is 'remark', but the destination_ports are set.
36+
ERROR_MESSAGE_ACTION_REMARK_DESTINATION_PORTS_SET = _("When the action is 'remark', Destination Ports must not be set.")
37+
38+
# Error message when the action is 'remark', but the protocol is set.
39+
ERROR_MESSAGE_ACTION_REMARK_PROTOCOL_SET = _("When the action is 'remark', Protocol must not be set.")
40+
41+
# Error message when a remark is provided, but the action is not set to 'remark'.
42+
ERROR_MESSAGE_REMARK_WITHOUT_ACTION_REMARK = _("A remark cannot be set unless the action is 'remark'.")
43+
2044

2145
class ACLRule(NetBoxModel):
2246
"""
@@ -111,6 +135,31 @@ class Meta(ACLRule.Meta):
111135
verbose_name = _("ACL Standard Rule")
112136
verbose_name_plural = _("ACL Standard Rules")
113137

138+
def clean(self):
139+
"""
140+
Validate the ACL Standard Rule inputs.
141+
142+
If the action is 'remark', then the remark field must be provided (non-empty),
143+
and the source_prefix field must be empty.
144+
Conversely, if the remark field is provided, the action must be set to 'remark'.
145+
"""
146+
147+
super().clean()
148+
errors = {}
149+
150+
# Validate that only the remark field is filled
151+
if self.action == ACLRuleActionChoices.ACTION_REMARK:
152+
if not self.remark:
153+
errors["remark"] = ERROR_MESSAGE_NO_REMARK
154+
if self.source_prefix:
155+
errors["source_prefix"] = ERROR_MESSAGE_ACTION_REMARK_SOURCE_PREFIX_SET
156+
# Validate that the action is "remark", when the remark field is provided
157+
elif self.remark:
158+
errors["remark"] = ERROR_MESSAGE_REMARK_WITHOUT_ACTION_REMARK
159+
160+
if errors:
161+
raise ValidationError(errors)
162+
114163

115164
class ACLExtendedRule(ACLRule):
116165
"""
@@ -174,5 +223,43 @@ class Meta(ACLRule.Meta):
174223
verbose_name = _("ACL Extended Rule")
175224
verbose_name_plural = _("ACL Extended Rules")
176225

226+
def clean(self):
227+
"""
228+
Validate the ACL Extended Rule inputs.
229+
230+
When the action is 'remark', the remark field must be provided (non-empty),
231+
and the following fields must be empty:
232+
- source_prefix
233+
- source_ports
234+
- destination_prefix
235+
- destination_ports
236+
- protocol
237+
238+
Conversely, if a remark is provided, the action must be set to 'remark'.
239+
"""
240+
super().clean()
241+
errors = {}
242+
243+
# Validate that only the remark field is filled
244+
if self.action == ACLRuleActionChoices.ACTION_REMARK:
245+
if not self.remark:
246+
errors["remark"] = ERROR_MESSAGE_NO_REMARK
247+
if self.source_prefix:
248+
errors["source_prefix"] = ERROR_MESSAGE_ACTION_REMARK_SOURCE_PREFIX_SET
249+
if self.source_ports:
250+
errors["source_ports"] = ERROR_MESSAGE_ACTION_REMARK_SOURCE_PORTS_SET
251+
if self.destination_prefix:
252+
errors["destination_prefix"] = ERROR_MESSAGE_ACTION_REMARK_DESTINATION_PREFIX_SET
253+
if self.destination_ports:
254+
errors["destination_ports"] = ERROR_MESSAGE_ACTION_REMARK_DESTINATION_PORTS_SET
255+
if self.protocol:
256+
errors["protocol"] = ERROR_MESSAGE_ACTION_REMARK_PROTOCOL_SET
257+
# Validate that the action is "remark", when the remark field is provided
258+
elif self.remark:
259+
errors["remark"] = ERROR_MESSAGE_REMARK_WITHOUT_ACTION_REMARK
260+
261+
if errors:
262+
raise ValidationError(errors)
263+
177264
def get_protocol_color(self):
178265
return ACLProtocolChoices.colors.get(self.protocol)

0 commit comments

Comments
 (0)