From 6cf4c5fe276601dbdaeded2cd3bc9efd5eb319a9 Mon Sep 17 00:00:00 2001
From: candifloss <candifloss@candifloss.cc>
Date: Thu, 13 Feb 2025 02:24:33 +0530
Subject: [PATCH] Cleaner code for config validation

---
 functions/validate_config.py | 147 ++++++++++++++++++++---------------
 1 file changed, 84 insertions(+), 63 deletions(-)

diff --git a/functions/validate_config.py b/functions/validate_config.py
index 253c578..19c7f7a 100644
--- a/functions/validate_config.py
+++ b/functions/validate_config.py
@@ -1,76 +1,97 @@
 import re
 from datetime import datetime
 
+def _validate_number(attrib, attrib_name):
+    """Validate number-specific attributes."""
+    if attrib.min and not _is_int(attrib.min):
+        return False
+    if attrib.max and not _is_int(attrib.max):
+        return False
+    if attrib.min and attrib.max and int(attrib.max) < int(attrib.min):
+        return False
+    if attrib.default_val and not _is_int(attrib.default_val):
+        return False
+    if attrib.default_val:
+        if attrib.min and int(attrib.default_val) < int(attrib.min):
+            return False
+        if attrib.max and int(attrib.default_val) > int(attrib.max):
+            return False
+    return True
+
+def _validate_date(attrib, attrib_name):
+    """Validate date-specific attributes."""
+    if attrib.min and not _is_date(attrib.min):
+        return False
+    if attrib.max and not _is_date(attrib.max):
+        return False
+    if attrib.min and attrib.max and datetime.strptime(attrib.max, "%Y-%m-%d") < datetime.strptime(attrib.min, "%Y-%m-%d"):
+        return False
+    if attrib.default_val and not _is_date(attrib.default_val):
+        return False
+    if attrib.default_val:
+        if attrib.min and datetime.strptime(attrib.default_val, "%Y-%m-%d") < datetime.strptime(attrib.min, "%Y-%m-%d"):
+            return False
+        if attrib.max and datetime.strptime(attrib.default_val, "%Y-%m-%d") > datetime.strptime(attrib.max, "%Y-%m-%d"):
+            return False
+    return True
+
+def _validate_text(attrib, attrib_name):
+    """Validate text-specific attributes."""
+    if attrib.min or attrib.max or attrib.auto_increment or attrib.options:
+        return False
+    if attrib.default_val and attrib.regex and not re.match(attrib.regex, str(attrib.default_val)):
+        return False
+    return True
+
+def _validate_select(attrib, attrib_name):
+    """Validate select-specific attributes."""
+    if not attrib.options:
+        return False
+    if attrib.default_val and attrib.default_val not in attrib.options:
+        return False
+    return True
+
+def _is_int(value):
+    """Check if a value is a valid integer."""
+    try:
+        int(value)
+        return True
+    except (ValueError, TypeError):
+        return False
+
+def _is_date(value):
+    """Check if a value is a valid date in YYYY-MM-DD format."""
+    try:
+        datetime.strptime(value, "%Y-%m-%d")
+        return True
+    except (ValueError, TypeError):
+        return False
+
 # Validate the configuration file to ensure all attributes are properly defined.
 def validate_config(item_attributes):
     for attrib_name, attrib in item_attributes.items():
-        # Check for required fields
+        # Validate display_name and html_input_type
         if not attrib.display_name:
             return f"Missing display name for attribute '{attrib_name}'."
         if not attrib.html_input_type:
             return f"Missing input type for attribute '{attrib_name}'."
-        elif attrib.html_input_type not in ["text", "number", "date", "select"]:
+        if attrib.html_input_type not in ["text", "number", "date", "select"]:
             return f"Invalid input type for attribute '{attrib_name}'."
