diff --git a/app/models.py b/app/models.py index ab17530547f38d9239b0b061339c47eff71f14d0..80c80a21a04b0c9207f891d26cf4205e609230e7 100644 --- a/app/models.py +++ b/app/models.py @@ -32,6 +32,7 @@ from .plugins import FlaskUserPlugin from .validators import ( ICS_ID_RE, HOST_NAME_RE, + GROUP_NAME_RE, INTERFACE_NAME_RE, VLAN_NAME_RE, MAC_ADDRESS_RE, @@ -1169,6 +1170,20 @@ class AnsibleGroup(CreatedMixin, SearchableMixin, db.Model): check_parents(self) return child + @validates("name") + def validate_name(self, key, string): + """Ensure the name matches the required format""" + if string is None: + return None + # Force the string to lowercase + lower_string = string.lower() + if GROUP_NAME_RE.fullmatch(lower_string) is None: + raise ValidationError(f"Group name shall match {GROUP_NAME_RE.pattern}") + existing_group_name = AnsibleGroup.query.filter_by(name=lower_string).first() + if existing_group_name: + raise ValidationError("Group name matches an existing group") + return lower_string + @property def is_dynamic(self): return self.type != AnsibleGroupType.STATIC diff --git a/app/validators.py b/app/validators.py index d6b222158c9f84bc168ff920f53ad4978b7c49c5..e084d550b4725adca5c5a85f0ad24f7ed7b456a9 100644 --- a/app/validators.py +++ b/app/validators.py @@ -16,6 +16,7 @@ from wtforms import ValidationError, SelectField ICS_ID_RE = re.compile(r"^[A-Z]{3}[0-9]{3}$") HOST_NAME_RE = re.compile(r"^[a-z0-9\-]{2,24}$") +GROUP_NAME_RE = re.compile(r"^[a-z0-9\-\_]{2,50}$") # Interface name needs to be at least 5 characters more than the hostname (Every interface name have to start with the hostname) INTERFACE_NAME_RE = re.compile(r"^[a-z0-9\-]{2,29}$") VLAN_NAME_RE = re.compile(r"^[A-Za-z0-9\-]{3,25}$")