Skip to content

Commit 871b0b7

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 6a2ee86 commit 871b0b7

File tree

2 files changed

+88
-78
lines changed

2 files changed

+88
-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: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,10 @@
44

55
from django.apps import apps
66
from django.contrib.postgres.fields import ArrayField
7+
from django.core.exceptions import ValidationError
78
from django.db import models
89
from django.urls import reverse
10+
from django.utils.translation import gettext_lazy as _
911
from netbox.models import NetBoxModel
1012

1113
from ..choices import ACLProtocolChoices, ACLRuleActionChoices, ACLTypeChoices
@@ -17,6 +19,29 @@
1719
"ACLExtendedRule",
1820
)
1921

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

2146
class ACLRule(NetBoxModel):
2247
"""
@@ -112,6 +137,31 @@ class Meta(ACLRule.Meta):
112137
verbose_name = "ACL Standard Rule"
113138
verbose_name_plural = "ACL Standard Rules"
114139

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

116166
class ACLExtendedRule(ACLRule):
117167
"""
@@ -176,3 +226,41 @@ class Meta(ACLRule.Meta):
176226

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

0 commit comments

Comments
 (0)