-        elif attrib.html_input_type =="number":       # Validate numbers
-            if attrib.min:
-                try:
-                    min_val = int(attrib.min)
-                except:
-                    return f"Min value for {attrib_name} must be a valid number."
-            if attrib.max:
-                try:
-                    max_val = int(attrib.max)
-                except:
-                    return f"Max value for {attrib_name} must be a valid number."
-            if attrib.min and attrib.max and max_val < min_val:
-                return f"Max value must greater than min value for attribute '{attrib_name}'"
-            if attrib.default_val:
-                try:
-                    def_val = int(attrib.default_val)
-                except:
-                    return f"Default value for {attrib_name} must be a valid number."
-                if attrib.min and def_val < attrib.min:
-                    return f"Default value for {attrib_name} must be a greater or equal to min value."
-                if attrib.max and def_val > attrib.max:
-                    return f"Default value for {attrib_name} must be a less or equal to max value."
-        elif attrib.html_input_type =="date":       # Validate dates
-            if attrib.min:
-                try:
-                    min_val = datetime.strptime(attrib.min, "%Y-%m-%d")
-                except:
-                    return f"Min value for {attrib_name} must be a valid date in YYYY-MM-DD format."
-            if attrib.max:
-                try:
-                    max_val = datetime.strptime(attrib.max, "%Y-%m-%d")
-                except:
-                    return f"Max value for {attrib_name} must be a valid date in YYYY-MM-DD format."
-            if attrib.min and attrib.max and max_val < min_val:
-                return f"Max value must greater than min value for attribute '{attrib_name}'"
-            if attrib.default_val:
-                try:
-                    def_val = datetime.strptime(attrib.default_val, "%Y-%m-%d")
-                except:
-                    return f"Default value for {attrib_name} must be a valid date in YYYY-MM-DD format."
-                if attrib.min and def_val < attrib.min:
-                    return f"Default value for {attrib_name} must be a greater or equal to min value."
-                if attrib.max and def_val > attrib.max:
-                    return f"Default value for {attrib_name} must be a less or equal to max value."
-        elif attrib.html_input_type =="text":       # Validate text types
-            if attrib.min or attrib.max or attrib.auto_increment or attrib.options:
-                return f"Text attribute {attrib_name} can't have min, max, auto_increment, or options."
-            if attrib.default_val:
-                try:
-                    def_val = str(attrib.default_val)
-                    if attrib.regex and not re.match(attrib.regex, def_val):
-                        return f"Default value for {attrib_name} is invalid. Allowed pattern: {attrib.regex}."
-                except:
-                    return f"Unexpected default value for text attribute '{attrib_name}.'"
-        elif attrib.html_input_type == "select":    # Validate selection menu types
-            if not attrib.options:
-                return f"Selection missing options for attribute '{attrib_name}'."
-            if attrib.default_val and attrib.default_val not in attrib.options:
-                return f"Default value for '{attrib_name}' must be in the options."
-                
+
+        # Validate min, max, and default values based on input type
+        if attrib.html_input_type == "number":
+            if not _validate_number(attrib, attrib_name):
+                return f"Invalid number configuration for attribute '{attrib_name}'."
+        elif attrib.html_input_type == "date":
+            if not _validate_date(attrib, attrib_name):
+                return f"Invalid date configuration for attribute '{attrib_name}'."
+        elif attrib.html_input_type == "text":
+            if not _validate_text(attrib, attrib_name):
+                return f"Invalid text configuration for attribute '{attrib_name}'."
+        elif attrib.html_input_type == "select":
+            if not _validate_select(attrib, attrib_name):
+                return f"Invalid select configuration for attribute '{attrib_name}'."
+
         # Validate min and max values
         if (attrib.min or attrib.max) and attrib.html_input_type not in ['number', 'date']:
             return f"'{attrib_name}' must be of type 'number' or 'date' to have min or max values."
@@ -81,5 +102,5 @@ def validate_config(item_attributes):
                 return f"Invalid reference attribute '{attrib.compareto[1]}' for comparison in attribute '{attrib_name}'."
             if attrib.compareto[0] not in ["lt", "gt", "le", "ge", "eq"]:
                 return f"Invalid comparison operator for attribute '{attrib_name}'. Valid operators are: lt, gt, le, ge, eq."
-
+    # Return "Ok" if everything is valid, otherwise return an error message.
     return "Ok"
\ No newline at end of file